[Swift]LeetCode31. 下一個排列 | Next Permutation

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-cgzdpsqo-me.html 
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.git

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).github

The replacement must be in-place and use only constant extra memory.算法

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.數組

1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1微信


實現獲取下一個排列的函數,算法須要將給定數字序列從新排列成字典序中下一個更大的排列。ide

若是不存在下一個更大的排列,則將數字從新排列成最小的排列(即升序排列)。函數

必須原地修改,只容許使用額外常數空間。動畫

如下是一些例子,輸入位於左側列,其相應輸出位於右側列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1spa


 【一遍掃描】算法

首先,咱們觀察到對於任何給定序列的降序,沒有可能的下一個更大的排列。

例如,如下數組不可能有下一個排列:

[9, 5, 4, 3, 1]

咱們須要從右邊找到第一對兩個連續的數字 a[i]a[i] 和 a[i-1]a[i1],它們知足 a[i]>a[i-1]a[i]>a[i1]。如今,沒有對 a[i-1]a[i1]右側的從新排列能夠建立更大的排列,由於該子數組由數字按降序組成。所以,咱們須要從新排列 a[i-1]a[i1] 右邊的數字,包括它本身。

如今,什麼樣的從新排列將產生下一個更大的數字?咱們想要建立比當前更大的排列。所以,咱們須要將數字 a[i-1]a[i1] 替換爲位於其右側區域的數字中比它更大的數字,例如 a[j]a[j]。

 Next Permutation

咱們交換數字 a[i-1]a[i1] 和 a[j]a[j]。咱們如今在索引 i-1i1 處有正確的數字。 但目前的排列仍然不是咱們正在尋找的排列。咱們須要經過僅使用 a[i-1]a[i1]右邊的數字來造成最小的排列。 所以,咱們須要放置那些按升序排列的數字,以得到最小的排列。

可是,請記住,在從右側掃描數字時,咱們只是繼續遞減索引直到咱們找到 a[i]a[i] 和 a[i-1]a[i1] 這對數。其中,a[i] > a[i-1]a[i]>a[i1]。所以,a[i-1]a[i1] 右邊的全部數字都已按降序排序。此外,交換 a[i-1]a[i1] 和 a[j]a[j] 並未改變該順序。所以,咱們只須要反轉 a[i-1]a[i1] 以後的數字,以得到下一個最小的字典排列。

下面的動畫將有助於你理解:


Next Permutation


 24ms


1
class Solution { 2 func nextPermutation(_ nums: inout [Int]) { 3 let len:Int = nums.count 4 var i:Int = len - 2 5 while (i >= 0 && nums[i + 1] <= nums[i]) {i -= 1} 6 if i >= 0 7 { 8 var j:Int = len - 1 9 while (j >= 0 && nums[j] <= nums[i]) {j -= 1} 10 swap(&nums, i, j) 11 } 12 reverse(&nums, i + 1) 13 } 14 15 func reverse(_ nums:inout [Int],_ start:Int) 16 { 17 var i:Int = start, j:Int = nums.count - 1 18 while (i < j) 19 { 20 swap(&nums, i, j) 21 i += 1 22 j -= 1 23 } 24 } 25 26 func swap(_ nums:inout [Int],_ i:Int,_ j:Int) 27 { 28 var temp:Int = nums[i] 29 nums[i] = nums[j] 30 nums[j] = temp 31 } 32 }

12ms

 1 class Solution {
 2     func nextPermutation(_ nums: inout [Int]) {
 3         if nums.count <= 1 { return }
 4         var ind = -1
 5         for i in (0..<(nums.count-1)).reversed() {
 6             if nums[i] < nums[i+1] {
 7                 ind = i
 8                 break
 9             }
10         }
11         if ind == -1 { 
12             nums = nums.reversed() 
13             return
14         }
15         let ind1 = ind
16         var temp = nums[ind+1]
17         var ind2 = ind+1
18         while ind < nums.count {
19             if nums[ind] > nums[ind1] && nums[ind] <= temp { 
20                 ind2 = ind
21                 temp = nums[ind]
22             }
23             ind += 1
24         }
25         (nums[ind1], nums[ind2]) = (nums[ind2], nums[ind1])
26         nums = Array(nums[0...ind1]) + Array(nums[(ind1+1)..<nums.count]).reversed()
27     }
28 }

16ms

 1 class Solution {
 2     func nextPermutation(_ nums: inout [Int]) {
 3         guard let violateIndex = findViolate(nums) else {
 4             nums.reverse()
 5             return
 6         }
 7         
 8         swap(&nums, violateIndex, findLeastGreater(nums, violateIndex))
 9         nums = nums[0...violateIndex] + nums[(violateIndex + 1)...].reversed()
10     }
11     
12     fileprivate func findViolate(_ nums: [Int]) -> Int? {
13         for i in (1..<nums.count).reversed() {
14             if nums[i] > nums[i - 1] {
15                 return i - 1
16             }
17         }
18         
19         return nil
20     }
21     
22     fileprivate func findLeastGreater(_ nums: [Int], _ violateIndex: Int) -> Int {
23         for i in (violateIndex + 1..<nums.count).reversed() {
24             if nums[i] > nums[violateIndex] {
25                 return i
26             }
27         }
28         
29         fatalError()
30     }
31     
32     fileprivate func swap<T>(_ nums: inout [T], _ indexL: Int, _ indexR: Int) {
33         (nums[indexL], nums[indexR]) = (nums[indexR], nums[indexL])
34     }
35 }

