【问题标题】:Counting inversions in a linked-list with O(n log n) running time以 O(n log n) 运行时间计算链表中的反转
【发布时间】:2017-09-19 10:38:52
【问题描述】:

我在 Java 中创建了一个非常简单的链表:

public class LinkedList {
    class Node {
        public Node next;
        public int item;

        public Node (int item) {
            this.item = item;
        }
    }

    int listSize = 0;
    Node first = null;
    Node last = null;

    public void add(int n) {
        Node node = new Node(n);
        if (first == null) {
            first = node;
        } else {
            last.next = node;
        }
        last = node;
        listSize++;
    }
}

所以在主类中,我将以随机顺序将元素添加到链表中。但是如何创建一个计算链表中反转次数的方法?

到目前为止,我已经设法以 O(N^2) 的运行时间来实现它:

    public int inversionCount() {
        int count = 0;
        Node current = this.first;
        for (int i = 0; i <= this.listSize - 2; i++) {
            Node next = current.next;
            for (int j = i + 1; j < this.listSize; j++) {
                if (current.item > next.item) {
                    System.out.print("(" + current.item + "," + next.item + ")" + " ");
                    count += 1;
                }
                next = next.next;
            }
            current = current.next;
        }
        return count;
    }

然而,正如我所说,这个算法的运行时间是 O(N^2)。我正在尝试实现 O(NlogN) 的运行时间。如何实现?

【问题讨论】:

  • 如果您将列表排序为(值,原始索引)的列表 - O(N log N)。那么索引和原始索引可能与反转计数具有数学关系。或者这样。快乐令人费解。如果事实上排序算法本身可以计算并行数组反转计数中的反转。
  • 在你的add方法中,last.next = Node;不应该是first.next = Node;吗?

标签: java algorithm linked-list time-complexity inversion


【解决方案1】:

您正在使用复杂度为 O(n^2)

的冒泡排序

对于链表,O(n log n)复杂度适用的算法是Merge Sort

请看this walk trough of merge sort for linked lists

【讨论】:

  • 我尝试对链接中的代码稍作修改:if (a.item &lt;= b.item) { result = a; result.next = sortedMerge(a.next, b); } else if (a.item &gt; b.item) { result = b; invCount++; result.next = sortedMerge(a, b.next); } 我希望如果 a.item
  • 在没有完整实现的情况下很难看到,但根据您在 aboce 注释中的代码 invCount++ 将不会在 a.item &lt; b.item 时执行,因为您在 a.item &gt; b.item 时增加它
  • 就是这样。如果左侧子链表中的值大于右侧子链表中的值,则 invCount 应该增加 1。但是当我测试它时,它不会计算正确的反转次数
  • ... 换句话说,在您的第一条评论中的代码中,invCount 的增量仅在 a.item &gt; b.item 发生时才会发生,因此您编码的内容与您期望发生的相反,或者您输入了第一个错误评论。
【解决方案2】:

在插入排序中,在普通数组上需要 o(n),即使您使用二进制搜索来查找需要排序的元素,也需要 o(n) 才能为数组腾出新空间。在链表中,插入需要 o(1) 并且通过二分查找,您可以获得 o(nlogn) 的复杂度。从那里您可以通过计算要移动的索引的计算减去前一个索引来计算该数组的反转。每次都将所有这些计算相加以获得数字反转。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 2015-07-06
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多