查找多个相同数字的立即数的优化或最佳方法

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

它使用相同的策略,但使用除法运算而不是构建字符串数字列表来分解数字。