16ms

 1 class Solution {
 2     func nextPermutation(_ nums: inout [Int]) {
 3         
 4         guard nums.count > 1 else {
 5             return
 6         }
 7         
 8         for i in (0 ..< nums.count - 1).reversed() {
 9             
10             var lowestDiff = -1
11             var lowestIndex = -1
12             
13             for j in (i+1 ..< nums.count) {
14                
15                 let diff = nums[j] - nums[i]
16                 
17                 if diff > 0 && (diff < lowestDiff || lowestDiff == -1) {
18                     lowestDiff = diff
19                     lowestIndex = j
20                 }
21             }
22             
23             if (lowestIndex >= 0) {
24                 print("swap \(nums[i]) \(nums[lowestIndex])")
25                 swap(&nums, i, lowestIndex)
26                 nums[i+1..<nums.count].sort()
27                 return
28             }
29         }
30         
31         for i in (0 ..< nums.count / 2) {
32             swap(&nums, i, nums.count - i - 1)
33         }
34     }
35     
36     func swap(_ nums: inout [Int], _ i: Int, _ j: Int) {
37         let tmp = nums[i]
38         nums[i] = nums[j]
39         nums[j] = tmp
40     }
41 }

20ms

 1 class Solution {
 2     func nextPermutation(_ nums: inout [Int]) {
 3         
 4         var end = nums.count - 1
 5        
 6         while end > 0 {
 7             if nums[end - 1] < nums[end] {
 8                 break
 9             }
10             end -= 1
11         }
12         
13         if end == 0 {
14             for i in 0..<nums.count / 2 {
15                 nums.swapAt(i, nums.count - 1 - i)
16             }
17         } else {
18             end -= 1
19             var i = nums.count - 1
20             while i > end {
21                 if nums[i] > nums[end] {
22                     break
23                 }
24                 i -= 1
25             }
26             
27             nums.swapAt(i, end)
28             
29             for i in 0..<(nums.count - end) / 2 {
30                 nums.swapAt(end + 1 + i, nums.count - 1 - i)
31             } 
32         }
33     }
34 }

20ms

 1 class Solution {
 2     func nextPermutation(_ nums: inout [Int]) {
 3         
 4         let size = nums.count
 5         
 6         //數組爲空或只有一個數
 7         if size == 0 || size == 1 {
 8             return
 9         }
10         
11         //只有兩個數直接交換
12         if size == 2 {
13             nums.swapAt(0, 1)
14             return
15         }
16         
17         //判斷大小交換位置
18         for index in stride(from: size-1, through: 1, by: -1) {
19             
20             if nums[index] > nums[index - 1] {
21                 
22                 for subIndex in stride(from: size-1, through: index, by: -1) {
23                     
24                     if nums[subIndex] > nums[index-1] {
25                         
26                         nums.swapAt(index-1, subIndex)
27                         break
28                     }
29                 }
30                 
31                 for tmpIndex in stride(from: (size-1-index)/2, through: 0, by: -1) {
32                     
33                     nums.swapAt(tmpIndex + index, size - 1 - tmpIndex)
34                 }
35                 
36                 return
37                 
38             }
39         }
40         
41         //降序排列好,直接逆序
42         for index in stride(from: (size-1)/2, through: 0, by: -1) {
43             
44             nums.swapAt(index, size-1-index)
45         }
46     }
47 }

24ms

 1 class Solution {
 2     func nextPermutation(_ nums: inout [Int]) {
 3         
 4         guard nums.count > 1 else {
 5             return
 6         }
 7         
 8         for i in (0 ..< nums.count - 1).reversed() {
 9             
10             var lowestDiff = -1
11             var lowestIndex = -1
12             
13             for j in (i+1 ..< nums.count) {
14                
15                 let diff = nums[j] - nums[i]
16                 
17                 if diff > 0 && (diff < lowestDiff || lowestDiff == -1) {
18                     lowestDiff = diff
19                     lowestIndex = j
20                 }
21             }
22             
23             if (lowestIndex >= 0) {
24                 print("swap \(nums[i]) \(nums[lowestIndex])")
25                 swap(&nums, i, lowestIndex)
26                 nums[i+1..<nums.count].sort()
27                 return
28             }
29         }
30         
31         for i in (0 ..< nums.count / 2) {
32             swap(&nums, i, nums.count - i - 1)
33         }
34     }
35     
36     func swap(_ nums: inout [Int], _ i: Int, _ j: Int) {
37         let tmp = nums[i]
38         nums[i] = nums[j]
39         nums[j] = tmp
40     }
41 }

