* Computer Science/Algorithm

718. Maximum Length of Repeated Subarray

soicem 2021. 8. 28. 23:02

https://leetcode.com/problems/maximum-length-of-repeated-subarray/

 

Maximum Length of Repeated Subarray - LeetCode

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com

 

class Solution {
public:
    int getSubLength(vector<int>& nums1, vector<int>& nums2, int i, int j){
        int ret = 0;
        while(i < nums1.size() && j < nums2.size()){
            if(nums1[i] != nums2[j]){
                break;
            }
            ret++;
            i++;
            j++;
        }
        return ret;
    }
    
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        unordered_map<int, vector<int>> idxs;
        
        for(int i = 0; i < nums2.size(); i++){
            int v = nums2[i];
            idxs[v].push_back(i);
        }
        
        int ans = 0;
        
        for(int i = 0; i < nums1.size(); i++){
            int v = nums1[i];
            for(auto j : idxs[v]){
                ans = max(ans, getSubLength(nums1, nums2, i, j));
            }
        }
        return ans;
    }
};

 unordered_map에 index만 집어넣고 이중루프 돌면서 sublength를 반환한다.  겹치는 글자가 너무 많은경우에 취약하다.  

 

1 <= nums1.length, nums2.length <= 1000

 

 범위가 1000이면 모두 동일한 숫자가 들어있다고 가정할때 시간복잡도는 O(N^3)이 걸리고 이는 1초의 임계시간을 아득히 넘는다.  계산하면 1,000,000,000이다.  

 

 getSubLength할 때 앞에서 뒤로 밀기만해서 caching하기가 까다로움

 

class Solution {
public:
    int visited[1001][1001];
    int ans = 0;
    int getSubLength(vector<int>& nums1, vector<int>& nums2, int i, int j){
        if(i >= nums1.size() || j >= nums2.size()){
            return 0;
        }
        
        int & ret = visited[i][j];
        
        if(ret != -1){
            return ret;
        }
        ret = 0;
        
        if(nums1[i] == nums2[j]){
            ret = 1 + getSubLength(nums1, nums2, i + 1, j + 1);
        } 
        getSubLength(nums1, nums2, i, j + 1);
        getSubLength(nums1, nums2, i + 1, j);

        ans = max(ans, ret);
        return ret;
    }
    
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        memset(visited, -1, sizeof(visited));
        getSubLength(nums1, nums2, 0, 0);
        return ans;
    }
};

 1000 x 1000에서 한 번 방문했던 위치는 캐싱하므로 시간복잡도는 O(N^2)이 걸린다.

 

 

+  효율성 체크 필요

 

-효율체크

class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        int cache[1001][1001];
        memset(cache, -1, sizeof(cache));
        
        int ans = 0;
        
        for(int i = 0; i <= nums1.size(); i++){
            for(int j = 0; j <= nums2.size(); j++){
                if(i == 0 || j == 0){
                    cache[i][j] = 0;
                    continue;
                }
                
                if(nums1[i - 1] == nums2[j - 1]){
                    cache[i][j] = 1 + cache[i - 1][j - 1];
                } else {
                    cache[i][j] = 0;
                }
                ans = max(ans, cache[i][j]);
            }
        }
        return ans;
    }
};

 연속 sub array를 판별할 때 nums1과 nums2를 2차원 배열로 매핑하면 대각선이 같으냐 다르냐에 따라 연속인지 아닌지 판별할 수 있다.  즉, 이중루프를 돌면서 각 셀의 문자가 같은지 아닌지 판별하고 같으면 cache[i - 1][j - 1]과 더해줬을때 모든 sub array 경우의 수를 구할 수 있다.

 

 max(cache[i - 1][j - 1] + 1) if nums[i] == nums[j]

 

Time complexity: O(N^2)

Space complexity: O(N^2)

 

 

 recursion을 사용하는것과 시간복잡도는 동일하지만, recursion은 각 호출 시 stack frame을 사용하므로 이중루프를 도는것에 비해 상대적으로 비효율적이다.

'* Computer Science > Algorithm' 카테고리의 다른 글

1871. Jump Game VII  (0) 2021.10.03
1759. 암호 만들기  (0) 2021.09.18
351. Android Unlock Pattern  (0) 2021.08.28
1171. Remove Zero Sum Consecutive Nodes from Linked List  (0) 2021.06.03
1488. Avoid Flood in The City  (0) 2021.05.30