★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(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,1
spa
【一遍扫描】算法
首先,咱们观察到对于任何给定序列的降序,没有可能的下一个更大的排列。
例如,如下数组不可能有下一个排列:
[9, 5, 4, 3, 1]
咱们须要从右边找到第一对两个连续的数字 a[i]a[i] 和 a[i-1]a[i−1],它们知足 a[i]>a[i-1]a[i]>a[i−1]。如今,没有对 a[i-1]a[i−1]右侧的从新排列能够建立更大的排列,由于该子数组由数字按降序组成。所以,咱们须要从新排列 a[i-1]a[i−1] 右边的数字,包括它本身。
如今,什么样的从新排列将产生下一个更大的数字?咱们想要建立比当前更大的排列。所以,咱们须要将数字 a[i-1]a[i−1] 替换为位于其右侧区域的数字中比它更大的数字,例如 a[j]a[j]。
咱们交换数字 a[i-1]a[i−1] 和 a[j]a[j]。咱们如今在索引 i-1i−1 处有正确的数字。 但目前的排列仍然不是咱们正在寻找的排列。咱们须要经过仅使用 a[i-1]a[i−1]右边的数字来造成最小的排列。 所以,咱们须要放置那些按升序排列的数字,以得到最小的排列。
可是,请记住,在从右侧扫描数字时,咱们只是继续递减索引直到咱们找到 a[i]a[i] 和 a[i-1]a[i−1] 这对数。其中,a[i] > a[i-1]a[i]>a[i−1]。所以,a[i-1]a[i−1] 右边的全部数字都已按降序排序。此外,交换 a[i-1]a[i−1] 和 a[j]a[j] 并未改变该顺序。所以,咱们只须要反转 a[i-1]a[i−1] 以后的数字,以得到下一个最小的字典排列。
下面的动画将有助于你理解:
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 }