Skip to content

Commit ca3f19a

Browse files
authored
Merge pull request #12 from rihib/next_permutation
Next Permutation
2 parents f4f6ff8 + 9cb86d6 commit ca3f19a

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//lint:file-ignore U1000 Ignore all unused code
2+
package nextpermutation
3+
4+
import "sort"
5+
6+
/*
7+
時間:36分
8+
解法を思いつくのに時間がかかってしまいました(15分ぐらい)。
9+
後ろから見ていって昇順になっていない箇所を見つけたら、nums[i-1]よりも大きい中で最小の値を見つけてスワップし、後ろの要素をソートするというやり方を取りました。
10+
*/
11+
func nextPermutation_step1(nums []int) {
12+
for i := len(nums) - 1; i > 0; i-- {
13+
if nums[i-1] < nums[i] {
14+
minN := nums[i]
15+
idx := i
16+
for j := i; j < len(nums); j++ {
17+
if nums[j] < minN && nums[i-1] < nums[j] {
18+
idx = j
19+
minN = nums[j]
20+
}
21+
}
22+
nums[i-1], nums[idx] = nums[idx], nums[i-1]
23+
sort.Slice(nums[i:], func(a, b int) bool {
24+
return nums[i+a] < nums[i+b]
25+
})
26+
return
27+
}
28+
}
29+
sort.Slice(nums, func(a, b int) bool {
30+
return nums[a] < nums[b]
31+
})
32+
}
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//lint:file-ignore U1000 Ignore all unused code
2+
package nextpermutation
3+
4+
import "sort"
5+
6+
/*
7+
変数名などをリファクタしました。
8+
*/
9+
func nextPermutation_step2(nums []int) {
10+
for i := len(nums) - 1; i > 0; i-- {
11+
if nums[i-1] < nums[i] {
12+
candidate, candidateIndex := nums[i], i
13+
for j := i; j < len(nums); j++ {
14+
if nums[j] < candidate && nums[i-1] < nums[j] {
15+
candidate, candidateIndex = nums[j], j
16+
}
17+
}
18+
nums[i-1], nums[candidateIndex] = nums[candidateIndex], nums[i-1]
19+
sort.Slice(nums[i:], func(a, b int) bool {
20+
return nums[i+a] < nums[i+b]
21+
})
22+
return
23+
}
24+
}
25+
sort.Slice(nums, func(a, b int) bool {
26+
return nums[a] < nums[b]
27+
})
28+
}
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//lint:file-ignore U1000 Ignore all unused code
2+
package nextpermutation
3+
4+
/*
5+
これまでの解法がソートを使っていたために時間計算量がO(n log n)になってしまったわけですが、他の人の回答を見てO(n)で解ける方法に変えました。
6+
nums[i-1]よりも後ろは昇順になっているのを利用し、リバースすればソートできるということに気づきませんでした。
7+
*/
8+
func nextPermutation_step3(nums []int) {
9+
if len(nums) < 2 {
10+
return
11+
}
12+
i := len(nums) - 2
13+
for i >= 0 && nums[i] >= nums[i+1] {
14+
i--
15+
}
16+
if i >= 0 {
17+
j := len(nums) - 1
18+
for nums[j] <= nums[i] {
19+
j--
20+
}
21+
nums[i], nums[j] = nums[j], nums[i]
22+
}
23+
reverse(nums[i+1:])
24+
}
25+
26+
func reverse(nums []int) {
27+
for i, j := 0, len(nums)-1; i < j; i, j = i+1, j-1 {
28+
nums[i], nums[j] = nums[j], nums[i]
29+
}
30+
}

0 commit comments

Comments
 (0)