英文:
Golang: Counting Inversions Sorting issue
问题
我最近开始尝试使用Golang。我正在尝试编写一个程序,用于计算给定切片中逆序对的数量,但是我遇到了一个问题。
我正在尝试使用基于MergeSort的代码对切片进行排序,但是我的代码似乎无法正确地对切片进行排序。我假设最终的切片必须被排序才能正确地计算逆序对的数量,但是我不知道如何做到这一点。我可以在这个问题上得到一些帮助吗?
func InversionCount(a []int) int {
if len(a) <= 1 {
return 0
}
mid := len(a) / 2
left := a[:mid]
right := a[mid:]
leftCount := InversionCount(left)
rightCount := InversionCount(right)
res := make([]int, 0, len(right)+len(left)) //用于保存排序后的左侧和右侧切片的临时切片
iCount := mergeCount(left, right, &res)
a = res //将结果复制回原始切片
fmt.Println(a) //为什么"a"没有被排序?
return iCount + leftCount + rightCount
}
func mergeCount(left, right []int, res *[]int) int {
count := 0
for len(left) > 0 || len(right) > 0 {
if len(left) == 0 {
*res = append(*res, right...)
break
}
if len(right) == 0 {
*res = append(*res, left...)
break
}
if left[0] <= right[0] {
*res = append(*res, left[0])
left = left[1:]
} else { //找到了逆序对
count += 1
*res = append(*res, right[0])
right = right[1:]
}
}
return count
}
func main() {
s := []int{4, 3, 2, 1}
fmt.Print(InversionCount(s))
}
这是我的代码链接:http://play.golang.org/p/QSJyg_qadD
英文:
I have recently started experimenting with Golang. I'm trying to write a program which counts the number of inversions with a given slice, but I have ran into an issue.
I'm trying to sort the slice using code based off MergeSort, but my code does not seem to sort the slice properly. I'm assuming that the final slice has to be sorted for the inversion count to work correctly, but I don't know how to do this. Can I get some help on this issue?
func InversionCount(a []int) int {
if len(a) <= 1 {
return 0
}
mid := len(a) / 2
left := a[:mid]
right := a[mid:]
leftCount := InversionCount(left)
rightCount := InversionCount(right)
res := make([]int, 0, len(right)+len(left)) //temp slice to hold the sorted left side and right side
iCount := mergeCount(left, right, &res)
a = res //Copies the result back into the original slice
fmt.Println(a) //Why hasn't "a" been sorted?
return iCount + leftCount + rightCount
}
func mergeCount(left, right []int, res *[]int) int {
count := 0
for len(left) > 0 || len(right) > 0 {
if len(left) == 0 {
*res = append(*res, right...)
break
}
if len(right) == 0 {
*res = append(*res, left...)
break
}
if left[0] <= right[0] {
*res = append(*res, left[0])
left = left[1:]
} else { //Inversion has been found
count += 1
*res = append(*res, right[0])
right = right[1:]
}
}
return count
}
func main() {
s := []int{4, 3, 2, 1}
fmt.Print(InversionCount(s))
}
Here is a link to my code: http://play.golang.org/p/QSJyg_qadD
答案1
得分: 3
你需要将以下代码行替换为:
count += len(left)
关键在于,在mergeCount
的任何一点上,如果left[0] > right[0]
,那么由于left
已经排序,left中剩余的所有元素相对于right[0]
都是倒置的。如果你这样做,你将得到正确的计数。
你的排序不起作用是另一个问题。如果你想修复它,我建议先删除所有的计数逻辑,只尝试修复排序。如果你还是卡住了,那可能需要提出一个单独的问题。
一个问题是InversionCount(arr)
并不会使arr
排序,所以
a = res //将结果复制回原始切片
fmt.Println(a) //为什么"a"没有被排序?
这不是你想要的结果,因为之前当你将mergeCount
应用于left
和right
时,这些子数组left
和right
并没有按照InversionCount
进行排序。一个更简单的例子是:
package main
import "fmt"
func Foo(a []int) {
a = []int{1, 2, 3, 4}
}
func main() {
a := []int{4, 3, 2, 1}
Foo(a)
fmt.Println(a) // [4, 3, 2, 1]
}
英文:
You need to replace the line
count += 1
with
count += len(left)
The point is that at any point in mergeCount
where left[0] > right[0]
, then since left
is already sorted, all the remaining things in left
are inverted relative to right[0]
. If you do this, you get the correct count.
The fact that your sort isn't working is a different problem. If you're interested in fixing that, I'd recommend taking out all the count logic and just trying to fix the sort. If you're still stuck, it probably deserves its own question.
One problem is that InversionCount(arr)
doesn't result in arr
being sorted, so
a = res //Copies the result back into the original slice
fmt.Println(a) //Why hasn't "a" been sorted?
this isn't what you're wanting it to be, because earlier when you apply mergeCount
to left
and right
, those subarrays left
and right
weren't sorted by InversionCount
. A simpler example of this:
package main
import "fmt"
func Foo(a []int) {
a = []int{1, 2, 3, 4}
}
func main() {
a := []int{4, 3, 2, 1}
Foo(a)
fmt.Println(a) // [4, 3, 2, 1]
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论