2026-09-17:判定好整数。用go语言,现有一个正整数 n。把它十进制写法中的每个数字拆出来,先累加这些数字,得到甲;再分别把每个数字平方后累加,得到乙。如果乙减去甲的结果不少于五十,就认为这个数符合要求。请判断 n 是否符合要求:符合时输出 true,不符合时输出 false。
1 <= n <= 1000000000。
输入: n = 19。
输出: true。
解释:
19 的数字为 1 和 9。
digitSum 为 1 + 9 = 10。
squareSum 为 1² + 9² = 1 + 81 = 82。
squareSum - digitSum 为 82 - 10 = 72。由于 72 大于等于 50,因此输出 true。
题目来自力扣3959。
一、逐步骤拆解执行过程
第 0 步:入口与参数main把 n = 19 传给checkGoodInteger。参数按值传递,函数内部对 n 的任何修改都不会影响调用方 —— 这一点很重要,因为下面的循环会破坏性地把 n 除到 0。
第 1 步:初始化累加器diff := 0,用于存放「乙 − 甲」的最终结果。此时还没读入任何一位数字,贡献总和为 0。
第 2 步:进入循环前的判断for ; n > 0; n /= 10的循环条件是n > 0。因为题目保证 n ≥ 1,所以循环至少执行一次;当 n 被除到 0 时说明所有位都处理完了,循环结束。(如果 n = 0,循环一次都不跑,diff 保持 0,返回 false —— 不过这不在题目范围内。)
第 3 步:取出当前最低位d := n % 10,用「对 10 取余」拿到十进制的最右一位。注意取位顺序是从个位往高位走的,与题目描述的「从左到右」书写顺序相反,但如上所述,加法可交换,顺序不影响结果。
第 4 步:把这一位的贡献累加进 diffdiff += d*d - d。其中d*d是这一位对「乙」的贡献,d是这一位对「甲」的贡献,两者之差就是这一位对最终差值的净贡献。注意这里用的是整数乘法而不是浮点幂运算,避免了精度问题,也更快。
第 5 步:砍掉最低位,推进迭代
循环后置语句n /= 10执行整数除法,把已经处理过的最低位丢弃,原来的十位变成新的个位。此时若 n 仍大于 0,回到第 2 步继续;若 n 变成 0,说明最高位也处理完毕,退出循环。
第 6 步:得出判定结果return diff >= 50。diff 此时恰好等于「乙 − 甲」。用>=对应题目里的「不少于五十」(含等于 50 的情形);若写成> 50就会在差值恰好为 50 时误判,这是个容易踩的边界点。返回值是 Go 的 bool 类型。
第 7 步:main 打印fmt.Println(result)把 bool 按true/false(小写)输出并换行。
二、以 n = 19 为例的完整追踪
轮次
进入时 n
d = n % 10
d² − d
累加后 diff
结束后 n
初始
19
0
第 1 轮
19
9
81 − 9 = 72
0 + 72 = 72
1
第 2 轮
1
1
1 − 1 = 0
72 + 0 = 72
0
终止
0
循环条件 n > 0 不成立,退出
最终 diff = 72,72 ≥ 50 成立,返回true,程序打印true。
对照题目给的「分两步算」的口径验证:甲 = 1 + 9 = 10,乙 = 1 + 81 = 82,乙 − 甲 = 82 − 10 = 72 ≥ 50 → true。两种算法结果一致,说明第 2 步的等价变换没有改变语义。
三、几个值得留意的细节
•数字 0 和 1 是"零贡献"位:0² − 0 = 0、1² − 1 = 0,它们只增加位数不增加差值。所以 1000000000(1 后面九个 0)的所有位贡献都是 0,最终 diff = 0,结果是 false —— 位数多不代表符合。
•单调递增的累积过程:
diff在整个循环中只会增加(每位贡献 d(d−1) ≥ 0),不会减少,因此不存在"后面被拉低"的情况。这也意味着理论上可以在 diff ≥ 50 时提前返回 true,但当前代码选择扫完全部位,逻辑更简单直接。•数值范围安全:单个数字最大 9,贡献最大 72;即使 n 取上限 10⁹(10 位),diff 最大也只有 10 × 72 = 720,远在 int 范围内,不存在溢出。
•输入假设:代码没有对 n < 1 或 n > 10⁹ 做校验,依赖题目给出的约束;若输入可能为 0,则需要额外处理(当前实现会返回 false,语义上也可以接受)。
设 n 的十进制位数为 k = ⌊log₁₀ n⌋ + 1。
•总时间复杂度:O(k),即 O(log₁₀ n),也就是 O(log n)。循环每轮砍掉一位,共执行 k 轮;每轮内部只做取余、乘法、减法、除法这些常数时间的基本运算,因此是 O(1) × k。由于题目限定 n ≤ 10⁹,k ≤ 10,循环次数被常数 10 卡住,所以在这个约束下也可以视作O(1)。若放宽到任意精度的大整数(比如用字符串读入),则严格是 O(k)。
•总的额外空间复杂度:O(1)。全程只用了
diff、d两个局部变量(外加按值传入、原地修改的形参 n),没有开辟数组、字符串或任何与位数相关的数据结构,也不涉及递归调用栈。无论 n 是 1 位还是 10 位,占用的额外空间都是常数级别。
一句话总结:这段代码用一次「从低位到高位」的逐位扫描,把「平方和减数字和」合并为「每位贡献 d(d−1) 的累加」,一趟 O(log n) 时间、O(1) 额外空间就完成了判定。
Go完整代码如下:
package main
import (
"fmt"
)
func checkGoodInteger(n int) bool {
diff := 0
for ; n > 0; n /= 10 {
d := n % 10
diff += d*d - d
}
return diff >= 50
}func main() {
n := 19
result := checkGoodInteger(n)
fmt.Println(result)
}
Python完整代码如下:
# -*-coding:utf-8-*-
def checkGoodInteger(n: int) -> bool:
diff = 0
while n > 0:
d = n % 10
diff += d * d - d
n //= 10
return diff >= 50
def main():
n = 19
result = checkGoodInteger(n)
print(result)if __name__ == "__main__":
main()
C++完整代码如下:
bool checkGoodInteger(int n) {
int diff = 0;
while (n > 0) {
int d = n % 10;
diff += d * d - d;
n /= 10;
}
return diff >= 50;
}int main() {
int n = 19;
bool result = checkGoodInteger(n);
std::cout << std::boolalpha << result << std::endl;
return 0;
}
我们相信人工智能为普通人提供了一种“增强工具”,并致力于分享全方位的AI知识。在这里,您可以找到最新的AI科普文章、工具评测、提升效率的秘籍以及行业洞察。 欢迎关注“福大大架构师每日一题”,发消息可获得面试资料,让AI助力您的未来发展。
热门跟贴