leetcode-和为s的连续正数序列

 题目来自LeetCode,链接:和为s的连续正数序列。具体描述为:输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。

 示例1:

输入:target = 9
输出:[[2,3,4],[4,5]]

 示例2:

输入:target = 15
输出:[[1,2,3,4,5],[4,5,6],[7,8]]

 这道题的话最naive的想法就是遍历以从1到target/2开头的一系列连续数字,这就不赘述了。

 首先说一下我的做法,通过观察,可以发现凡是符合条件的序列都有以下特点:

  • 数列长度为奇数的话,中间的数字刚好等于target除以数列长度;
  • 数列长度为偶数的话,中间两个数的平均数为X.5=target÷数列长度(比如第一个例子有4.5=9÷2)。

 所以根据这个,我们直接遍历可能的序列长度(也就是2到target的一半),并判断此序列长度下是否有满足条件的连续正数。时间复杂度为 O ( N ) O(N) O(N),空间复杂度为 O ( 1 ) O(1) O(1)

 JAVA版代码如下:

class Solution {
    public int[][] findContinuousSequence(int target) {
        List<int[]> result = new LinkedList<>();
        for (int i = 2; i <= (target + 1) / 2; ++i) {
            if (i % 2 == 0 && target % i == i/2) {
                int smallerNum = target/i - i/2 + 1;
                if (smallerNum <= 0) {
                    break;
                }
                else {
                    int[] oneSolution = new int[i];
                    for (int j = 0; j < i; ++j) {
                        oneSolution[j] = smallerNum + j;
                    }
                    result.add(oneSolution);
                }
            }
            else if (i % 2 == 1 && target % i == 0) {
                int smallerNum = target/i - i/2;
                if (smallerNum <= 0) {
                    break;
                }
                else {
                    int[] oneSolution = new int[i];
                    for (int j = 0; j < i; ++j) {
                        oneSolution[j] = smallerNum + j;
                    }
                    result.add(oneSolution);
                }
            }
        }
        Collections.reverse(result);
        return result.toArray(new int[0][]);
    }
}

 提交结果如下:


 Python版代码如下:

class Solution:
    def findContinuousSequence(self, target: int) -> List[List[int]]:
        result = []
        for i in range(2, (target + 1) // 2 + 1):
            if i % 2 == 0 and target % i == i//2:       #如果可以由偶数个连续数字组成
                smallerNum = target//i - i//2 + 1
                if smallerNum <= 0:                     #接下来不再可能有符合的了,直接break
                    break
                else:
                    result.append([j for j in range(smallerNum, smallerNum + i)])
            elif i % 2 == 1 and target % i == 0:        #如果可以由奇数个连续数字组成
                smallerNum = target//i - i//2
                if smallerNum <= 0:
                    break
                else:
                    result.append([j for j in range(smallerNum, smallerNum + i)])
        return result[::-1]

 提交结果如下:


 这里再介绍另一种做法,考虑长度为n的数列,假设第一个数为 a 1 a_{1} a1,则符合条件的数列有
t a r g e t = n a 1 + n ( n − 1 ) 2 target=na_{1}+\frac{n(n-1)}{2} target=na1+2n(n1)

 可得 a 1 = t a r g e t − n ( n − 1 ) 2 n a_{1}=\frac{target-\frac{n(n-1)}{2}}{n} a1=ntarget2n(n1)。所以只需要遍历数列长度n,看是否有满足条件的 a 1 a_{1} a1即可。本质和上面的方法没有太大区别,只是在判断条件上没那么复杂了。

 JAVA版代码如下:

class Solution {
    public int[][] findContinuousSequence(int target) {
        List<int[]> result = new LinkedList<>();
        for (int n = 2; n <= (target + 1) / 2; ++n) {
            int temp = target - n * (n - 1) / 2;
            if (temp % n == 0) {
                int first = temp / n;
                if (first > 0) {
                    int[] oneSolution = new int[n];
                    for (int i = 0; i < n; ++i) {
                        oneSolution[i] = first + i;
                    }
                    result.add(oneSolution);
                }
                else {
                    break;
                }
            }
        }
        Collections.reverse(result);
        return result.toArray(new int[0][]);
    }
}

 提交结果如下:


 Python版代码如下:

class Solution:
    def findContinuousSequence(self, target: int) -> List[List[int]]:
        #a1 = (target-n*(n-1)/2)/n
        n = 2
        first = 1
        result = []
        for n in range(2, (target + 1) // 2):
            temp = target - n * (n - 1) // 2
            if temp % n == 0:
                first = temp // n
                if first > 0:
                    result.append([i for i in range(first, first + n)])
                else:
                    break
        return result[::-1]

 提交结果如下:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值