Golang:计算逆序对的排序问题

huangapple go评论83阅读模式
英文:

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) &lt;= 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, &amp;res)
a = res        //Copies the result back into the original slice
fmt.Println(a) //Why hasn&#39;t &quot;a&quot; been sorted?
return iCount + leftCount + rightCount
}
func mergeCount(left, right []int, res *[]int) int {
count := 0
for len(left) &gt; 0 || len(right) &gt; 0 {
if len(left) == 0 {
*res = append(*res, right...)
break
}
if len(right) == 0 {
*res = append(*res, left...)
break
}
if left[0] &lt;= 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应用于leftright时,这些子数组leftright并没有按照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] &gt; 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&#39;t &quot;a&quot; 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 &quot;fmt&quot;
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]
}

huangapple
  • 本文由 发表于 2014年8月15日 12:06:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/25321111.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定