|
| 1 | +// https://leetcode.com/problems/next-permutation/discuss/1554932/Go-Submission-with-Explanation |
| 2 | +// Time O(N) , Space: O(1) |
| 3 | + |
1 | 4 | package leetcode
|
2 | 5 |
|
| 6 | +// [2,(3),6,5,4,1] -> 2,(4),6,5,(3),1 -> 2,4, 1,3,5,6 |
3 | 7 | func nextPermutation(nums []int) {
|
4 |
| - i, j := 0, 0 |
5 |
| - for i = len(nums) - 2; i >= 0; i-- { |
6 |
| - if nums[i] < nums[i+1] { |
7 |
| - break |
8 |
| - } |
| 8 | + var n = len(nums) |
| 9 | + var pIdx = checkPermutationPossibility(nums) |
| 10 | + if pIdx == -1 { |
| 11 | + reverse(nums, 0, n-1) |
| 12 | + return |
9 | 13 | }
|
10 |
| - if i >= 0 { |
11 |
| - for j = len(nums) - 1; j > i; j-- { |
12 |
| - if nums[j] > nums[i] { |
13 |
| - break |
14 |
| - } |
| 14 | + |
| 15 | + var rp = len(nums) - 1 |
| 16 | + // start from right most to leftward,find the first number which is larger than PIVOT |
| 17 | + for rp > 0 { |
| 18 | + if nums[rp] > nums[pIdx] { |
| 19 | + swap(nums, pIdx, rp) |
| 20 | + break |
| 21 | + } else { |
| 22 | + rp-- |
15 | 23 | }
|
16 |
| - swap(&nums, i, j) |
17 | 24 | }
|
18 |
| - reverse(&nums, i+1, len(nums)-1) |
| 25 | + // Finally, Reverse all elements which are right from pivot |
| 26 | + reverse(nums, pIdx+1, n-1) |
19 | 27 | }
|
20 | 28 |
|
21 |
| -func reverse(nums *[]int, i, j int) { |
22 |
| - for i < j { |
23 |
| - swap(nums, i, j) |
24 |
| - i++ |
25 |
| - j-- |
| 29 | +func swap(nums []int, i, j int) { |
| 30 | + nums[i], nums[j] = nums[j], nums[i] |
| 31 | +} |
| 32 | + |
| 33 | +func reverse(nums []int, s int, e int) { |
| 34 | + for s < e { |
| 35 | + swap(nums, s, e) |
| 36 | + s++ |
| 37 | + e-- |
26 | 38 | }
|
27 | 39 | }
|
28 | 40 |
|
29 |
| -func swap(nums *[]int, i, j int) { |
30 |
| - (*nums)[i], (*nums)[j] = (*nums)[j], (*nums)[i] |
| 41 | +// checkPermutationPossibility returns 1st occurrence Index where |
| 42 | +// value is in decreasing order(from right to left) |
| 43 | +// returns -1 if not found(it's already in its last permutation) |
| 44 | +func checkPermutationPossibility(nums []int) (idx int) { |
| 45 | + // search right to left for 1st number(from right) that is not in increasing order |
| 46 | + var rp = len(nums) - 1 |
| 47 | + for rp > 0 { |
| 48 | + if nums[rp-1] < nums[rp] { |
| 49 | + idx = rp - 1 |
| 50 | + return idx |
| 51 | + } |
| 52 | + rp-- |
| 53 | + } |
| 54 | + return -1 |
31 | 55 | }
|
0 commit comments