題目描述:給定一個整數 X,找到組成的數字和 X 完全相同的,且大於 X 的最小的那個數。
-
輸入要求
一個整數 X,不會以0開頭。
-
輸出要求
輸出與 X 數字組成完全相同,且大於 X 的最小的數。若不存在這樣的數,輸出 0
-
例如,輸入 156 輸出 165,或者 27711 就是 71127,330 的話就是 0
思路:題目有三大約束:a. 組成與 X 相同 b. 大於 X c. 最小
針對 a,可以交換 X 的各個位;對於 b,變動的最高位必須比原來大;對於 c,變動的最高位越接近個位越好
1. 暴力法
窮舉所有可能的數,然后在大於 X 的里面找最小
2. 反向掃描
從個位開始逆向遍歷,向后掃描,找出比自己大的所有位,選擇其中最小的,交換之,然后排序,done
如字符串 s="263861",序號為 0~5
s[4] = 6,后面沒有比自己大的
s[3] = 8,同上
s[2] = 3,后面比自己大但最小的數是 6,交換 s[2]和s[4]
從小到大排序 s[3]~s[5] [注]:因為當前字符后的序列總是降序的,且交換后仍可保持降序,充分利用這一點能有效提高算法效率。故此處無需排序。
所以,最終結果為 266138
實現:
#!/usr/bin/env python
#coding=utf8
def test(num):
text = str(num)
rtext = list(text[::-1]) #反轉字符串以方便遍歷
for i in xrange(1, len(rtext)):
if rtext[i] < rtext[i-1]: #減少無效比較次數
gts = [x for x in rtext[:i] if x > rtext[i]] #找到比自己大的所有位
j = rtext.index(min(gts)) #選擇其中最小的
rtext[i], rtext[j] = rtext[j], rtext[i] #交換之
return ''.join(rtext[i:][::-1] + rtext[:i])
return '0'
if __name__ == "__main__":
from timeit import Timer
num = input("Input a number: ")
t1 = Timer("test(num)", "from __main__ import test, num")
print t1.timeit(1000) #運行1000次所需秒數