28ms

 1 class Solution {
 2     func nextPermutation(_ nums: inout [Int]) {
 3         if nums.count < 2 {
 4             return
 5         }
 6         
 7         var max = nums[nums.count - 1]
 8         var i = nums.count - 2
 9         while i >= 0 {
10             if nums[i] < max {
11                 break
12             }
13             max = nums[i]
14             i = i - 1
15         }
16         if i < 0 {
17             nums.sort()
18             return
19         }
20         var x = nums[i]
21         nums[(i+1)...].sort()
22         var left = i + 1
23         var right = nums.index(before: nums.endIndex)
24         
25         while right > (left + 1) {
26             var m = left + (right - left) / 2
27             if nums[m] <= x {
28                 left = m
29             } else {
30                 right = m
31             }
32         }
33       
34         var ind = (x < nums[left]) ? left : right
35         nums[i] = nums[ind]
36         nums[ind] = x
37     }
38 }

32ms

 1 class Solution {
 2     func nextPermutation(_ nums: inout [Int]) {
 3         var toSwap = -1
 4         
 5         if nums.count <= 1 {
 6             return
 7         }
 8         
 9         for index in (1...nums.count - 1).reversed() {
10             if nums[index] > nums[index - 1] {
11                 toSwap = index - 1
12                 break
13             }
14         }
15         
16         if toSwap != -1 {
17             var min = Int.max, swapIndex = toSwap
18             for index in (toSwap + 1...nums.count - 1).reversed() {
19                 if nums[index] < min && nums[index] > nums[toSwap] {
20                     swapIndex = index
21                     min = nums[index]
22                 }
23             }
24             nums.swapAt(toSwap, swapIndex)
25             nums[toSwap + 1...nums.count - 1].reverse()
26         } else {
27             nums.reverse()
28         }
29     }
30 }

36ms

 1 class Solution {
 2     func nextPermutation(_ nums: inout [Int]) {
 3         //no arrangement possible
 4         if(nums.sorted().reversed() == nums){
 5             nums = nums.sorted()
 6             return
 7         }
 8         let n = nums.count
 9         var position = -1
10         for i in (0 ..< n - 1).reversed() {
11             print(i)
12             if nums[i] < nums[i + 1] {
13                 position = i
14                 break
15             }
16         }
17         var indexToSwap = -1
18         var diff = Int.max
19         
20         
21         for j in (position+1 ..< n).reversed() {
22             let d =  nums[j] - nums[position]
23                 if d < diff && d > 0 {
24                     indexToSwap = j
25                     diff = d
26                 }
27             }
28         nums.swapAt(position, indexToSwap)
29         nums = nums[0 ... position] + nums[position + 1 ... nums.count - 1].reversed()
30         
31         
32         
33         
34         
35     }
36 }

44ms

 1 class Solution {
 2     func nextPermutation(_ nums: inout [Int]) {
 3         if nums.count < 2 {
 4             return
 5         }
 6         
 7         var max = nums[nums.count - 1]
 8         var i = nums.count - 2
 9         while i >= 0 {
10             if nums[i] < max {
11                 break
12             }
13             max = nums[i]
14             i = i - 1
15         }
16         if i < 0 {
17             nums.sort()
18             return
19         }
20         var x = nums[i]
21         nums[(i+1)...].sort()
22         var left = i + 1
23         var right = nums.index(before: nums.endIndex)
24         
25         while right > left {
26             var m = left + (right - left) / 2
27             if nums[m] <= x {
28                 if nums[m+1] > x {
29                     left = m
30                     right = m + 1
31                     break
32                 }
33                 left = m + 1
34             } else {
35                 if nums[m-1] <= x {
36                     left = m - 1
37                     right = m
38                     break
39                 }
40                 right = m - 1
41             }
42         }
43       
44         nums[i] = nums[right]
45         nums[right] = x
46     }
47 }

48ms

 1 class Solution {
 2     func nextPermutation(_ nums: inout [Int]) {
 3         var left = 0
 4         var right = nums.count - 1
 5         for i in (0 ..< nums.count - 1).reversed() {
 6             if nums[i] >= nums[i + 1] {
 7                 continue
 8             } else {
 9                 left = i
10                 break
11             }
12         }
13         
14         var nextIndex = 0
15         for i in (0 ..< nums.count).reversed() {
16             if nums[i] > nums[left] {
17                 nextIndex = i 
18                 break
19             }
20         }
21 
22         nums.swapAt(left, nextIndex)
23         if nextIndex != 0 {
24             left += 1
25         }
26         while left < right {
27             nums.swapAt(left, right)
28             left += 1
29             right -= 1
30         }
31     }
32 }
相關文章
相關標籤/搜索