zoukankan      html  css  js  c++  java
  • [LeetCode]Minimum Size Subarray Sum

    题目:Minimum Size Subarray Sum

    给定一个整数数组,和一个值,找到一个连续子序列,使其和>=给定的值,且该子序列长度最短。

    思路1:

    时间复杂度O(n),空间复杂度O(1)的解法。

    使用首尾两个指针,求出两个指针之间的数据之和;当和大于等于s时,比较序列长度和最小值,然后,增加头指针;当和小于s时,然后,增加尾指针;

    注意:

    1.数组整个之和小于s的情况;

    2.循环退出条件是tail != nums.cend();它不能保证最后的子序列是最短状态。

    int LeetCode::minSubArrayLen(int s, vector<int>& nums){
        if (!nums.size())return 0;
        auto head = nums.cbegin(), tail = nums.cbegin() + 1;
        int min = nums.size(), cur = nums.at(0);//s可能是负值
        while (tail != nums.cend()){
            if (cur < s){//尾指针增加
                cur += *tail;
                ++tail;
            }
            else{
                if (min > tail - head)min = tail - head;//判断是否当前子序列更短
                cur -= *head;//头指针增加
                ++head;
            }
        }
        if (min == nums.size() && cur < s)return 0;//数组的总和仍小于s
        while (s <= cur){//最后子序列可能不是最优状态{7[2, 3, 1, 2, 4, 3]}
            cur -= *head;
            ++head;
        }
        if (min > tail - head + 1)min = tail - head + 1;
        return min;
    }

    思路2:

    时间复杂度O(nlogn),空间复杂度O(1)的解法。

    滑动窗口的思想来解此问题。固定一个大小的窗口,从头到尾滑动该窗口,判断窗口里的元素之和>=s,返回true。

    然后,通过折半的方式锁定窗口的大小,找到最小的窗口大小使得窗口中的元素之和>=s。

    int LeetCode::minSubArrayLen2(int s, vector<int>& nums){
        int i = 1, j = nums.size(), min = 0;
        while (i <= j) {
            int mid = (i + j) / 2;//窗口大小
            if (windowExist(mid, nums, s)) {
                j = mid - 1;//存在,则收缩窗口
                min = mid;
            }
            else i = mid + 1;//折半的方式锁定窗口大小
        }
        return min;
    }
    
    bool LeetCode::windowExist(int size, vector<int>& nums, int s) {
        int sum = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (i >= size) sum -= nums[i - size];//开始滑动
            sum += nums[i];
            if (sum >= s) return true;
        }
        return false;
    }

    思路3:

    时间复杂度O(nlogn),空间复杂度O(n)的解法。

    这个思路需要辅助数组,用来保存给定的数组的前i项的数据之和。

    循环所有元素,并且通过折半的方法找到当前位置开始到最近结束位置,使得该区间的元素之和>=s。

    int LeetCode::minSubArrayLen3(int s, vector<int>& nums){
        int sum = 0, ret = nums.size() + 1;//ret记录最小值
    
        vector<int>& sums(nums);//前i项的和
        for (int i = 0; i < nums.size(); i++)
            sums[i] = nums[i] + (i == 0 ? 0 : sums[i - 1]);
    
        for (int i = 0; i < nums.size(); i++) {
            //找到以当前位置开始和大于s的最近结束位置
            int j = i, k = sums.size() - 1, offset = i == 0 ? 0 : sums[i - 1];//j从当前起始位置i开始,k作为尾指针前后往前,offset记录前一个的位置的和
            while (j <= k) {//折半的方式找到最近结束位置
                int m = (j + k) / 2;
                int sum = sums[m] - offset;
                if (sum >= s) k = m - 1;
                else j = m + 1;
            }
            if (j == nums.size()) break;
            ret = min(j - i + 1, ret);//更新最小值
        }
    
        return ret == nums.size() + 1 ? 0 : ret;
    }
  • 相关阅读:
    pycharm下载与安装
    IOS 字体表
    iOS 在 ARC 环境下 dealloc 的使用、理解误区
    微信支付的开发
    Undefined symbols for architecture i386:和"_OBJC_CLASS_$_xx", referenced from:问题解决方法
    soureTree使用
    UINavigationController 直接pop到指定controllerView的方法
    OBC: NSString 与 NSArray 互转
    NSArray的containsObject的使用时注意的问题
    IOS 自定义导航栏标题和返回按钮标题
  • 原文地址:https://www.cnblogs.com/yeqluofwupheng/p/6792536.html
Copyright © 2011-2022 走看看