zoukankan      html  css  js  c++  java
  • Easy | 剑指 Offer 57

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

    限制:

    • 1 <= target <= 10^5

    方法一: 双指针遍历

    先固定一个指针, 然后一个指针不断向右遍历, 直到两指针中间的和大于目标值即可。

    public int[][] findContinuousSequence(int target) {
        List<int[]> res = new ArrayList<>();
        int left = 1, right = 2;
        while(left < right && left <= target/2) {
            int curSum = (right + left) * (right - left + 1) / 2;
            if (curSum == target) {
                int[] curRes = new int[right - left + 1];
                for (int i = left; i <= right; i++) {
                    curRes[i - left] = i;
                }
                res.add(curRes);
                right++;
            } else if (curSum < target) {
                // 当两指针之间和小于target时, 右指针继续向前
                right++;
            } else {
                // 当超过了target值, 此后此left就要换个位置了
                // 此时right不必回溯, 因为此时[left+1, right-1]之间的和必定小于target
                left++;
            }
        }
        return res.toArray(new int[res.size()][]);
    }
    

    方法二: 枚举 + 数学优化

    x 累加到 y 的和由求和公式如下:

    [frac{(x+y) *(y-x+1)}{2}= ext { target } ]

    转化为如下:

    [y^{2}+y-x^{2}+x-2 * ext { target }=0 ]

    套用求和公式, 则问题转化为两个条件

    • 判别式 b^2 - 4ac 开根号必须是整数。(固定X, 移动Y, 把方程看作是Y为变量的一元二次方程)
    • 最后的求根公式的分子需要为偶数,因为分母为 22
    public int[][] findContinuousSequence(int target) {
        List<int[]> vec = new ArrayList<int[]>();
        int sum = 0, limit = (target - 1) / 2; // (target - 1) / 2 等效于 target / 2 下取整
        for (int x = 1; x <= limit; ++x) {
            long delta = 1 - 4 * (x - (long) x * x - 2 * target);
            if (delta < 0) {
                continue;
            }
            int delta_sqrt = (int) Math.sqrt(delta + 0.5);
            if ((long) delta_sqrt * delta_sqrt == delta && (delta_sqrt - 1) % 2 == 0) {
                int y = (-1 + delta_sqrt) / 2; // 另一个解(-1-delta_sqrt)/2必然小于0,不用考虑
                if (x < y) {
                    int[] res = new int[y - x + 1];
                    for (int i = x; i <= y; ++i) {
                        res[i - x] = i;
                    }
                    vec.add(res);
                }
            }
        }
        return vec.toArray(new int[vec.size()][]);
    }
    
  • 相关阅读:
    MySQL my.cnf详解
    函数:sleep-exit-wait
    fork-小实验
    OS-进程调度
    CET-4流程
    SDK和API的区别
    生活-金钱管理-不是理财
    算法设计与分析:Strassen矩阵乘法
    力扣:二进制加法求和
    算法设计与分析:大整数乘法
  • 原文地址:https://www.cnblogs.com/chenrj97/p/14320605.html
Copyright © 2011-2022 走看看