
2026-06-19:阶数数字排列。用go语言,给定一个整数 n,判断能否把 n 的各位数字重新排列(允许使用原来的顺序,也允许换成任意顺序),得到某个有效整数,使得它满足下面的性质:
要求考虑所有排列的可能性,但排列必须是有效的:不能以 0 开头(否则该排列视为无效)。
如果存在至少一种有效排列能形成阶数数字,返回 true;否则返回 false。
1 <= n <= 1000000000。
输入: n = 145。
输出: true。
解释:
数字 145 本身是一个阶数数字,因为 1! + 4! + 5! = 1 + 24 + 120 = 145。因此,答案为 true。
题目来自力扣3848。
题目要求:给定数字n,把它所有数字做不含前导0的排列,只要任意一个排列x满足「x每一位阶乘相加 = x本身」,就返回true。 核心数学关键点:
x = S;输入示例n=145,循环条件 n>0,每次对10取模取个位,再除以10截断:
核心逻辑:如果sumFac和原数n是数字重排列,那么两者每个数字出现次数完全相等,遍历sumFac每一位,对应cnt数字计数减1,最终所有cnt必须归零。
循环条件 sumFac>0,每次取个位、除以10:
[10]int{0,0,...0};固定循环0~9,循环次数恒定10次 → O(1) 常数时间,只执行一次。
设输入数字n的位数为k(题目上限1e9,最多10位):
整体单次判断函数时间:O(1),与输入数值大小无关。 全局总时间复杂度:O(1)(常数级)。
额外开辟的存储空间:
不存在随输入长度增长的动态数组、切片、递归栈等。 总额外空间复杂度:O(1)(常数空间)。
.
package main
import (
"fmt"
)
var fac = [10]int{1}
func init() {
// 预处理阶乘
for i := 1; i < len(fac); i++ {
fac[i] = fac[i-1] * i
}
}
func isDigitorialPermutation(n int)bool {
sumFac := 0
cnt := [10]int{}
for ; n > 0; n /= 10 {
d := n % 10
sumFac += fac[d]
cnt[d]++
}
for ; sumFac > 0; sumFac /= 10 {
cnt[sumFac%10]--
}
// cnt[i] == 0
return cnt == [10]int{}
}
func main() {
n := 145
result := isDigitorialPermutation(n)
fmt.Println(result)
}

.
# -*-coding:utf-8-*-
# 预处理阶乘
fac = [1] * 10
for i in range(1, len(fac)):
fac[i] = fac[i-1] * i
def is_digitorial_permutation(n: int) -> bool:
sum_fac = 0
cnt = [0] * 10
# 计算各位数字阶乘之和,并统计各位数字出现次数
temp = n
while temp > 0:
d = temp % 10
sum_fac += fac[d]
cnt[d] += 1
temp //= 10
# 对阶乘和的各位数字,减少对应计数
while sum_fac > 0:
cnt[sum_fac % 10] -= 1
sum_fac //= 10
# 检查所有计数是否为 0
return all(c == 0for c in cnt)
def main():
n = 145
result = is_digitorial_permutation(n)
print(result)
if __name__ == "__main__":
main()
.
#include <iostream>
#include <array>
using namespace std;
// 预处理阶乘
array<int, 10> fac;
void initFac() {
fac[0] = 1;
for (int i = 1; i < 10; i++) {
fac[i] = fac[i-1] * i;
}
}
bool isDigitorialPermutation(int n) {
int sumFac = 0;
array<int, 10> cnt = {0};
// 计算各位数字阶乘之和,并统计各位数字出现次数
int temp = n;
while (temp > 0) {
int d = temp % 10;
sumFac += fac[d];
cnt[d]++;
temp /= 10;
}
// 对阶乘和的各位数字,减少对应计数
while (sumFac > 0) {
cnt[sumFac % 10]--;
sumFac /= 10;
}
// 检查所有计数是否为 0
for (int i = 0; i < 10; i++) {
if (cnt[i] != 0) {
returnfalse;
}
}
returntrue;
}
int main() {
initFac();
int n = 145;
bool result = isDigitorialPermutation(n);
cout << (result ? "true" : "false") << endl;
return0;
}
