力扣剑指offer之和为s的连续数组

输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
示例 1:
输入:target = 9
输出:[[2,3,4],[4,5]]

解析:看到本题,我相信大部分人都能想到并实现普通的暴力解法:
1)从1到target开始遍历每一个数,将每一个数都假设作为满足条件的连续整数序列的起始元素,来进行逐个验证是否满足假设。
2)写函数来验证假设。在函数内部,就是从当前值出发,进行叠加,如果能有叠加值正好等于target,那就返回true,说明该值可以作为满足条件的连续整数序列起始值。否则返回false。
3)我们利用第二步中函数返回值作为判断依据,如果返回值false,则直接进行下一次循环,如果返回是true,则开始声明列表,将从该值起,一直到累加和为target为止,所有的数添加到列表中。再将该小列表添加到大列表中。
4)将大列表转化为数组即可返回。

class Solution {
    ArrayList<ArrayList<Integer>> result = new ArrayList<>();
    public int[][] findContinuousSequence(int target) {
        for(int i = 1; i < target; i++){
            if(Test(i, target)){
                ArrayList<Integer> li = new ArrayList<>();
                int sum = 0;
                for(int j = i; j < target; j++){
                    sum += j;
                    li.add(j);
                    if(sum == target){
                        break;
                    }
                }

                result.add(li);
            }
        }
        int[][] re = new int[result.size()][];
        for(int i = 0; i < result.size(); i++){
            re[i] = new int[result.get(i).size()];
            for(int j = 0; j < result.get(i).size(); j++){
                re[i][j] = result.get(i).get(j);
            }
        }
        return re;
    }

    boolean Test(int k, int target){
        
        int sum = 0;
        int i = 0;
        for(i = k; i < target; i++){
            sum += i;
            if(sum == target){
                return true;
            }
            if(sum > target){
                return false;
            }
        }

        return false;
    }
}

下面我们来看第二种:滑动窗口。
只要是跟连续数组相关的,滑动窗口一定要能联系到。我们从1开始进行滑动。如果窗口内值小于target,则窗口右侧增加数据。如果窗口内值大于target,则窗口左侧减少数据。如果正好相等,则就要将窗口内值保存到list中,再放入大list内。一直滑动到结束为止。

public int[][] findContinuousSequence(int target) {
    int i = 1; // 滑动窗口的左边界
    int j = 1; // 滑动窗口的右边界
    int sum = 0; // 滑动窗口中数字的和
    List<int[]> res = new ArrayList<>();

    while (i <= target / 2) {
        if (sum < target) {
            // 右边界向右移动
            sum += j;
            j++;
        } else if (sum > target) {
            // 左边界向右移动
            sum -= i;
            i++;
        } else {
            // 记录结果
            int[] arr = new int[j-i];
            for (int k = i; k < j; k++) {
                arr[k-i] = k;
            }
            res.add(arr);
            // 左边界向右移动
            sum -= i;
            i++;
        }
    }

    return res.toArray(new int[res.size()][]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值