最近從《程式設計謎題》上面看到一道很有意思的題目,這裡摘錄一下大意:
題目概述:
有n組資料,每組資料給出m和m個數(每個數之間用空格隔開),這m個數組成乙個m位數,請你求出下乙個比當前m位數大的排列組成的m位數
若是沒有,請輸出-1
輸入樣例:24
1 2 3 4
33 2 1
輸出樣例:
1243
-1還是那句話:看到這裡請自行思考10分鐘左右。
解法1.暴力
思路:求出這m個數的全排列,然後找到給定的資料,下乙個就是答案了
這裡設定乙個標記變數flag,如果都沒有找到就輸出-1。
時間複雜度:省去常數複雜度 o(n!)
**這裡就不貼了,想寫的童鞋可以自己練練手
好像還可以有乙個遞迴檢索法(我自己發明的【笑】)
就是對於每一位數都可以通過遞迴找到全排列中的位置
2.「數學解法」
這裡還是乙個所謂的數學解法
這裡比較玄學,我盡量講明白吧。
先來看解題步驟,最後再解釋:
拿序列3 4 2 1舉例子
1.從右往左找到第乙個反遞增的數a,將這個數所在的位置(下標)記為pos
在這個例子裡頭,a=3,pos=1
2.從右到左找到比a大的第乙個數b
在這裡,b=4
3.交換a和b
例子中的序列就變成了:4 3 2 1
4.將pos右邊的所有數都翻轉(最後一位變為第一位,倒數第二位變為第二位……)
例子中的序列就變成了4 1 2 3
此時的序列就是所求的解
怎麼樣,玄學吧【笑】
看到這裡,還是請自行思考5~10分鐘
一步一步理解(也可以畫圖,也可以論證,理解就行)
我的理解
我理解了蠻久,大概也是10min這樣才看懂。
第一步,找到a和pos
我們反過來理解,a是右到左反遞增數,那麼說,從右到左在pos之前的一直都是保持遞增的序列
ps:如果沒找到就直接輸出-1,自己想想為什麼
第二步,找到b
這一步還是要連著第三步一起講
第三步:交換a和b
這一步就是使新得到的序列比原序列大,連第二步來說,就是讓新的到的序列在其他比原序列大的序列中盡可能小,因為b是第乙個比a大的數
第四步:pos後面的翻轉
因為pos後的都是遞增,翻轉後就也是遞增,不過方向不一樣,翻轉後的遞增是使b為關鍵的序列最小
我盡力解釋清楚了
如果不相信諸位可以自己再試試
**太簡單也不貼了
演算法題 下乙個排列
實現獲取下乙個排列的函式,演算法需要將給定數字序列重新排列成字典序中下乙個更大的排列。如果不存在下乙個更大的排列,則將數字重新排列成最小的排列 即公升序排列 必須原地修改,只允許使用額外常數空間。以下是一些例子,輸入位於左側列,其相應輸出位於右側列。1,2,3 1,3,2 3,2,1 1,2,3 1...
leetcode第31題下乙個排列
實現獲取下乙個排列的函式,演算法需要將給定數字序列重新排列成字典序中下乙個更大的排列。如果不存在下乙個更大的排列,則將數字重新排列成最小的排列 即公升序排列 必須原地修改,只允許使用額外常數空間。以下是一些例子,輸入位於左側列,其相應輸出位於右側列。1,2,3 1,3,2 3,2,1 1,2,3 1...
leetcode 第31題 下乙個排列
實現獲取 下乙個排列 的函式,演算法需要將給定數字序列重新排列成字典序中下乙個更大的排列。如果不存在下乙個更大的排列,則將數字重新排列成最小的排列 即公升序排列 必須 原地 修改,只允許使用額外常數空間。示例 1 輸入 nums 1,2,3 輸出 1,3,2 示例 2 輸入 nums 3,2,1 輸...