프로그래머스의  2레벨이 시작되었다...

 

2레벨 초입이라 그런지, 풀이가 어느정도 가능할 것으로 보이는 문제이다.

 

 

n은 2 이상으로 주어지기 때문에 시작을 2로 잡아보았다.

 

 

이렇게 배열을 하나 만들어서  Fn-2 Fn-1 Fn 을 표현해 주었다.

 

first[2] 를 반환하여 정답을 만드는것

 

 

문제 그대로를 집어넣은듯한 반복문을 작성해주었다.

 

1회 반복될 때 마다,

first[1],first[2] =>  first[0] first[1] 이 되고

first[2] = first[0] +first[1] 로 갱신되는 형태

  

 

shift를 사용해서 배열의 값을 한칸 씩 땡기고 first[2] 를 다시 만들어 주는것도 같은 결과일 것이다.

shift() 의 시간복잡도는  O(n) 인데,  이 경우 항상 length =3 에서 진행되기 때문에 3의 시간 복잡도가 된다.

 

하지만 first[0]  과  firtst[1] 을 각각 수정하면  복잡도가 1+1 이기 때문에  n당 n회 이득이다..ㅋㅋ...

 

크헉

 

 

 

조건이 더 있었다.

Int 한계 때문에 생긴 조건일까?

 

 

마찬가지로 조건도 그대로 넣어버린다

 

 

 

 

 

지금 타이밍에 풀기 좋은 문제가 등장 !

 

 

겉보기에는 엄청 쉬운 문제인것 처럼 느껴지지만, 이 문제의 핵심은

 

 

문제에서 주어지는 today, terms, privacies 가 정제되지 않는 형태로 주어진다.

완전 쌩 문자열 이라는것이다.

 

그러나 나는 주어진 문자열을 원하는 형태로 가공하는것에 약하다 !

일단 처음 계획은

date 에 해당하는 부분은 숫자열로 바꿔준다 !

 

terms 이 문제인데, 아무래도 객체 형태로 만드는것이 좋을것 같다 !

{ A : 6 , B : 12 , C: 3 }  이렇게 만들어주면 !

키값을 참고하여 숫자를 어떻게 해먹을 수 있겠다.

 

기초적인 내용이라고 생각되지만...

어째선지, 잘 모르기 때문에 일단 킹st.js 로 !!

 

 

 

가장 기초적인 객체의 사용방법 !

object .  key = value   로, 한번에 빈 객체에 key 와 value를 집어넣을 수 있다 .

 

obj[key] = value 형태를 통해, 원하는 key값을 변수를 사용해 넣어줄 수 있다. 

 

다시 문제로 돌아와서, terms 를 { A : 6 , B : 12 , C: 3 } 로 만들어보자.

 

이렇게 하면

{ A : 6 , B : 12 , C: 3 }  를 만들수  .. 가 없다

 

terms 의 값이 전부 문자열이기 때문이다.

+를 사용하던지, Numer(term)  을 해주던지 하여 숫자열로 변환후 value에 넣어주자.

 

 

그 다음은, 날짜를 계산해야 하는데, 아주 원시적인 방법을 사용하기로 했다. 

일단은 말이다 !!

보기만 해도 점수가 깎여나갈것 같은 방법이지만 당장은 가능하다는게 중요

month + year*12 + day/100  이것으로 날짜를 비교할 수 있게 되었다..(흠흠)

 

 이제, 두 방법을 활용 하여

문제에서 제시한 privacies 를 흠흠↑ 의 형태로 바꾸어 비교하기만 하면된다.

 

 

방법은 사실 상 동일하다. 

privacies의 앞부분인 2021.05.02 를 위와 같은 이상한 소수점으로 만들고

여기에 A를  앞에서만든 termType에서 찾아서 value를 더해주면 된다. 

 

그리고 반복문을 통해, 값을 비교해주면 끝 .. !

 

 

 

 

 

 

햄버거 만들기

햄버거는 쌓아서 만든다는 특징이 있다... 쌓는다 !

 

이 문제는, stack 의 풀이를 사용할 것을 유도하고 있다.

 

 last in , first Out 

마지막에 들어온 데이터가 가장 먼저 빠져온다. 

그렇기 때문에, 스택 구조는 시간 복잡도 면에서 유리하다.

