题解 | 和大于等于K的最短子数组(单调栈+二分)

和大于等于K的最短子数组

http://www.nowcoder.com/practice/3e1fd3d19fb0479d94652d49c7e1ead1

双指针(错误)

写完双指针,发现题目输入还有负数,感觉双指针不对......

想到这个数据 [-10, 3,-10],3,会输出-1。

(错误代码)

class Solution {
public:
    int shortestSubarray(vector<int>& nums, int k) {
        int n = nums.size(), ans = INT_MAX;
        long long cnt = 0;
        for (int i = 0, j = 0; i < n; ++i) {
            cnt += nums[i];
            while (cnt >= k) {
                cnt -= nums[j ++];
            }
            if (j) ans = min(ans, i - j + 2);
        }
        return ans == INT_MAX ? -1 : ans;
    }
};

单调栈+二分

(这个做法应该是对的...)

子数组和 k \ge k,即 pre[R]pre[L1]kpre[R] - pre[L-1] \ge k (prepre 为前缀和)。

枚举 RR,应该选择尽量大的 LL 满足上面不等式。

假设找到一个 jj,在 jj 的左边有一个 kkpre[k1]pre[j1]pre[k-1] \ge pre[j-1]jj 比 k更好。

因为 : ①、kk 如果能满足上面不等式, jj 也一定能满足,而且形成的子数组, jj 的比 kk 更短。②、如果 jj 能满足上面不等式,kk 不一定能满足,因为pre[k1]pre[j1]pre[k-1] \ge pre[j-1]

因此前面更大的数是没用的,使用单调栈维护递增序列。枚举RR,二分单调栈找到最大的LL

class Solution {
public:
    int shortestSubarray(vector<int>& nums, int k) {
        using LL = long long;
        int n = nums.size();
        vector<LL> pre(n + 1);
        vector<int> stk(n + 1);
        int top = 1, ans = INT_MAX;
        for (int i = 1; i <= n; ++i) {
            pre[i] = pre[i - 1] + nums[i - 1];
        }
        for (int i = 1; i <= n; ++i) {
            if (pre[i] - pre[stk[1]] >= k) {
                int l = 1, r = top;
                while (l < r) {
                    int mid = l + r + 1 >> 1;
                    if (pre[i] - pre[stk[mid]] >= k) {
                        l = mid;
                    } else {
                        r = mid - 1;
                    }
                }
                ans = min(ans, i - stk[r]);
            }
            while (top && pre[i] <= pre[stk[top]]) --top;
            stk[++top] = i;
        }
        return ans == INT_MAX ? -1 : ans;
    }
};
全部评论

相关推荐

07-11 11:10
门头沟学院 Java
请问各位大三兄弟们跟hr说多久实习时间到时候可以提前跑路吗?
程序员小白条:问就是六个月以上,可以一年,实习都这样,你入职后想跑就跑
点赞 评论 收藏
分享
05-25 10:45
门头沟学院 Java
Frank_zhan...:没实习一个项目肯定不够,可以再做一个轮子,技术栈再补一个mq,微服务,整体再换个简历模板,暑期尽量再找一个日常实习
无实习如何秋招上岸
点赞 评论 收藏
分享
门口唉提是地铁杀:之前b站被一个游戏demo深深的吸引了。看up主页发现是个初创公司,而且还在招人,也是一天60。二面的时候要我做一个登录验证和传输文件两个微服务,做完要我推到github仓库,还要我加上jaeger和一堆运维工具做性能测试并且面试的时候投屏演示。我傻乎乎的做完以后人家跟我说一句现在暂时不招人,1分钱没拿到全是白干
你的秋招第一场笔试是哪家
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务