Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add next permutation problem #720

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,7 @@ Read our [Contribution Guidelines](CONTRIBUTING.md) before you contribute.

1. [`GenerateElementSet`](./math/permutation/heaps.go#L37): No description provided.
2. [`Heaps`](./math/permutation/heaps.go#L8): Heap's Algorithm for generating all permutations of n objects
3. [`NextPermutation`](./math/permutation/next_permutation.go#8): A solution to find next permutation of an integer array in constant memory

---
</details><details>
Expand Down
37 changes: 37 additions & 0 deletions math/permutation/next_permutation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// A practice to find lexicographically next greater permutation of the given array of integers.
// If there does not exist any greater permutation, then print the lexicographically smallest permutation of the given array.
// The implementation below, finds the next permutation in linear time and constant memory and returns in place
// Useful reference: https://www.geeksforgeeks.org/next-permutation/

package permutation

func NextPermutation(nums []int) {
pivot := 0
for pivot = len(nums) - 2; pivot >= 0; pivot-- {
if nums[pivot] < nums[pivot+1] {
break
}
}
if pivot < 0 {
// current permutation is the last and must be reversed totally
for l, r := 0, len(nums)-1; l < r; l, r = l+1, r-1 {
nums[l], nums[r] = nums[r], nums[l]
}
} else {
succ := 0
for succ = len(nums) - 1; succ > pivot; succ = succ - 1 {
if nums[succ] > nums[pivot] {
break
}
}

// Swap the pivot and successor
nums[pivot], nums[succ] = nums[succ], nums[pivot]

// Reverse the suffix part to minimize it
for l, r := pivot+1, len(nums)-1; l < r; l, r = l+1, r-1 {
nums[l], nums[r] = nums[r], nums[l]
}
}

}
40 changes: 40 additions & 0 deletions math/permutation/next_permutation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package permutation

import (
"reflect"
"testing"
)

func TestNextPermutation(t *testing.T) {
var nextPermutationTestData = []struct {
description string
numbers []int
next []int
}{
{
description: "Basic case",
numbers: []int{1, 2, 3},
next: []int{1, 3, 2},
},
{
description: "Should reverse the whole slice",
numbers: []int{3, 2, 1},
next: []int{1, 2, 3},
},
{
description: "A more complex test",
numbers: []int{2, 4, 1, 7, 5, 0},
next: []int{2, 4, 5, 0, 1, 7},
},
}
for _, test := range nextPermutationTestData {
t.Run(test.description, func(t *testing.T) {
NextPermutation(test.numbers)

if !reflect.DeepEqual(test.numbers, test.next) {
t.Logf("FAIL: %s", test.description)
t.Fatalf("Expected result:%v\nFound: %v", test.next, test.numbers)
}
})
}
}
Loading