데이터가 위쪽에 쌓이는 형태이기 때문에 PUSH (O)n 

나가는 것도 맨 위쪽이기 때문에 POP (O)n 이기 때문이다.

 

 

 

우선 stack 배열을 만들고, 

주어진 배열 ingredient 를 순회하며 앞에서 부터 하나씩 쌓는다. Stack !

 

 

하나쌓을 때 마다, stack 배열의  뒤에서부터 4개의 값을 조사한다. 

1231 일 경우, 햄버거를 만들 수 있으므로, answer ++ 를 해주고,

조립한 햄버거 재료를 제외한다.

다시 반복문으로 돌아가 다음 재료 stack에 추가한다 ... 반복

 

이렇게 하면, 문제의 핵심인

 

1231이 아니어서 지나친 재료가  다시 1231의 재료가 될 수 있는 부분 

12  1231 31    << 와 같은 경우 또한 정상적으로 조립 대상에 포함할 수 있다.

12 1231 에서 answer ++  후 1231 제거

12 3 

12 3 1  에서 answer ++  후 1231 제거

 

 

 

 

 

코드 카타에 사용할 이미지

 

 

오랜만에 못풀진 않을듯 ? 하는 문제가 나왔다.

 

문제의 포인트는 2가지로 설명할 수 있다.

 

1. 소문자 알파벳으로 이루어진 문자열 s가 , index 의 int만큼 밀려서 다음 알파벳으로 출력됨

=> 이는 아스키 코드 의 문제와 같은 부류이고,

 

2. skip 내에 있는 알파벳은 기본적으로 건너 뛰게 된다.

=> 이 부분이 해당 문제의 난이도를 올리는 부분이다.

 

우선, 아스키 코드 대신 저번처럼 알파벳 문자열과 index를 사용하기로 했다.

 

소문자만 존재하므로, 

 

전체 소문자 문자열을 arr에 할당해주고,

(왜 변수명을 arr로 했지?)

 

반복문을 통해 arr배열.. 아 아니라 문자열에서 s[i] 에 해당하는 알파벳의 인덱스를 뽑아오면, 

s와 동일한 값을 우선 추출할 수 있다.

s.length 만큼 반복시 s와 동일한 값이 나오게 됨

 

문제는  skip 부분인데, 문자열 arr 을 만들면서 생각이 난게 있다. 

skip에 해당하는 알파벳을 다 없애버리면 그게 skip이 아닐까?

 

skip 에 해당하는 알파벳은 조건없이 항상 건너 뛰게 되므로, 사실상 없는것과 같다.

 

 

프로그래머스 치고,  상당히 친절한 조건까지 붙어있다.

 

 

 

반복문과 replace 메서드 를 이용해 하나하나 날려주기로 했다.

뭔가 한번에 날릴 방법이 없을까 생각했지만, 찾아내진 못했다.

 

skip 에 해당하는 문자가 도려내졌다. 

 

이제, 위의 방법에서 주어진 index만큼을 더해서 반환하면 된...

 

 

 

당연히 안된다

 

z 이후를 참조하려 하면 undefined 이기 때문이다  

 

 

arr.length 만큼 나눠서, 나머지에 해당하는 부분으로 적용하면,

arr.length 이하인 경우에 대해서는 기존처럼 작동하고,

넘어가면 자연스럽게 0부터 시작하는 형태가 완성된다.

 

 

 

 

 

매일 1시간씩 코드 카타 시간을 갖는데, 이 문제를 푸는데 3일이 소요됐다.

 

문제를 이해하고, 어떤 방법으로 구현할까 생각했는데

 

keymap 에 해당되는 문자열을

 

{A : 1, B:2, C: 3} 과 같은 형태로 만들어 키와 밸류를 이용해 문제를 풀어나가면 

될것 같다는 생각을 했다.

 

검색을 통해 알아 본 결과, 위와 같이 배열의 데이터를 

키와 밸류로 각각 나누어 객체 형태로 저장하는 방법을 해시(Hash) 라고 한다 !

 

배열과의 차이는,

 

배열은

0~ 으로 시작하는, 순번을 알려주는 index 와  index의 값인 요소(element) 로 구성된다면,

 

객체는

