查找多个相同数字的立即数的优化或最佳方法
Optimized or best way to find an immediate number of a number of same digits
所以我有一个像 123 这样的数字,相同数字的立即数是 132。考虑另一个例子,数字是 1238,下一个立即数是 1283。所以对于这个逻辑,我已经实现了一个代码
def findnext(n):
ns=list(map(int,str(n)))
for i in reversed(range(len(ns))):
if i == 0: return n
if ns[i] > ns[i-1] :
break
left,right=ns[:i],ns[i:]
for k in reversed(range(len(right))):
if right[k]>left[-1]:
right[k],left[-1]=left[-1],right[k]
break
return int("".join(map(str,(left+sorted(right)))))
n=int(input())
print(findnext(n))
我需要一个不使用 itertools 的更优化或更精简代码的逻辑。请帮我!!提前致谢。
这与其说是一个 python 问题,不如说是一个逻辑问题。
根据我正确理解你的问题的方式,你需要使用相同的数字并找到最接近的数字。从逻辑上讲,这意味着大多数时候你想交换最后两位数字。但是,如果我这样做,最接近您的 1238
示例的是 1283
,距离是 1283-1238=45
而不是 `1328-1238=90,还是我错过了某种规则?
距离可以是双向的还是只有一个?
当我确定规则时,我(和其他人)可能会提供更多帮助。
您可以在没有任何 for 循环或库函数的情况下做到这一点。攻略如下:
- 求最后2位递增序列的位置(
pivot
)
- 这两个数字中的第一个数字将被更高的数字取代
- 其余的将按照剩余数字的排序顺序 (
suffix
)
- 要使用的较高数字是剩余数字中比我们要替换的数字大的最小数字 (
digit
)
实现方法如下:
def nextPerm(N):
sN = list(str(N))
incPos = [i for i,d in enumerate(sN[:-1]) if d<sN[i+1]]
if not incPos: return None
pivot = incPos[-1]
suffix = sN[pivot:]
digit = min(d for d in suffix if d>sN[pivot])
suffix.remove(digit)
sN[pivot:] = [digit]+suffix[::-1]
return int("".join(sN))
输出:
n = 1234
while n:
print(n)
n = nextPerm(n)
1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321
也可以在不转换为字符串的情况下执行此操作:
def nextPerm(N):
suffix = []
while N:
N,digit = divmod(N,10)
suffix.append(digit)
if len(suffix)>1 and digit<suffix[-2]:
break
else: return
suffix = sorted(suffix)
swap = min(s for s in suffix if s>digit)
suffix.remove(swap)
for d in [swap]+suffix: N = N*10 + d
return N
它使用相同的策略,但使用除法运算而不是构建字符串数字列表来分解数字。
所以我有一个像 123 这样的数字,相同数字的立即数是 132。考虑另一个例子,数字是 1238,下一个立即数是 1283。所以对于这个逻辑,我已经实现了一个代码
def findnext(n):
ns=list(map(int,str(n)))
for i in reversed(range(len(ns))):
if i == 0: return n
if ns[i] > ns[i-1] :
break
left,right=ns[:i],ns[i:]
for k in reversed(range(len(right))):
if right[k]>left[-1]:
right[k],left[-1]=left[-1],right[k]
break
return int("".join(map(str,(left+sorted(right)))))
n=int(input())
print(findnext(n))
我需要一个不使用 itertools 的更优化或更精简代码的逻辑。请帮我!!提前致谢。
这与其说是一个 python 问题,不如说是一个逻辑问题。
根据我正确理解你的问题的方式,你需要使用相同的数字并找到最接近的数字。从逻辑上讲,这意味着大多数时候你想交换最后两位数字。但是,如果我这样做,最接近您的 1238
示例的是 1283
,距离是 1283-1238=45
而不是 `1328-1238=90,还是我错过了某种规则?
距离可以是双向的还是只有一个?
当我确定规则时,我(和其他人)可能会提供更多帮助。
您可以在没有任何 for 循环或库函数的情况下做到这一点。攻略如下:
- 求最后2位递增序列的位置(
pivot
) - 这两个数字中的第一个数字将被更高的数字取代
- 其余的将按照剩余数字的排序顺序 (
suffix
) - 要使用的较高数字是剩余数字中比我们要替换的数字大的最小数字 (
digit
)
实现方法如下:
def nextPerm(N):
sN = list(str(N))
incPos = [i for i,d in enumerate(sN[:-1]) if d<sN[i+1]]
if not incPos: return None
pivot = incPos[-1]
suffix = sN[pivot:]
digit = min(d for d in suffix if d>sN[pivot])
suffix.remove(digit)
sN[pivot:] = [digit]+suffix[::-1]
return int("".join(sN))
输出:
n = 1234
while n:
print(n)
n = nextPerm(n)
1234
1243
1324
1342
1423
1432
2134
2143
2314
2341
2413
2431
3124
3142
3214
3241
3412
3421
4123
4132
4213
4231
4312
4321
也可以在不转换为字符串的情况下执行此操作:
def nextPerm(N):
suffix = []
while N:
N,digit = divmod(N,10)
suffix.append(digit)
if len(suffix)>1 and digit<suffix[-2]:
break
else: return
suffix = sorted(suffix)
swap = min(s for s in suffix if s>digit)
suffix.remove(swap)
for d in [swap]+suffix: N = N*10 + d
return N
它使用相同的策略,但使用除法运算而不是构建字符串数字列表来分解数字。