剑指offer 57 - II. 和为s的连续正数序列

news/2024/5/20 9:20:58 标签: 算法, 剑指offer, 滑动窗口

剑指 Offer 57 - II. 和为s的连续正数序列 - 力扣(LeetCode) (leetcode-cn.com)

目录

解法1:数学手段

运行结果

分析

确定可能的元素个数

根据等差数列所有项之和与项数的关系来筛选

 代码

解法2:滑动窗口

运行结果

分析

代码


解法1:数学手段

运行结果

分析

确定可能的元素个数

满足条件的序列最少要有两个元素,最多可能有几个元素?

如果n个连续正数之和为s,设第一个数为x,即:

        x, x + 1, ..., x + n-1

这个序列之和:n * x + n * (n - 1) / 2 == s

我们需要求的是n的最大值,那么x需要取得最小值,x至少是1,所以令x = 1代入上式,得到:

n * (n + 1) == 2 * s

又因为:n ^ 2 < n * (n + 1) == 2 * s

所以:n < sqrt ( 2 * s )

则满足要求的序列至多有sqrt ( 2 * s )个元素,我们记为N

根据等差数列所有项之和与项数的关系来筛选

对于任意n ∈ [ 2, N ]个连续正数组成的,和为s的序列,其平均值为 s / n,第一个元素:

x = s / n - (n-1) / 2 (可以验证:x * n + n * (n - 1)/ 2 == s)

如果n为奇数,那么均值s / n必然为该序列的中值,且n必然整除s,即:

s % n == 0

如果n为偶数,那么均值s / n必然为该序列中间两个数的均值

设中间两个数为a, a+1
则:
s / n = (a + a+1) / 2
s / n = a + 1/2
s = a * n + n / 2

所以:s % n == n / 2

 代码

class Solution {
public:
	bool check(int s, int n) {
		return ((n & 1) && !(s % n)) ||
			(!(n & 1) && (s % n == n / 2));
	}

	vector<vector<int>> findContinuousSequence(int s) {
		int N = sqrt(2 * s);
		vector<vector<int>> res;

		for (int i = N; i >= 2; --i) {
			if (check(s, i)) {
				int a1 = s / i - (i - 1) / 2;
				vector<int> arr(i);
				for (int j = 0; j < i; ++j) {
					arr[j] = a1 + j;
				}
				res.push_back(arr);
			}
		}

		return res;
	}
};

解法2:滑动窗口

运行结果

分析

我们考虑检查所有可能的连续整数序列:

从1开始的连续整数序列,从2开始的连续整数序列,……,从s/2开始的连续整数序列

由于这些序列之间存在大量重复的元素,我们希望通过找出他们之间的关系来避免重复的求和运算。

设f(i)表示从i开始的、和小于s的连续整数序列的最后一项,s[i, f(i)]表示这个闭区间上所有整数之和。

则有:

s[i, f(i)] = i + i+1 + ... + f(i) < s
s[i, f(i)+1] = i + i+1 + ... + f(i) + f(i)+1 >= s

同理:

s[i+1, f(i+1)] = i+1 + i+2 + ... + f(i+1) < s
s[i+1, f(i+1)+1] = i+1 + i+2 + ... + f(i+1) + f(i+1)+1 >= s

由此我们可以找出f(i+1)与f(i)的关系:

由 s[i+1, f(i)] < s[i, f(i)] < s
得:
    f(i+1) >= f(i)

由
s[i+1, f(i)+2] = s[i, f(i)+1] + f(i)+2 - i
s[i, f(i)+1] >= s
f(i)+2 - i > 0
得:
    s[i+1, f(i)+2] >= s
则: f(i+1)+1 <= f(i)+2
即: f(i+1) <= f(i)+1

根据以上关系,我们得到:

f(i) <= f(i+1) <= f(i) + 1 <= f(i+1) + 1

因此当检验完s[i, f(i)+1]之后,我们只需检验s[i+1, f(i)+1],用s[i, f(i)+1] - i 即可。

代码

class Solution {
public:
	vector<vector<int>> findContinuousSequence(int s) {
		vector<vector<int>> res;
		int end = 1;
		int sum = 1;
		for (int beg = 1; beg <= s / 2; ++beg) {
			while (sum < s) {
				++end;
				sum += end;
			}
			if (sum == s) {
				int size = end - beg + 1;
				vector<int> arr(size);
				for (int i = 0; i != size; ++i) arr[i] = beg + i;
				res.push_back(arr);
			}
			sum -= beg;
		}
		return res;
	}
};


http://www.niftyadmin.cn/n/1817206.html

相关文章

【kotlin】人机交互和异常处理

文章目录人机交互异常处理人机交互 我们从键盘输入两个数字&#xff0c;然后打印它们的和 首先先得到从键盘输入的字符串 println("请输入第一个数字")var num1Str readLine()println("请输入第二个数字")var num2Str readLine()然后转数字 我们发现报…

剑指offer 61. 扑克牌中的顺子

剑指 Offer 61. 扑克牌中的顺子 - 力扣&#xff08;LeetCode&#xff09; (leetcode-cn.com) 目录 运行结果 分析 代码 运行结果 分析 不难发现&#xff0c;如果抽取的5个数出现顺子&#xff0c;那么这5个数&#xff1a; 1. 不能出现重复数字 2. 不考虑0&#xff0c;最大…

【kotlin】递归和尾递归

文章目录递归尾递归优化递归 递归&#xff08;Recursive&#xff09;是指自己方法内部调用自己 我们来算一下5的阶乘 fun main(args: Array<String>) {//5的阶乘&#xff1a;5*4*3*2*1var num 5println(fact(num)) }fun fact(num:Int):Int{if(num 1){return 1}else{…

剑指offer 62. 圆圈中剩下的数字(约瑟夫环问题)

剑指 Offer 62. 圆圈中最后剩下的数字 - 力扣&#xff08;LeetCode&#xff09; (leetcode-cn.com) 目录 运行结果 分析 删除第m个数字 序列重组 映射 递推关系 代码 运行结果 分析 删除第m个数字 初始序列&#xff1a; 0, 1, ..., n-1 &#xff08;1&#xff09…

【kotlin】面向对象、封装、继承、多态

文章目录面向对象封装继承多态主构造函数和次构造函数面向对象 fun main(args: Array<String>) {var rect01 Rect(20,10)println("矩形的宽度&#xff1a;"rect01.width"&#xff0c;矩形的高度&#xff1a;"rect01.height) }class Rect(var width…

剑指offer 65. 不用加减乘除做加法

剑指 Offer 65. 不用加减乘除做加法 - 力扣&#xff08;LeetCode&#xff09; (leetcode-cn.com) 目录 运行结果 思路 代码 运行结果 思路 加法可以分解为两个步骤&#xff1a; 1. 各位相加&#xff0c;忽略进位&#xff1b;可以使用异或^来完成。 2. 把上一步取得的结果…

【kotlin】接口和抽象类

我们来定义一个接口&#xff0c;new一个Kotlin Interface&#xff0c;名字为IMan interface IMan {fun joyride() }然后新建一个Man类&#xff0c;实现刚才的IMan接口 class Man:IMan {override fun joyride(){println("我在飙车")} }编写测试代码 fun main(args:…

剑指offer 68 - I. 二叉搜索树的最近公共祖先

剑指 Offer 68 - I. 二叉搜索树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; (leetcode-cn.com) 目录 题解 运行结果 拓展&#xff1a;查找任意二叉树的任意两个节点的最近公共祖先 思路 代码&#xff08;含注释&#xff09; 检验运行结果 题解 由于树是二…