Eat Study Love

먹고 공부하고 사랑하라

Coding_Practice

Longest Non-decreasing Subarray From Two Arrays[M,Array,Dynamic Programming]

eatplaylove 2024. 7. 24. 16:56

 

https://leetcode.com/problems/longest-non-decreasing-subarray-from-two-arrays/

You are given two 0-indexed integer arrays nums1 and nums2 of length n.

Let's define another 0-indexed integer array, nums3, of length n. For each index i in the range [0, n - 1], you can assign either nums1[i] or nums2[i] to nums3[i].

Your task is to maximize the length of the longest non-decreasing subarray in nums3 by choosing its values optimally.

Return an integer representing the length of the longest non-decreasing subarray in nums3.

Note: A subarray is a contiguous non-empty sequence of elements within an array.

 

Example 1:

Input: nums1 = [2,3,1], nums2 = [1,2,1]
Output: 2
Explanation: One way to construct nums3 is: 
nums3 = [nums1[0], nums2[1], nums2[2]] => [2,2,1]. 
The subarray starting from index 0 and ending at index 1, [2,2], forms a non-decreasing subarray of length 2. 
We can show that 2 is the maximum achievable length.

Example 2:

Input: nums1 = [1,3,2,1], nums2 = [2,2,3,4]
Output: 4
Explanation: One way to construct nums3 is: 
nums3 = [nums1[0], nums2[1], nums2[2], nums2[3]] => [1,2,3,4]. 
The entire array forms a non-decreasing subarray of length 4, making it the maximum achievable length.

Example 3:

Input: nums1 = [1,1], nums2 = [2,2]
Output: 2
Explanation: One way to construct nums3 is: 
nums3 = [nums1[0], nums1[1]] => [1,1]. 
The entire array forms a non-decreasing subarray of length 2, making it the maximum achievable length.

 

Constraints:

  • 1 <= nums1.length == nums2.length == n <= 105
  • 1 <= nums1[i], nums2[i] <= 109

1. Python

 

class Solution:
    def maxNonDecreasingLength(self, nums1: List[int], nums2: List[int]) -> int:
        if len(nums1) == 0 or len(nums2) == 0 : return 0
        n = len(nums1)
        ans = []
        ans.append(min(nums1[0],nums2[0]))
        nums1 = nums1[1:]
        nums2 = nums2[1:]
        i = 0
        while i<n-1 :
            if nums1[0]>=ans[i] or nums2[0]>=ans[i]:
                if nums1[0] < ans[i] :
                    ans.append(nums2[0])
                    nums1 = nums1[1:]
                    nums2 = nums2[1:]
                    i+=1
                    continue                 
                elif nums2[0] < ans[i] :
                    ans.append(nums1[0])
                    nums1 = nums1[1:]
                    nums2 = nums2[1:]
                    i+=1
                    continue 
                else:
                    ans.append(min(nums1[0],nums2[0]))
                    nums1 = nums1[1:]
                    nums2 = nums2[1:]
                    i+=1
                    continue
            break
        return len(ans)

 

이렇게 했더니 통과하지 못하는 test case가 있다. 문제를 잘못 파악했나..?

 

아 만들어진 ans list에서 non decreasing의 시작은 꼭 index 0 일 필요가 없다는 것..

 

결국 Dynamic Programming을 이용해야 한다.

 

class Solution:
    def maxNonDecreasingLength(self, nums1: List[int], nums2: List[int]) -> int:
        n = len(nums1)
        dp1 = [0 for x in range(n)]
        dp2 = [0]*n

        dp1[0]=1
        dp2[0]=1

        for i in range(1,n):
            dp1[i]=dp2[i]=1
            if nums1[i] >= nums1[i-1]:
                dp1[i] = max(dp1[i],dp1[i-1]+1)
            if nums1[i] >= nums2[i-1]:
                dp1[i] = max(dp1[i],dp2[i-1]+1)
            if nums2[i] >= nums1[i-1]:
                dp2[i] = max(dp2[i],dp1[i-1]+1)
            if nums2[i] >= nums2[i-1]:
                dp2[i] = max(dp2[i],dp2[i-1]+1)
        return max(max(dp1),max(dp2))

경의로운 DP의 세계..

 

이건 사실 최대 non-decrease 조합자체를 반환하기 보단, 그 length를 구하는 것에 특화된 solution 같긴 하다.

 

 

2. C

int max(int a, int b){
    if(a>=b) return a;
    return b;
}

int maxNonDecreasingLength(int* nums1, int nums1Size, int* nums2, int nums2Size){
    int* dp1 = (int*)malloc(nums1Size*sizeof(int));
    int* dp2 = (int*)malloc(nums1Size*sizeof(int));
    dp1[0]=dp2[0]=1;
    for(int i=1;i<nums1Size;i++){
        dp1[i]=dp2[i]=1;
        if(nums1[i] >= nums1[i - 1])
            dp1[i] = dp1[i] >= dp1[i-1]+1 ? dp1[i] : dp1[i-1]+1;
        if(nums1[i] >= nums2[i - 1])
            dp1[i] = dp1[i] >= dp2[i-1]+1 ? dp1[i] : dp2[i-1]+1;
        if(nums2[i] >= nums1[i - 1])
            dp2[i] = dp2[i] >= dp1[i-1]+1 ? dp2[i] : dp1[i-1]+1;
        if(nums2[i] >= nums2[i - 1])
            dp2[i] = dp2[i] >= dp2[i-1]+1 ? dp2[i] : dp2[i-1]+1;
    }
    int ans1=0;
    for(int i=0;i<nums1Size;i++){
        ans1 = max(ans1,dp1[i]);
    }
    int ans2=0;
    for(int i=0;i<nums1Size;i++){
        ans1 = max(ans1,dp2[i]);
    }
    return max(ans1,ans2);
}

 

사실상 Python logic을 그대로 C로 옮겨보는 것에 초점을 두었다.

 

3. C++

C랑 거의 똑같은데, int 비교 max함수 쓸 수가 있고, for문 돌리는게 좀 더 편하다.

class Solution {
public:
    int maxNonDecreasingLength(vector<int>& nums1, vector<int>& nums2) {
        int n = nums1.size();
        vector<int> dp1(n,0);
        vector<int> dp2(n,0);
        dp1[0]=dp2[0]=1;
        for(int i=1;i<n;i++){
            dp1[i]=dp2[i]=1;
            if(nums1[i] >= nums1[i - 1])
                dp1[i] = max(dp1[i],dp1[i-1]+1);
            if(nums1[i] >= nums2[i - 1])
                dp1[i] = dp1[i] >= dp2[i-1]+1 ? dp1[i] : dp2[i-1]+1;
            if(nums2[i] >= nums1[i - 1])
                dp2[i] = dp2[i] >= dp1[i-1]+1 ? dp2[i] : dp1[i-1]+1;
            if(nums2[i] >= nums2[i - 1])
                dp2[i] = dp2[i] >= dp2[i-1]+1 ? dp2[i] : dp2[i-1]+1;
        }
    int ans1=0;
    for(int i=0;i<n;i++){
        ans1 = max(ans1,dp1[i]);
    }
    int ans2=0;
    for(int i=0;i<n;i++){
        ans1 = max(ans1,dp2[i]);
    }
    return max(ans1,ans2);
    }
};

 

        int max1 = *max_element(dp1.begin(), dp1.end());
        int max2 = *max_element(dp2.begin(), dp2.end());

        return max(max1, max2);

이런 식으로 C++ vector의 max값을 찾기도 한다!