剑指 Offer 57 - II. 和为s的连续正数序列

描述:

输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。

序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。

示例 1:

输入:target = 9
输出:[[2,3,4],[4,5]]
示例 2:

输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]

思路:
最容易想到的就是暴力解法,两层遍历。但是题目要求返回二维数组,这个不知道怎么定义,看下官方解析,定义如下:

class Solution {
    public int[][] findContinuousSequence(int target) {
    
        List<int[]> vec = new ArrayList<int[]>();  
// (target - 1) / 2 等效于 target / 2 下取整
        int sum = 0, limit = (target - 1) / 2; 
        for (int i = 1; i <= limit; ++i) {  //第一层循环
            for (int j = i;; ++j) {   //第二层循环:没有大小的限定条件
                sum += j;
                if (sum > target) {
                    sum = 0;
                    break;
                } else if (sum == target) {
                    int[] res = new int[j - i + 1];
                    for (int k = i; k <= j; ++k) {   //遍历后放入数组中
                        res[k - i] = k;
                    }
                    vec.add(res);
                    sum = 0;
                    break;
                }
            }
        }
        return vec.toArray(new int[vec.size()][]);  //转为数组输出
    }
}

第二种思路:

参考:https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/solution/shi-yao-shi-hua-dong-chuang-kou-yi-ji-ru-he-yong-h/

使用滑动窗口:滑动窗口的左边界和右边界永远只能向右移动。
所以有以下几种情况:

  • 窗口和 < target,窗口和需要变得更大,所以扩大窗口,窗口右边界向右移动;
  • 窗口和 > target,窗口和需要变得更小,所以缩小窗口,窗口左边界向右移动;
  • 窗口和 = target,记录结果,然后向后继续寻找,所以窗口的左边界向右移动;
class Solution {
    public int[][] findContinuousSequence(int target) {

       List<int[]> res = new ArrayList<>();

       int i = 1,j = 1,sum = 0;  //i是窗口左边界,j是窗口右边界

       while(i <= target / 2){
           if(sum < target){  //当小于target时,窗口右边界右移
               sum += j;
               j++;
           }else if(sum > target){  //当大于target时,窗口左边界右移
               sum -= i;
               i++;
           }else if(sum == target){
               int[] temp = new int[j - i];  //右边界是开区间
               for(int k = i;k < j; k++){
                   temp[k - i] = k;
               }
               res.add(temp);  //向后遍历
               sum -= i;
               i++;
           }
       }
       return res.toArray(new int[res.size()][]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值