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

剑指 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]]

思路:

解法一:一般解法

从i=1开始, 尝试每个值i为连续子数组的开头,
使用一个内层for循环判断这个开头能走到哪里,会有两种情况
第一种:sum[i…j]=target,记录答案,尝试下一个开头(因为每一个开头只会有为一个子数组的和是target);
第二种:sum[i…j]>target, 表示开头i无法产生“和为target的连续子数组”,于是尝试下一个开头。

 public int[][] findContinuousSequence(int target){
       List<int[]> vec =  new ArrayList<>();
       for(int i=1;i<=(target-1)/2;i++){// (target-1)/2 等效于 target/2向下取整
           // start i
           int sum=0;
           for(int j=i;;j++){
               sum+=j;
               if(sum>target){// say sum[3,4] and add 5, we get 12, but target=11 // so turn to try the next i as start
                   break;
               }else if(sum==target){
                   int[] sub = new int[j-i+1];// 以i为开头的子数组,和为 target
                   for(int k=i;k<=j;k++){
                       sub[k-i]=k;
                   }
                   vec.add(sub);
                   // one start has only one solution, so let's try i as the next solution
                   break;
               }
           }
       }
       return vec.toArray(new int[vec.size()][]);
    }

解法二:双指针

可以把l,r想象成滑动窗口的左右边界,
当窗口内的和等于target时,把当前窗口记录到答案中,然后l++,表示尝试下一个开头;
当窗口内的和大于target时,l++,表示当前的开头没有希望了,尝试下一个开头;
当窗口内的和小于target时,r++,表示扩大当前窗口。

 public int[][] findContinuousSequence(int target){
        List<int[]> vec = new ArrayList<>();
        for(int l=1,r=2;l<=(target/2);){
            int sum = (r-l+1)*(r+l)/2;
            if(sum==target){
                int[] res = new int[r-l+1];
                for(int k=l;k<=r;k++){
                    res[k-l]=k;
                }
                vec.add(res);
                l++;
            }else if(sum>target){
                l++;
            }else{
                r++;
            }
        }
        return vec.toArray(new int[vec.size()][]);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值