题解 | 和大于等于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;
    }
};
全部评论

相关推荐

24分钟1.自我介绍2.黑盒测试用例设计方法3.运用刚才的测试方法对手机端淘宝购物车结算页面进行测试4.测试流程5.需求文档没有标明边界值,怎么确定边界值,确定边界值后怎么测6.你们公司自动化测试是测业务主流程还是新需求反问:不足之处答:问答问题前思考3s再答,针对提问再答
一笑而过2222:边:边界值分析法(处理输入边界) 类:等价类划分法(划分有效 / 无效输入) 定:判定表法(多条件组合的逻辑判定) 因:因果图法(分析输入输出的因果关系) 迁:状态迁移法(覆盖系统状态转换路径) 场:场景法(模拟端到端业务流程) 正:正交试验法(多因素组合的测试优化) 错:错误推测法(基于经验推测潜在漏洞) 记忆逻辑链(按测试场景优先级排序) 先处理明确输入:边界值 + 等价类(边类) 再处理条件组合:判定表 + 因果图(定因) 接着处理状态与流程:状态迁移 + 场景法(迁场) 最后优化多因素与补漏:正交试验 + 错误推测(正错)
查看6道真题和解析
点赞 评论 收藏
分享
若怜君欢:驾驶证去掉吧,PPT啥的也去掉,本硕课程去掉,导师和研究方向去掉;加入本硕排名(好才写);技能栏加入你会的那些控制算法和滤波算法,这个比你会啥啥啥软件更有用;获奖写上去,奖学金啊,有没有专利啊之类的 电机和硬件这一块,属于传统制造业,制造业实习并不多。多投一些攒攒经验,有实习最好,没有也不需要焦虑(制造业实习其实除了转正,没多大用处) 最后,划重点,等秋招开始后,把你所有社交软件都发一份简历上去,并经常更新,找人内推你!
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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