임의의 key : 임의의 값 value  로 구성이 되기 때문에, 

 key 에 해당하는 부분에 숫자는 물론 문자열 또한 들어갈 수 있기 때문에 자유롭다 !

 

이 둘의 차이는 마치,

관계형 데이터 베이스 (배열) 와 비관계형 데이터 베이스 (객체) 와 비슷하다고 생각된다.

 

일반적으로 JS 에서는 해시 형태를 만들기 위해 그의 단짝인 Map이 사용된다.

 

 

 

라고 하는 내용을 찾을 수 있었으나, 

 

한번에 이해하고 사용하기엔 어려웠기 때문에,

일단은 원시적인 방법으로 해시를 구현해보고자 했다.

 

 

여기까지 오기가 가장 힘들었다

 

객체로 선언된 keykey에, 이중 반복문을 통해

key에 해당하는 keymap의 문자열, value에 해당 문자열의 index 를 넣는 방식으로 만들었다.

 

이것은 사실상, map() 이 작동되는 방식을 반복문으로 표현한 것과 같다.

 

이제, targets 을 순회하며 일치하는 값을 더해주기만 하면 된다.

 

 

마찬가지로, 이중 반복문을 통해 몇 번째 index 에 있는 몇 번째 문자열인지를 참고하여

순회한다. 만약 key에 없는 문자를 한번이라도 마주친다면,

작성이 불가능한 문자열 이므로 -1을 반환하고 다음 i로 넘어간다.

 

이 때, break 를 하지 않는다면

sum= -1 이 되었지만  남은 j 반복문을 계속 진행하여 -1 에서 값이 변경될 여지가 생기게된다.

 

이 부분을 놓쳐서 꽤 긴 시간을 낭비했다.

( 기본으로 주어지는 테스트 케이스 에서는, sum= -1 이후에 변동되는 케이스가 없기 때문에 )

 

이를테면,

임의로 추가한 위의 테스트 케이스 에서,

2번째 targets 배열인 DADFA 를 보면, 

F가 작성이 불가능한 문자열 이므로 sum = -1 이 되었지만, break 가 없다면

F 다음 index인  A로 넘어가면서 A= +1 의 값을 받아 sum= 0 이 되어버리는 문제가 생기는 것이었다.

 

 

break ;  적용 이후로, 실패했던 테스트가 통과되며 정답처리가 되었다. 

 

 

상당히 골치아픈 문제가 나와서 글로 작성해 보았다.

이게 level 1 이라니...

 

얼핏보면 수월하게 풀 수 있을것 같은 문제지만 (그렇게 생각했었는데요...)

제한 사항을 보면 X와 Y의 길이가 최대 300만 으로 정해져 있으며,

이로 인해서 이중 for문 등을 사용하면 시간복잡도가 급증해 시간초과의 결과가 나오게 된다.

 

 

풀이 설계

 

1. X 와 Y 를 내림차 정렬을 한다.

2. X 와 Y를 맨 앞에서부터 비교하여 같을 경우 answer 에 추가

3. X[0] Y[0] 이 같지 않을 경우 둘 중 작은 값의 다음 index를 검사

4. "0" 의 결과와 "-1" 의 결과를 따로 리턴

 

늘 그렇지만, 이번에도 대단히 효율적이진 않을것 같은 풀이 방향이다.

내림차 정렬을 위한 sort 2회, X와 Y의 값을 비교하기 위한 반복문이 기본적으로 필요하기 때문.

 

 

풀이 시작

 

    X= [...X].sort((a,b) => b-a)
    Y= [...Y].sort((a,b) => b-a)

시작은 역순정렬 부터 한다. 큰 값으로 정렬하여 비교하면 유리할 거라는 생각이었으나,

사실, sort 과정 자체가 시간복잡도를 많이 잡아먹어버린다.

어쨌든 그렇게 설계했기 때문에 이렇게 시작해 보도록 하자.

 

이 과정에서 저번 알고리즘 때 배웠던 [...str] 을 이용한 배열화를 사용해 보았다.

 

그 후, X와 Y를 비교하기 위해 반복문을 사용해야 하는데, 

