Skip to content

Commit 23aacae

Browse files
Add 'Next Permutation'
1 parent 7019e32 commit 23aacae

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ A collection of LeetCode solutions
7272

7373
[Minimum Window Substring](./src/minimum_window_substring.py)
7474

75+
[Next Permutation](./src/next_permutation.py)
76+
7577
[Palindromic Substrings](./src/palindromic_substrings.py)
7678

7779
[Permutation in String](./src/permutation_in_string.py)

src/next_permutation.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"""
2+
31. Next Permutation
3+
4+
https://leetcode.com/problems/next-permutation
5+
6+
NOTES
7+
* Use a special algorithm. You just need to know how to do this one.
8+
9+
Definitions
10+
-----------
11+
A permutation of an array of integers is an arrangement of its members into a
12+
sequence or linear order.
13+
14+
For example, all permutations of the array [1, 2, 3] are:
15+
16+
[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]
17+
18+
The next permutation of an array of integers is the next lexicographically
19+
greater permutation of its integers. If the arrangement for the next possible
20+
permutation does not exist, the next permutation is the first (lowest)
21+
permutation.
22+
23+
NOTE: A list of length n has n! permutations, so enumerating all possible
24+
permutations has O(n!) time complexity.
25+
26+
Algorithm
27+
---------
28+
First, observe that for a sequence that is in descending order, no next larger
29+
permutation is possible.
30+
31+
[5, 4, 3, 2, 1]
32+
33+
So, the next permutation is the reverse of the final permutation.
34+
35+
[1, 2, 3, 4, 5]
36+
37+
Next, let's take a look at the permutation before the final permutation:
38+
39+
[5, 4, 3, 1, 2]
40+
41+
To get the final permutation we swap 1 and 2. In fact 1 and 2 are the first
42+
pair of successive numbers which satisfy the condition a[i] > a[i-1]. This is
43+
another key insight:
44+
45+
>Given a starting permutation of `a`, the first pair of two successive
46+
numbers a[i] and a[i−1], which satisfy the condition a[i] > a[i−1] found by
47+
traversing the array from the right, demarcate the start of the next
48+
permutation. We can assert that a[i...n-1] are in descending order.
49+
50+
In order to get the next permutation, we need to replace a[i-1] with the next
51+
larger number in a[i...n-1]. Said another way, we need to find the smallest
52+
value a[i...n-1] that is larger than a[i-1]. We will call this value a[j].
53+
Swapping these values, a[i-1] and a[j], puts the correct value at index i - 1.
54+
55+
Next, the sequence a[i...n-1] needs to be rearranged into the lowest possible
56+
permutation, which is formed by putting its values in ascending order. However,
57+
since we have already asserted that a[i...n-1] are in descending order, we just
58+
have to reverse the sequence (an O(n) operation).
59+
"""
60+
61+
62+
class Solution:
63+
def nextPermutation(self, nums: list[int]) -> None:
64+
"""
65+
Do not return anything, modify nums in-place instead.
66+
67+
1. Find the pivot: Scan from right to left to find the first index i−1
68+
such that nums[i−1] < nums[i].
69+
70+
2. Swap with a just‐larger element: From the right again, find the
71+
first index j where nums[j] > nums[i−1]. Swap nums[i−1] and nums[j].
72+
73+
3. Reverse the suffix: Finally, reverse the subarray nums[i...n−1].
74+
"""
75+
n = len(nums)
76+
if n <= 1:
77+
return None
78+
79+
i = n - 1
80+
81+
# Find `i` which satisfies the condition nums[i−1] < nums[i].
82+
while i > 0 and nums[i - 1] >= nums[i]:
83+
i -= 1
84+
85+
# Find the first value in nums[i...n-1], where nums[j] > nums[i-1].
86+
if i > 0:
87+
j = n - 1
88+
while nums[j] <= nums[i - 1]:
89+
j -= 1
90+
# Swap nums[i-1] and nums[j].
91+
nums[i - 1], nums[j] = nums[j], nums[i - 1]
92+
93+
# Reverse nums[i...n-1].
94+
k = n - 1
95+
while i < k:
96+
nums[i], nums[k] = nums[k], nums[i]
97+
i += 1
98+
k -= 1
99+
100+
return None

tests/test_next_permutation.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""
2+
31. Next Permutation
3+
4+
https://leetcode.com/problems/next-permutation
5+
"""
6+
7+
from unittest import TestCase
8+
9+
from src.next_permutation import Solution
10+
11+
12+
class TestSolution(TestCase):
13+
def test_1(self):
14+
exp, nums = [1, 3, 2], [1, 2, 3]
15+
Solution().nextPermutation(nums)
16+
assert nums == exp
17+
18+
def test_2(self):
19+
exp, nums = [1, 2, 3], [3, 2, 1]
20+
Solution().nextPermutation(nums)
21+
assert nums == exp
22+
23+
def test_3(self):
24+
exp, nums = [1, 5, 1], [1, 1, 5]
25+
Solution().nextPermutation(nums)
26+
assert nums == exp
27+
28+
def test_4(self):
29+
exp, nums = [5, 1, 1], [1, 5, 1]
30+
Solution().nextPermutation(nums)
31+
assert nums == exp

0 commit comments

Comments
 (0)