[LeetCode] 209. 최소 크기 하위 배열 합계 (C ++)


주제 출처 : https://leetcode-cn.com/problems/minimum-size-subarray-sum/

제목 설명

문자열이 주어지면 반복되는 문자의 가장 긴 부분 문자열 길이가 포함되지 않은 문자열을 찾습니다 .

示例 1

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
示例 2

输入:target = 4, nums = [1,4,4]
输出:1
示例 3

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
 

提示:

1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 105


进阶:

如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(nlog(n)) 时间复杂度的解法。

일반적인 생각

  • 반복되는 문자를 포함하지 않는 가장 긴 문자열을 찾고 슬라이딩 창 + 이중 포인터의 형태를 통해 발생 횟수를 기록하는 cnt 배열을 사용합니다.

슬라이딩 윈도우 + 이중 포인터

  • 가변 길이 창을 유지하고 왼쪽 및 오른쪽 포인터를 계속 움직이고 가장 긴 창 길이를 사용합니다.
class Solution {
    
    
public:
    int minSubArrayLen(int target, vector<int>& nums) {
    
    
        int len = nums.size(), left = 0, right = 0;
        int ans = INT_MAX, cnt = 0;
        bool flag = false;
        for(; right < len ; ++right){
    
    
            cnt += nums[right];
            while(cnt >= target){
    
    
                ans = min(ans, right - left + 1);
                cnt -= nums[left];
                ++left;
                flag = true;
            }
        }
        if(!flag)   return 0;
        return ans;
    }
};

복잡성 분석

  • 시간 복잡도 : O (n). 왼쪽 및 오른쪽 포인터가 모두 n 번 이동했습니다.
  • 공간 복잡성 : O (1)

접두사 및 + 이진 검색

  • 슬라이딩 윈도우의 복잡성은 O (n)이지만 고급 주제에는 nlogn이 필요합니다. 묻지 마십시오. 질문은 O (nlogn)이 O (n)보다 낫다는 것입니다. logn에 대한 생각은 정렬 된 것과 연관 될 수 있습니다. 요소에 대한 이진 검색의 시간 복잡도는 O (logn)입니다. 배열을 정렬하는 한 가지 방법은 직접 정렬하는 것이고 다른 하나는 접두사 및를 통해 단조로운 시퀀스를 구성하는 것입니다. 제목의 요소 값은 양수 여야합니다. 숫자이므로 접두사와 단조로운 시퀀스 여야합니다.
  • 이 중 sum [i]는 nums [0]에서 nums [i-1]까지 요소의 합을 나타냅니다. 접두사 합계를 구한 후 각 시작 첨자 i에 대해 i에서 경계까지의 합계 [i, bound]의 누적 합계 (즉, i에서 경계까지의 연속 하위 배열의 누적 합계)를 이진 검색으로 검색 할 수 있습니다. , sum [i, bound]> = target을 만족하는 것으로 확인되면 하위 배열의 최소 길이를 업데이트합니다 (현재 하위 배열의 길이는 bound-i + 1 임).
  • 여기서 stl 캡슐화 된 lower_bound벡터를 직접 호출하여 이진 검색 계산을 직접 수행 할 수 있습니다 (이 중 80 %는 인터뷰 중에 직접 호출되지 않음). 여기서는 대상보다 크거나 같은 첫 번째 요소에 해당하는 인덱스 값을 수동으로 반환합니다.
class Solution {
    
    
public:
    int minSubArrayLen(int target, vector<int>& nums) {
    
    
        int len = nums.size(), ans = INT_MAX;
        int sums[len + 1];
        sums[0] = nums[0];
        // sums[0] = 0 意味着前 0 个元素的前缀和为 0
        // sums[1] = A[0] 前 1 个元素的前缀和为 A[0]
        for(int i = 1 ; i <= len ; ++i)  sums[i] = sums[i - 1] + nums[i - 1];
        for(int i = 1 ; i <= len ; ++i){
    
    
            int newTarget = target + sums[i - 1];
            int bound = BinarySearch(newTarget, sums, 0, len);
            if(bound != -1){
    
    
               ans = min(ans, bound - i + 1);
            }
        }
        return ans == INT_MAX ? 0 : ans;
    }
    int BinarySearch(int target, int* nums, int left, int right){
    
    
        while(left <= right){
    
    
            int mid = right + ((left - right) >> 1);
            if(nums[mid] < target)  left = mid + 1;
            else{
    
    
                if(mid == 1 || nums[mid - 1] < target)  return mid;
                else    right = mid - 1;
            }
        }
        return -1;
    }
};

복잡성 분석

  • 시간 복잡도 : O (nlogn). n은 배열의 길이, n주기 * logn은 이진 검색의 평균 복잡도입니다.
  • 공간 복잡성 : O (n). n은 배열의 길이이며 접두사와 배열을 유지합니다.

추천

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