while 문을 사용하기로 했다. 

 

    let i = 0;
    let j = 0;
    while ( X.length > i && Y.length > j) {
        if ( X[i] === Y[j]) {
            answer += X[i]
            j++ 
            i++
        }

X 와 Y의 끝까지 비교를 해야할 것으로 예상되기 때문에, 위 같이 조건을 주었고,

가장 중요한 X[i] ===Y[j] 일 경우 answer에 추가하는 것 까지는 어렵지 않게 진행되었다.

 

 

잘못된 풀이..?

그 전에, 잠깐 뻘짓을 했던 과정을 살펴보자면

    while ( X.length > i && Y.length > j) {
        if ( X[0] === Y[0]) {
            answer += X[0]
            X= X.substring(1)
            Y= Y.substring(1)
        }

위처럼 동일한 조건으로 진행하지만, i j 를 통해 다음 index로 넘어가는것이 아니라,

.substirng(1) 을 통해  X,Y의 0번의 index만 검사하도록 진행해 보려는 시도를 했었는데, 

굳이 substring 이라는 메서드가 사용된다는 점 때문에 폐기 되었다.

 

시도했던 이유와 폐기한 이유??

 

substring 은 문자열의 0번째 ~를 제거하는 메서드이다. 

참조형이 아닌 기본형 타입의 string을 변조하는건 시간복잡도가 1회 일 것으로 예상을 했었으나,

기본적으로 substring() 의 시간 복잡도는 O(n) 에 해당했다.

글 마무리에 substring을 사용했을 때와, index 순번을 사용했을 때의 시간차이를 비교해보도록 하겠다.

 

 

자, 다시 풀이로 돌아와서, 이제 X[i] 와 Y[j] 가 다른 값일 경우만 처리하면 된다.

 

생각이 닿기는 좀 시간이 걸렸지만,

    while ( X.length > i && Y.length > j) {
        if ( X[i] === Y[j]) {
            answer += X[i]
            j++ 
            i++
        } else if (X[i] > Y[j]){
            i++          
        } else { 
            j++}
        
    }

X[i] 와 Y[j] 의  둘 중 큰 값을 비교해서 

큰 값을 가진쪽의 index 를++ 해서  다음 index를 참조하게 하면,

점점 값이 작아지며 서로 같은 값이 나올때 까지 넘어가게 된다.

 

마무리로, 

    if (answer[0] === "0" ) { return "0"}
    return answer === ""? "-1" : answer

"000000" 만 나온 경우와  일치하는값이 하나도 없을경우만 따로 빼주면 정답이 완성된다.

 

답 코드

function solution(X, Y) {
    var answer = '';
    
    X= [...X].sort((a,b) => b-a)
    Y= [...Y].sort((a,b) => b-a)
    let i = 0;
    let j = 0;
    while ( X.length > i && Y.length > j) {
        if ( X[i] === Y[j]) {
            answer += X[i]
            j++ 
            i++
        } else if (X[i] > Y[j]){
            i++          
        } else { 
            j++}
        
    }
    if (answer[0] === "0" ) { return "0"}
    return answer === ""? "-1" : answer
}

 앞서 말한것 처럼, sort와 반복문이 사용되며 결론적으로 그렇게 효율적인 코드는 아니게 되었다.

 

딱 봐도  11~ 15번 case 가 헬 구간 ( X,Y length가 길게 주어지는듯)

 

 

 

 

 

그렇다면, substirng 의 경우 얼마나 차이가 날까?

function solution(X, Y) {
    var answer = '';
    
    X= [...X].sort((a,b) => b-a).join('')
    Y= [...Y].sort((a,b) => b-a).join('')
    while ( X.length > 0 && Y.length > 0) {
        if ( X[0] === Y[0]) {
            answer += X[0]
            X= X.substring(1)
            Y= Y.substring(1)
        } else if (X[0] > Y[0]){
            X= X.substring(1)       
        } else {
            Y= Y.substring(1)}
        
    }
    if (answer[0] === "0" ) { return "0"}
    return answer === ""? "-1" : answer
}

.substirng(1) 이기 때문에 별로 차이가 없지 않을까 하는 생각에서 완성을 해 보았다.

 

 

유의미한 차이가 있다.

substirng(1) 이라고 해도 결코 상수의 처리시간이 걸리는건 아닌것으로 보인다.

물론 X 와 Y를 추가로 join 해주는 과정에서도 추가적인 시간이 소요됐겠지만 말이다.

 

대충 정리를 하자면 

11~15번 케이스에서 걸린 시간은 

기본 답 코드 ( X[i] Y[j] 로 비교) = 약 2300ms 가량 

두 번째 테스트 ( 기본 답 코드에서 X,Y를 join만 해준 경우)  = 약 2500ms 가량 (join에 걸리는 시간 대략적으로 확인)

세 번째 테스트 ( join 이후 substring을 통해 X[0] Y[0] 으로 비교) =  약 2800ms 가량 ( join과 substring에 걸리는 시간 확인)

 

 

당연히~~~~~

X[i] Y[j] 로 비교하는것이 빠르겠지만, 순전히 궁금증이 생겨나서 

테스트를 해 보게 되었다.

결론은.... 애초에 sort 가 제일 오래 걸리는듯 함 (ㅠ)

 

 

알고리즘 풀다 죽은 개발자가 때깔도 곱다

 

1. 문자열 내림차순으로 배치하기

 

간단하고 쉬워보이는 문제이다

이전에 풀었던 정수 내림차순으로 나열하기 와 같은 맥락이다

 

sort  정렬 시 대문자가 소문자 앞에 오던가 뒤에 오던가 헷갈리는 부분이 있긴한데...

해보면 알 것이다

function solution(s) {
    s= s.split('').sort();
    return s
}

 

대문자가 소문자보다 앞에 오기 때문에 다행이다.

이러면 여기서 역순 reverse 적용하고 join하면 끝이다

 

function solution(s) {
    s= s.split('').sort().reverse().join('');
    return s
}

 

 

 

2. 부족한 금액 계산하기

 

1회 이용시마다 기본 금액에 무려 100% 할증이 붙는 놀이공원이 되었다

 

내가 생각 한 방법은

반복문으로 count 까지의 총 요금을 구하고, 

소지금 money 에서 총 요금을 뺀 결과가 0 이상이면 0으로 출력,

음수면 (-) 부호만 떼줘서 출력 이다.

 

여기서, 음수 부호만 떼는법만 배워오면 될듯하다

 

Math.abs();   

=  () 내의 수가 음수일 경우 양수로 바꿔준다

 

function solution(price, money, count) {
    var answer = 0;
    for(var i = 1; i <= count ; i++) {
        answer += price * i
    }
    answer = money - answer >= 0 ? 0 : Math.abs(money- answer);
    return answer;
}

위에서 설명한 그대로의 코드가 되었다

 

상당히 부끄럽게도, Math.abs는 필요가 없었다

부족한 금액에 초점을 맞춘 나머지 -를 지워야 한다는 생각을 했는데,

 

애초에  money - answer 가 음수인 경우라면,  answer -money 를 하면 양수로 나오는 것이었다

    return money - answer >= 0 ? 0 : answer - money;

이렇게 !

 

 

 

3.  문자열 다루기 기본

 

 

갑자기 '기본' 이라는 문제가 튀어나온걸 보니

아직 못배운 영역이 나왔을것이 분명하다.

 

아니나 다를까, 간단해보이는 문제이지만 어떻게 해결해야 할 지 모르겠다.

길이 4 || 6 체크는 쉽겠지만, 문자열을 포함할때 true false를 나누는 법을 모르겠다

 

답을 알아내기 위해 검색을 하다가

 

parseInt();  를 활용하는 것을 보았다.

parseInt() 는 , 문자열을 숫자로 반환하는, 기존에 알고있던 함수이다.

 

여기서 중요한건, parseInt() 는 정확하게 

(숫자로 바꿀수 있는것) ~ (숫자로 바꿀 수 있는것) 까지만 반환한다.

즉 "a123" 처럼 알파벳으로 시작하는 경우 반환될 값이 없어  NaN 가 출력된다.

"123a456" 의 경우, 알파벳 a의 이전까지인 123 까지만 반환이 된다.

 

이 문제를 풀기 위한 핵심은

숫자 이외 불순물이 하나라도 있다면 기존의 값과 달라진다는 것이다.

"a123" == parseInt("a123")    ==> false 라는 말이다

이것으로 문자열을 포함하는지를 체크할 수 있다.

최선인지는 모르겠지만 말이다

 

function solution(s) {
    var answer = 0;
    if ( s.length == 6 || s.length ==4 ) {
        if ( s == parseInt(s)) { return true}
        else return false;
    }
        else return false;
    return answer;
}

 

쓰이지도 않은 answer 를 버리고 

조건문을 조금 깔끔하게 고치면

 

function solution(s) {
    if((s.length == 4 || s.length ==6) && (s == parseInt(s))) { return true}
     else return false;
}

 

 

를  삼항연산자로

function solution(s) {
    return (s.length ==4 || s.length == 6) && (s== parseInt(s)) ? true : false
}

 

이렇게 쓸 수 있다..

 

 

'사전캠프' 카테고리의 다른 글

28일차 - SQL 문제 풀이  (0) 2024.07.30
27일차 - 알고리즘 풀이  (0) 2024.07.29
25일차 - 알고리즘 풀이  (3) 2024.07.24
24일차 - 알고리즘 풀이  (1) 2024.07.23
23일차 - 알고리즘 풀이  (3) 2024.07.22

1. 가운데 글자 가져오기

 

s.length 가 짝수인 경우와

s.length 가 홀수인 경우를 구분해서 어찌 저찌 하면 될듯하다

function solution(s) {
    var sl = Math.floor(s.length/2)
    return s.length % 2 == 0 ? s[sl-1]+s[sl] : s[sl];
}

그다지 어려운 문제가 아니었으므로 자세한 내용은 생략한다

슬슬

홀수 짝수를 %2 =0  으로 구분하는것이 뭔가 좀 아쉽긴한데..

 

 

 

2. 수박수박수박...

가장 먼저 생각난 방법은

for문으로 n 까지 홀수짝수로 반복을 하면 될듯 하다

 

function solution(n) {
    var answer = '';
    for( var i = 0; i < n; i++) {
        answer = i % 2 == 0? answer + "수" : answer+"박" ;
    }
    return answer;
}

뭔가... 아쉬운 코드

 

 

일단 새로운 함수

.repeat 을 배워왔다

string.repeat() 은 () 안의 횟수만큼 stirng 을 반복하여 출력해주는 함수이다.

단순히 string을 여러번 반복해야할 경우 for 문을 사용하지 않아도 된다.

function solution(n) {
    var answer = '';
    answer = n % 2 == 0 ? "수박".repeat(n/2) : "수박".repeat(Math.floor(n/2))+"수"
    return answer;
}

 

좀 그럴싸 해지긴 했지만 역시  % 2 ==0  의 늪에선 빠져 나올순 없다

 

 

 

3. 내 적 

 

내적이 뭘까

 

my enemy 인가

 

정의를 찾아봐도 무슨 말인지 알 수가 없다

 

 

 

아무튼간에 같은 인덱스 끼리 곱하고 나온걸 다 합해주면 된다고 한다..

수학이 필요하다면 배워야겠지만 이건 논외인것 같다.

function solution(a, b) {
    var answer = 0;
    for(let i = 0; i < a.length; i++) {
        answer += a[i] * b[i];
    }
    return answer;
}

 

모든 배열 순회 이기 때문에

for ( var i in a) {} 또한 사용할 수 있다.

a의 인덱스인 0 1 2 3이 i 에 들어가며 반복된다

 

4. 약수의 개수와 덧셈

 

오늘..

풀이가 좀 수월했던 관계로 한문제 더  풀려고 했는데 불안한 녀석이 걸렸다.

 

아는방법대로 하면 분명 괴짜 코드가 나올것 같은 예감이 들지만

 

일단 해보는 수밖에 없다

function solution(left, right) {
    var answer = 0; 
    let ia = 0; // 약수의 개수를 카운트할 임의 변수
    for( var i = left; i <= right ; i++ ) { // left ~ right 까지의 연산이 필요
        for( var j = 1; j <= i; j++) {   // left부터 약수의 숫자를 구한다
            if(i % j == 0) { ia += 1 ;}  // 약수로 나눈경우 ia 를 +1 
        }
        answer = ia % 2 == 0 ? answer + i : answer - i // ia 가 홀수 짝수일 때 각각 -i +i 연산
        ia = 0; // ia 카운트 초기화
    }
    return answer
}

 

약수의 개수를 카운트할 ia 변수를 만들어 주고

for문 2개를 돌려서

left (i) 의 약수의 숫자를 구하고 그 갯수가 홀수일때와 짝수일 때  + - 연산을 해준뒤 임의로 ia를 초기화

left (i) 를 1씩 늘려가며 i == right 까지 반복 하는 !!

 

작동이 잘 되다니 오히려 놀랐다 

' 그래도 모자란 코드'  라는 생각과 '뿌듯함'   이 교차한다

 

 

 

 

 

'사전캠프' 카테고리의 다른 글

27일차 - 알고리즘 풀이  (0) 2024.07.29
26일차 - 알고리즘 풀이  (0) 2024.07.25
24일차 - 알고리즘 풀이  (1) 2024.07.23
23일차 - 알고리즘 풀이  (3) 2024.07.22
22일차 - 알고리즘 풀이  (0) 2024.07.19

 

이제 학습의 시작을 알고리즘으로 하는것에 익숙해졌다.

 

학습이 건강해지고 있다는것....

 

 

1. 핸드폰 번호 가리기

 

그다지 어렵지 않은 문제이다. (엄청 헤맸음)

 

반복문을 이용해서 문자열 phone_number를 순회하여 length -4 까지는 * 로, 그외는 그대로 출력해주면 된다

function solution(phone_number) {
    var answer = '';
    for(var i = 0; i < phone_number.length; i++ ) {
     answer = i < phone_number.length - 4 ? answer + '*' : answer + phone_number[i] ;
    }
    return answer;
}

 

 

 

2. 없는 숫자 더하기

 

function solution(numbers) {
    var answer = 0;
    for( var i = 0; i < numbers.length; i ++) {
        answer += numbers[i]
    }
    return 45 - answer;
}

배열의 모든 숫자를 더하고 0~9 의 합인 45에서 빼는 코드를 만들었다.

 

아무래도 (야매)

정답으로 인정받기엔 어려운 답지라고 생각한다.

 

 

.includes() 함수  를 데려오도록 하자

이걸 이용하면 훨씬 그럴싸 한 코드를 만들 수 있다.

 

function solution(numbers) {
    var answer = 0;
    for ( var i = 1; i < 10; i ++) {
        if(!numbers.includes(i)) { answer +=i} 
    }
    return answer;
}

1~9 까지의 숫자를 number가 포함되어 있는지를 체크한 뒤  없는경우 ( ! ) 만 answer 에 더해준다.

 

 

 

3. 제일 작은 수 제거하기

 

우선 아는것만 가지고 풀어보자..

 

function solution(arr) {
    var answer = [];
    for( var i = 0; i < arr.length ; i++) {
        if(arr[i] != Math.min(...arr) ) { answer.push(arr[i])}
    }
    return answer < 1 ? [-1] : answer;
}

 

arr을 순회하여 arr의 최소값이 아닌경우 answer 에 push 한다.

그리고 answer 값이 없는경우 [-1] 을 리턴하고 아닌경우 answer 를 그대로 리턴...

 

 

통과는 되는데, 테스트1의 지연시간이 심상치가 않다.

아마도, arr.length 가 엄청나게 큰 경우인 듯 하다.

 

검색 해본결과, index값을 찾기 위한 for 노가다를 할 필요가 없이

 

 

indexOf() 함수를 사용하면 된다

이 문제는 사실상 Math.min() 과 indexOf() 를 위한 문제였던것

 

function solution(arr) {
    if(arr.length == 1) { return [-1]}
    arr.splice(arr.indexOf(Math.min(...arr)), 1)
    return arr;
}

우선 [-1] 이 리턴될 경우는 arr.length 가 1인 경우 뿐이므로 미리 리턴해버린다

그 후 arr 배열에서 가장 작은 수의 index 값을 splice 로 날려주면 끝이다 !

 

 

'사전캠프' 카테고리의 다른 글

26일차 - 알고리즘 풀이  (0) 2024.07.25
25일차 - 알고리즘 풀이  (3) 2024.07.24
23일차 - 알고리즘 풀이  (3) 2024.07.22
22일차 - 알고리즘 풀이  (0) 2024.07.19
21일차 - Javascript 입문 수업  (0) 2024.07.18

알고리즘 !!

월요일은 역시 알고리즘 

 

1. 서울에서 김서방 찾기

 

늘 그렇듯,

아는방법대로 풀고  모르면 검색한다

 

아는 방법

function solution(seoul) {
    let i = 0;
    while(true) {
        if (seoul[i] == 'Kim') { return '김서방은 '+i+'에 있다'}
        i++
    }
}

 

 반 드 시 seoul 에 포함이 되어있기 때문에 while  true를 돌렸다.

while 을 가급적 멀리 하라고 했지만 아무튼 근거는 있다.

 

Kim 이 나올 때 까지 seoul[i] 를 순회한다. 찾으면 i를 반환하여 문장을 출력.

끝끝

 

 

 

2. 나누어 떨어지는 숫자 배열

 

약간 복잡해 보이는 문제...

 

for (var i = 0; i < arr.length ; i++)

우선 for 문으로 arr 원소를 순회해보자 

 

 if(arr[i] % divisor == 0)

arr 의 원소를 divisor 로 나누어 떨어질 경우

 

           answer.push(arr[i]);

해당 원소를 answer 배열에 넣어준다.

 

push는 배열의 뒤에 추가하는 것이다.

 

여기서 든 생각은 arr 배열이 오름차순이라면 자연스럽게 

연산의 결과도 오름차순이 될. 것이다.

 

        arr.sort((a,b) => a-b);

반복문 진입 전에, 해당 코드로 arr 배열을 오름차순으로 만들어 주자.

 

 

    if (answer.length == 0) { return [-1]} ;
    return answer;

 

 

값이 없는경우 -1을 리턴하게 하면 완성... 인데  

쓸데없이 if문 하나 더 쓰는것 보다는 삼향 연산자에 익숙해질 필요가 있다.

 

   return answer.length == 0 ? [-1] : answer;

거기서 거기 같지만 했다는게 중요하다...

 

 

function solution(arr, divisor) {
        var answer = [];
        arr.sort((a,b) => a-b);
    for (var i = 0; i < arr.length ; i++) {
        if(arr[i] % divisor == 0) answer.push(arr[i]);
    }
   return answer.length == 0 ? [-1] : answer;
}

최종 결과 

 

 

3. 음양 더하기

불리언 배열 ???

수학을 못해서 불리 ..한 배열

 

정리해보면, absolutes[n] signs[n] 원소가 있을때 signs[n] =false 인 경우는 absolutes[n] 이 음수이다

그 외는 양수

 

머리로는 알겠는데..

 

 for ( var i = 0; i < absolutes.length; i++) {
     if ( signs[i] == false) {
         nn.push(absolutes[i] * -1)
     } else nn.push(absolutes[i] * 1)
    }

 

우선 양수는 양수로 음수는 음수로 nn배열에 넣도록 했다

    for ( var i = 0; i < nn.length ; i++) {
        answer += nn[i]

그 다음 다 더하면.. 끝?

function solution(absolutes, signs) {
    var nn = [];
    var answer = 0;
    for ( var i = 0; i < absolutes.length; i++) {
     if ( signs[i] == false) {
         nn.push(absolutes[i] * -1)
     } else nn.push(absolutes[i] * 1)
    } 
    for ( var i = 0; i < nn.length ; i++) {
        answer += nn[i] 
    }
    return answer;

잘 작동하지만 쓸데없이 조잡해보인다. for 문도 괜히 2번 들어가고..

 

가능한 줄여보도록 하자.

 

불필요한 nn변수를 없애고 바로 answer 에서 연산

 if 구문을 삼향 연산자로 대체

function solution(absolutes, signs) {
    var answer = 0;
    for ( var i = 0; i < absolutes.length; i++) {
        answer = signs[i] == false ? answer-absolutes[i] : answer+absolutes[i]
    }
    return answer;
}

 

 

 

'사전캠프' 카테고리의 다른 글

25일차 - 알고리즘 풀이  (3) 2024.07.24
24일차 - 알고리즘 풀이  (1) 2024.07.23
22일차 - 알고리즘 풀이  (0) 2024.07.19
21일차 - Javascript 입문 수업  (0) 2024.07.18
20일차 - Javascript 입문 수업  (0) 2024.07.17

+ Recent posts