《剑指offer》——和为S的连续正数序列

来源:互联网 发布:网络大电影 铁扇公主 编辑:程序博客网 时间:2024/05/21 07:02

  • 遍历穷举法
  • 滑动窗口法

T:

题目描述
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
`
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序.

遍历穷举法

我刚开始采用的做法,用遍历穷举的方式,在遍历的过程中,进行条件的约束,但是这种方式的时间复杂度仍然是O(n2)

我的code:

    package niuke.sward2offer.findContinuousSequence;    import java.util.ArrayList;    /**     * T: 和为S的连续正数序列     *      * 题目描述      * 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。     * 但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。     * 没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。     * 现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!      *       * 输出描述:      * 输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序     *      * date: 2015.12.7  20:53     * @author SSS     *     */    public class Solution {        public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {            ArrayList<ArrayList<Integer>> resultsList = new ArrayList<ArrayList<Integer>>();            // 小于3的没有意义(无解)            if (sum < 3) {                return resultsList;            }            // 只要遍历sum一半就可以,因为再往后的连续正数序列其总和肯定大于sum            int mid = sum / 2;            for (int i = 1; i <= mid; i++) {                for (int len = 2; ; len++) {    // 长度至少为2                    int curSum = this.getSum(i, len);                    if (curSum == sum) {                        resultsList.add(this.saveSequence(i, len));                    } else if (curSum > sum) {                        break;                    }                }            }            return resultsList;        }        /**         * 返回首位为startIndex,长度为length的连续序列的总和         * @param startIndex         * @param length         * @return         */        public int getSum(int startIndex, int length) {            int endIndex = startIndex + length - 1;            return (startIndex + endIndex) * length / 2;        }        /**         * 返回连续正数列表         * @param startIndex         * @param length         * @return         */        public ArrayList<Integer> saveSequence(int startIndex, int length) {            ArrayList<Integer> resList = new ArrayList<Integer>();            int endIndex = startIndex + length;            for (int i = startIndex; i < endIndex; i++) {                resList.add(i);            }            return resList;        }    }

滑动窗口法

这种方式,是看到讨论版上有人贴出来的解题思路,我才恍然大悟的,这种思路将时间复杂度降到了O(n)

这里写图片描述

将我重新实现一遍的代码再贴出来,code:

    import java.util.ArrayList;    /**     * T: 和为S的连续正数序列     *      * 题目描述      * 小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。     * 但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。     * 没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。     * 现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!      *       * 输出描述:      * 输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序     *      * date: 2015.12.7  21:44     * @author SSS     *     */    public class Solution2 {        /**         * 类似于滑动窗口的概念,总和小于sum,就执行endIndex ++; 大于的话,就执行 startIndex ++;         * @param sum         * @return         */        public ArrayList<ArrayList<Integer> > FindContinuousSequence(int sum) {            ArrayList<ArrayList<Integer>> resultsList = new ArrayList<ArrayList<Integer>>();            if (sum < 3) {                return resultsList;            }            int startIndex = 1;            int endIndex = 2;            int curSum = 3;            int mid = sum / 2;            while (endIndex < mid || startIndex < endIndex) {                if (curSum == sum) {                    resultsList.add(this.saveList(startIndex, endIndex));                }                endIndex ++;                curSum += endIndex;                while (curSum > sum) {                    curSum -= startIndex;                    startIndex ++;                }            }            return resultsList;        }        /**         * 存储到list当中,并返回         * @param startIndex         * @param endIndex         * @return         */        public ArrayList<Integer> saveList(int startIndex, int endIndex) {            ArrayList<Integer> resList = new ArrayList<Integer>();            for (int i = startIndex; i <= endIndex; i++) {                resList.add(i);            }            return resList;        }    }
0 0
原创粉丝点击