本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,还会用多种编程语言实现题解,涉及到通用解法时更将归纳总结出相应的算法模板。
为了方便在PC上运行调试、分享代码文件,我还建立了相关的仓库:https://github.com/memcpy0/LeetCode-Conquest。在这一仓库中,你不仅可以看到LeetCode原题链接、题解代码、题解文章链接、同类题目归纳、通用解法总结等,还可以看到原题出现频率和相关企业等重要信息。如果有其他优选题解,还可以一同分享给他人。
由于本系列文章的内容随时可能发生更新变动,欢迎关注和收藏征服LeetCode系列文章目录一文以作备忘。
给你一个正整数 n
,找出满足下述条件的 中枢整数 x
:
1
和x
之间的所有元素之和等于x
和n
之间所有元素之和。
返回中枢整数 x
。如果不存在中枢整数,则返回 -1
。题目保证对于给定的输入,至多存在一个中枢整数。
示例 1:
输入:n = 8
输出:6
解释:6 是中枢整数,因为 1 + 2 + 3 + 4 + 5 + 6 = 6 + 7 + 8 = 21 。
示例 2:
输入:n = 1
输出:1
解释:1 是中枢整数,因为 1 = 1 。
示例 3:
输入:n = 4
输出:-1
解释:可以证明不存在满足题目要求的整数。
提示:
1 <= n <= 1000
解法1 枚举 或 前缀和
根据题意,我们从 1 1 1 开始遍历到 n n n ,并求前缀和,如果包含当前元素 x x x 的前缀和 s u m sum sum 等于 n × ( n + 1 ) / 2 − s u m + x n\times (n + 1) / 2 - sum + x n×(n+1)/2−sum+x ,则说明当前元素 x x x 是中枢整数。
class Solution {
public:
int pivotInteger(int n) {
int sum = 0, tot = n * (n + 1) / 2;
for (int x = 1; x <= n; ++x) {
sum += x;
if (sum == tot - sum + x) return x;
}
return -1;
}
};
又或者,我们不用求前缀和,而是在
[
1
,
n
]
[1,n]
[1,n] 的范围内枚举
x
x
x ,判断以下等式是否成立。若成立,则
x
x
x 为中枢整数。
(
1
+
x
)
×
x
=
(
x
+
n
)
×
(
n
−
x
+
1
)
(1 + x) \times x = (x + n) \times (n - x + 1)
(1+x)×x=(x+n)×(n−x+1)
class Solution {
public:
int pivotInteger(int n) {
for (int x = 1; x <= n; ++x)
if ((1 + x) * x == (x + n) * (n - x + 1))
return x;
return -1;
}
};
复杂度分析:
- 时间复杂度: O ( n ) O(n) O(n) ,其中 n n n 为给定的正整数 n n n 。
- 空间复杂度: O ( 1 ) O(1) O(1) 。
解法2 数学O(1)
1 1 1 到 x x x 的元素和为 x ( x + 1 ) 2 \dfrac{x(x+1)}{2} 2x(x+1) , x x x 到 n n n 的元素和为 1 1 1 到 n n n 的元素和减去 1 1 1 到 x − 1 x-1 x−1 的元素和,即 n ( n + 1 ) − x ( x − 1 ) 2 \dfrac{n(n+1)-x(x-1)}{2} 2n(n+1)−x(x−1) 。两式相等,简化后即
x = n ( n + 1 ) 2 x = \sqrt{\dfrac{n(n+1)}{2}} x=2n(n+1)
如果 x x x 不是整数则返回 − 1 −1 −1 。
class Solution {
public:
int pivotInteger(int n) {
int m = n * (n + 1) / 2;
int x = sqrt(m);
return x * x == m ? x : -1;
}
};
复杂度分析:
- 时间复杂度:
O
(
1
)
O(1)
O(1) 。计算平方根有专门的 CPU 指令,可以视作是
O
(
1
)
O(1)
O(1) 时间。Python 的
math.isqrt
用的牛顿迭代法,这里也视作 O ( 1 ) O(1) O(1) 。 - 空间复杂度: O ( 1 ) O(1) O(1) ,仅用到若干变量。
解法3 查表O(1)
注意到 n ( n + 1 ) 2 \dfrac{n(n+1)}{2} 2n(n+1) 又叫三角数 triangular number(见 OEIS A000217),定义是:非负整数前 n n n 项和, 0 + 1 + 2 + … + n 0 + 1 + 2 + … + n 0+1+2+…+n 。如 0 , 1 , 3 , 6 , 10 , 15 , 21 , 28 , 36 , 45 , 55 , 66 , 78 , 91 , 105 , 120 , 136 , 153 , 171 , 190 , 210 , 231 , 253 , 276 , 300 , 325 , 351 , 378 , 406 , 435 , 465 , 496 , 528 , 561 , 595 , 630 , 666 , 703 , 741 , 780 , 820 , 861 , 903 , 946 , 990 , 1035 , 1081 , 1128 , 1176 , 1225 , 1275 , 1326 , 1378 , 1431 , … 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300, 325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225, 1275, 1326, 1378, 1431, … 0,1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210,231,253,276,300,325,351,378,406,435,465,496,528,561,595,630,666,703,741,780,820,861,903,946,990,1035,1081,1128,1176,1225,1275,1326,1378,1431,… 帮助理解的方式:想像有一堆包子摆成杨辉三角的形状,前 n n n 行包子的数量之和就是第 n n n 个三角数。
一个三角数是完全平方数的情况(见 OEIS A001108),定义是:第 n n n 个(base 0)三角数同时是一个平方数。如 0 , 1 , 8 , 49 , 288 , 1681 , 9800 , 57121 , 332928 , 1940449 , 11309768 , 65918161 , 384199200 , … 0, 1, 8, 49, 288, 1681, 9800, 57121, 332928, 1940449, 11309768, 65918161, 384199200, … 0,1,8,49,288,1681,9800,57121,332928,1940449,11309768,65918161,384199200,… 比如:
- 第 1 1 1 个三角数是 1 1 1 ,它是 1 1 1 的平方
- 第 8 8 8 个三角数, 8 × ( 8 + 1 ) / 2 = 36 8 \times (8 + 1) / 2 = 36 8×(8+1)/2=36 ,它是 6 6 6 的平方
- 第 49 49 49 个三角数, 49 × ( 49 + 1 ) / 2 = 1225 49 \times (49 + 1) / 2 = 1225 49×(49+1)/2=1225 ,它是 35 35 35 的平方
- 第 288 288 288 个三角数, 288 × ( 288 + 1 ) / 2 = 41616 288 \times (288 + 1) / 2 = 41616 288×(288+1)/2=41616 ,它是 204 204 204 的平方
一个数的平方数是三角数的情况(见 OEIS A001109)。如 0 , 1 , 6 , 35 , 204 , 1189 , 6930 , 40391 , 235416 , 1372105 , 7997214 , 46611179 , 271669860 , 1583407981 , … 0, 1, 6, 35, 204, 1189, 6930, 40391, 235416, 1372105, 7997214, 46611179, 271669860, 1583407981, … 0,1,6,35,204,1189,6930,40391,235416,1372105,7997214,46611179,271669860,1583407981,… 比如:
- 1 1 1 的平方 1 1 1 是三角数
- 6 6 6 的平方 36 36 36 是三角数
- 35 35 35 的平方 1225 1225 1225 是三角数
- 204 204 204 的平方 41616 41616 41616 是三角数
即在本题数据范围下,这种「是三角数也是完全平方数的情况」是很少的。
n
n
n 只有
1
,
8
,
49
,
288
1,8,49,288
1,8,49,288
这四个,对应的答案为
1
,
6
,
35
,
204
1,6,35,204
1,6,35,204
上述数据用程序枚举
[
1
,
1000
]
[1,1000]
[1,1000] 内的
n
n
n ,调用上面的代码,即可得到。
class Solution {
const unordered_map<int, int> m{{1, 1}, {8, 6}, {49, 35}, {288, 204}};
public:
int pivotInteger(int n) {
auto it = m.find(n);
return it != m.end() ? it->second : -1;
}
};
复杂度分析:
- 时间复杂度: O ( 1 ) O(1) O(1) 。
- 空间复杂度: O ( 1 ) O(1) O(1) ,仅用到若干变量。