zoukankan      html  css  js  c++  java
  • 每日一题leetcode

    剑指 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 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()][]);
            }
        }
    

      方法一:此题是暴力解法  枚举+暴力

      知识点:

    toArray(new int[vec.size()][]);转化为列表转化为二维数组
    浮点型转化为整型是向上取整
    解法:

      枚举每个正整数为起点,判断以它为起点的序列和 sum 是否等于target 即可,由于题目要求序列长度至少大于 2,所以枚举的上界为(target - 1) / 2 等效于 target / 2 下取整

      方法二:双指针法

    设连续正整数序列的左边界 i 和右边界 j ,则可构建滑动窗口从左向右滑动。循环中,每轮判断滑动窗口内元素和与目标值 target 的大小关系,若相等则记录结果,若大于 target则移动左边界 i(以减小窗口内的元素和),若小于 target 则移动右边界 j (以增大窗口内的元素和)。

    算法流程:
    初始化: 左边界 i = 1 ,右边界 j = 2,元素和 s = 3 ,结果列表 res;

    循环: 当 i≥j 时跳出;

    当 s > target 时: 向右移动左边界 i = i + 1 ,并更新元素和 s ;
    当 s < targett时: 向右移动右边界 j = j + 1 ,并更新元素和 s ;
    当 s = target 时: 记录连续整数序列,并向右移动左边界 i = i + 1 ;
    返回值: 返回结果列表 res ;

    class Solution {
        public int[][] findContinuousSequence(int target) {
            List<int[]> vec = new ArrayList<int[]>();
            for (int l = 1, r = 2; l < r;) {
                int sum = (l + r) * (r - l + 1) / 2;
                if (sum == target) {
                    int[] res = new int[r - l + 1];
                    for (int i = l; i <= r; ++i) {
                        res[i - l] = i;
                    }
                    vec.add(res);
                    l++;
                } else if (sum < target) {
                    r++;
                } else {
                    l++;
                }
            }
            return vec.toArray(new int[vec.size()][]);
        }
    }
    

      方法三:求根公式法

    class Solution {
        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()][]);
        }
    }
    

      

  • 相关阅读:
    PLSQL连接64位oracle,导入导出错误解决办法
    VS2008或者VS2010工具栏,标准里面的 在浏览器中浏览按钮不见了
    jquery radio取值,checkbox取值,select取值 及选中
    Waiting for HOME (‘android.process.acore’) to be launched…解决办法
    GetTickCount() 函数的作用和用法
    MFC ado连接access数据库
    VC切分窗口和多视图
    C++容器——插入与清除
    VC中在对话框上显示图片
    error LNK2005 已经在***.obj中定义
  • 原文地址:https://www.cnblogs.com/nenu/p/15140706.html
Copyright © 2011-2022 走看看