[LeetCode] 523. 연속 하위 배열 합계 및 연속 하위 배열 합계 (C ++)


질문 출처 : https://leetcode-cn.com/problems/continuous-subarray-sum/

제목 설명

음수가 아닌 숫자와 대상 정수 k를 포함하는 배열이 주어지면 배열에 크기가 2 이상이고 합이 k의 배수 인 연속 하위 배열이 포함되어 있는지 여부를 확인하는 함수를 작성합니다. sum은 n * k입니다. 여기서 n은 정수이기도합니다.

示例 1

输入:[23,2,4,6,7], k = 6
输出:True
解释:[2,4] 是一个大小为 2 的子数组,并且和为 6
示例 2

输入:[23,2,6,4,7], k = 6
输出:True
解释:[23,2,6,4,7]是大小为 5 的子数组,并且和为 42
 
说明:

数组的长度不会超过 10,000
你可以认为所有数字总和在 32 位有符号整数范围内。

일반적인 생각

  • 배열이 주어지면 길이가 2보다 큰 연속 하위 배열의 합이 n * k인지 확인하고 True와 False를 반환합니다.

접두사 및 + 폭력적 열거

  • 연속 하위 배열의 합은 접두사 합계를 사용하여 간격의 합계 처리 시간 복잡성을 최적화 할 수 있습니다. 무차별 대입 열거는 다음 조건을 충족하는 배열을 찾습니다
    (합계 [j]-합계 [i-1]). % k = 0 (sums [j] -sum [i-1]) \ % k = 0( s u m s [ j ]s u m [ i1 ] ) % k=0
class Solution {
    
    
public:
    bool checkSubarraySum(vector<int>& nums, int k) {
    
    
        int len = nums.size();
        int sums[len + 1];
        memset(sums, 0, sizeof(sums));
        for(int i = 1; i <= len ; ++i)  sums[i] = sums[i - 1] + nums[i - 1];
        for(int i = 1 ; i <= len ; ++i){
    
    
            for(int j = i + 1 ; j <= len ; ++j){
    
    
                if(k == 0 && sums[j] - sums[i - 1] == 0)    return true;
                if(k != 0 && (sums[j] - sums[i - 1]) % k == 0)    return true;
            }
        }
        return false;
    }
};

복잡성 분석

  • 시간 복잡도 : O (n ^ 2). n은 배열의 길이입니다.
  • 공간 복잡성 : O (ln). n은 배열의 길이입니다.

HashMap + 접두사 합계

  • 공식을 더 단순화 할 수 있습니다. 동일한 접두사와 동일한 값이 동일한 값에 매핑됩니다. 여기서 접두사와 합계 [0]도 매핑해야합니다. k = 0
    (합계 [ j] − sum [i − 1]) (mod) k = 0 → sums [j] (mod) k ⟺ sum [i − 1] (mod) k (sums [j] -sum [i-1]) ( mod) k = 0 → sums [j] (mod) k⟺sum [i-1] (mod) k( s u m s [ j ]s u m [ i1 ] ) ( m o d ) k=0s u m s [ j ] ( m o d ) ks u m [ i1 ] ( m o d ) k
class Solution {
    
    
public:
    bool checkSubarraySum(vector<int>& nums, int k) {
    
    
        int len = nums.size();
        int sums[len + 1];
        memset(sums, 0, sizeof(sums));
        map<int, vector<int>> mmap;
        if(k == 0){
    
    
            for(int i = 0 ; i < len - 1; ++i){
    
    
                if(nums[i + 1] == nums[i] && nums[i] == 0)  return true;
            }
            return false;
        }
        for(int i = 1; i <= len ; ++i){
    
    
            sums[i] = sums[i - 1] + nums[i - 1];
            mmap[sums[i] % k].push_back(i);
        }
        // sums[0] ->   0     -> index :  0
        // sums[1] -> nums[0] -> index :  0
        mmap[0].push_back(0);
        for(int i = 1 ; i <= len ; ++i){
    
    
            int index = sums[i] % k;
            for(auto it : mmap[index]){
    
    
                // 排除长度为1
                if (i - 1 > it) return true;
            }
        }
        return false;
    }
};

복잡성 분석

  • 시간 복잡도 : O (n). n은 배열의 길이이고 해당 액세스 매핑 배열의 평균 복잡도는 O (1)입니다.
  • 공간 복잡성 : O (n). 무순 맵의 길이는 최대 배열 길이입니다.

추천

출처blog.csdn.net/lr_shadow/article/details/114051302