【达标子数组】腾讯二面,竟挂在了数组题上!!!

最近有小伙伴说,面试时面试官问了两道很类似的题目。

只想到第一道题目是关于 滑动窗口 的,第二道就想不出来了。

之前的文章我们就练习过一道关于 「滑动窗口」 的题目:窗口内的最大值
还没看过的小伙伴可以点击链接阅读哦~

今天我们就来讨论一下这 两道类似的题目 ,小伙伴们可以进行对比学习!!!


问题 1

给定一个由正整数组成的无序数组 arr 和一个整数 K ,在所有 arr 子数组中找到累加和等于 K ,并且长度最长的子数组,返回该长度。

示例 :

输入: arr = [3,2,1,3,3,1,1,1,1,1,1,2,2,2] ,K = 6

输出: 6

解释: 组合方式有多种:

  • 3 + 2 + 1 = 6
  • 2 + 1 + 3 = 6
  • 3 + 3 = 6
  • 3 + 1 + 1 + 1 = 6
  • 1 + 1 + 1 + 1 + 1 + 1 = 6

最长子数组为 6 个 1 时,因此返回 6 。

思路分析

由于数组均由正整数构成,因此就隐藏了一个重要的 单调信息

  • 窗口增大时,窗口累加和一定增大;
  • 窗口减小时,窗口累加和一定减小。

根据滑动窗口的思想,构造窗口[L, R],初始时[0, 0]表示窗口内只包含第一个元素 arr[0] ,设置窗口内的累加和变量sum,即初始值为sum=arr[0]

  1. sum < K,说明窗口值太小了,需要扩大窗口大小,因此R++
  2. sum > K,说明窗口值太大了,需要缩小窗口大小,因此L++
  3. sum = K,即找到了一组满足要求的子数组,记录并更新此时长度的最大值。缩小或扩大窗口,继续往后寻找是否还有满足要求的子数组。

注意: 要保证R++时不会越界哦~


有小伙伴可能会有疑惑:这种方法能够做到 不重不漏 的计算么?

我们对这三种情况都进行下分析:

  1. sum < K时,R++L不变,相当于在寻找以L为起始点的子数组中是否有满足要求的。(由于具有单调性,满足要求的子数组只可能比此时的长度长,因此R++)。
  2. sum > K时,L++R不变,相当于以L为起始点的子数组中一定不会出现满足要求的了。(因此L++缩小范围往后继续寻找)。
  3. sum = K时,记录此时长度。如果选择R++,那下一次一定会触发情况 2 ;如果选择L++,那下一次一定会触发情况 1 (具体实现选择一种即可)。实现了往后继续寻找的功能。

代码

public static int getMaxLength(int[] arr, int K) {
    if (arr == null || arr.length == 0 || K <= 0) {
        return 0;
    }
    int left = 0;
    int right = 0;
    int sum = arr[0];
    int len = 0;
    // 不越界
    while (right < arr.length) {
        if (sum == K) {
            // 更新长度信息
            len = Math.max(len, right - left + 1);
            // 选择了移动左侧
            sum -= arr[left++];
        } else if (sum < K) {
            // 已经到达最后一个位置了
            right++;
            if (right == arr.length) {
                break;
            }
            sum += arr[right];
        } else {
            // sum > K 时 L++
            sum -= arr[left++];
        }
    }
    return len;
}

思考一下

理解了 窗口功能 的思路之后,写出代码还是轻而易举的!

小伙伴们思考两个问题:

  1. 代码中的sum初始值设置成了arr[0]。如果修改成初始值:sum = 0,其他部分代码应该如何修改呢?含义是什么?
  2. 代码中的sum == K时,选择了L++,即缩小窗口。如果选择R++扩大窗口,代码如何写呢?(注意边界判断~)

评论区讨论一下吧~

对于第二个上难度的问题,小伙伴们先自己思考讨论一下吧!我们下篇文章接着聊~

关注
回复「ACM紫书」获取 ACM 算法书籍 ~
回复「算法导论」获取 算法导论第3版 ~

在看 + 转发

让你的小伙伴们一起来学算法吧!!

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值