FrontEnd/프로그래머스

[JS] 연속 펄스 부분 수열의 합

728x90

문제 자체는 부분수열의 합을 구하는 방법을 알면 해결할 수 있는 문제이다.

 

 

1 , -1 , 1 , -1 ...

-1 , 1 , - 1 , 1 ...

 

해당되는 펄스를 각각 곱한 2개의 수열을 만들어주면 된다.

 

이어서 dp를 활용해서 부분수열의 합중 가장 큰 값을 가지면 된다.

 

 

아래 예시를 보며 생각해보자.

2 3 -6 1 3 -1 2 4

 

dp[n] 을 n번째에 올 수 있는 가장 최대치의 부분수열의 합이라 생각하고

maxDp[n]을 n번를 무조건 포함한 가장 최대치의 부분수열의 합이라 생각하자.

 

결국 dp[n] = Math.max(dp[n-1] , maxDp[n])

 

이 되게된다.

n번째 값이 들어왔을때 이를 포함한 부분수열의 합이 더큰가 아닌가만 확인하면 되는 문제로 바뀐 것이다.

 

 

maxDp[n]은 아래와 같이 구할 수 있다.

maxDp[n] = MAt.max(maxDp[n-1] + ary[n] , ary[n])

 

즉, n-1번째 까지 부분수열의 합에 ary[n] 값을 더하거나 , 아예 ary[n] 이 더큰경우를 판별하면 된다.

 

위 점화식이 가능한 이유를 살펴보자.

 

1. 양수가 들어오는 경우 => 양수이므로 무조건 maxDp[n-1]에 n번째 수를 넣는것이 가장 클 것이다.

2. 음수가 들어오는 경우 => 음수이므로 무조건 maxDp[n-1]에 n번째 수를 넣는것이 n번째 수를 넣어야하는 입장에서는 가장 클 것이다.

3. maxDp[n-1]이 음수인 경우 => 아예 부분수열을 끊고 n번째 값 한개만 있는 부분수열이 가장 클 것이다.

 

이를 코드로 구현하면 아래와 같다.

 

function solution(sequence) {
    const ary1 = sequence.map((v,idx) => idx%2 ? v : -v)
    const ary2 = sequence.map((v,idx) => idx%2 ? -v : v)
    
    const dp1 = new Array(sequence.length)
    const maxDp1 = new Array(sequence.length)
    const dp2 = new Array(sequence.length)
    const maxDp2 = new Array(sequence.length)
    
    dp1[0] = ary1[0]
    dp2[0] = ary2[0]
    maxDp1[0] = ary1[0]
    maxDp2[0] = ary2[0]
    
    for (let i = 1 ; i < sequence.length ; i++){
        
        maxDp1[i] = Math.max(maxDp1[i-1] + ary1[i] , ary1[i])
        maxDp2[i] = Math.max(maxDp2[i-1] + ary2[i] , ary2[i])
        
        dp1[i] = Math.max(maxDp1[i] , dp1[i-1])
        dp2[i] = Math.max(maxDp2[i] , dp2[i-1])
    }
    
    return Math.max(dp1[dp1.length-1] , dp2[dp2.length-1])
}

 

 

 

 

 

 

 

728x90

'FrontEnd > 프로그래머스' 카테고리의 다른 글

[JS] 표현 가능한 이진트리  (0) 2023.10.14
[JS] 인사고과  (0) 2023.10.12
[JS] 아방가르드 타일링  (0) 2023.10.09
[JS] 상담원 인원  (0) 2023.10.07
[JS] 에어컨  (0) 2023.10.04