Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 合并两个排序的单链表_Java_Algorithm_Merge_Linked List - Fatal编程技术网

Java 合并两个排序的单链表

Java 合并两个排序的单链表,java,algorithm,merge,linked-list,Java,Algorithm,Merge,Linked List,在寻找一些考试练习时,我在Leetcode上遇到了这个问题,我提出了以下解决方案: public class ListNode { int val; ListNode next; ListNode(int x) { val = x; } } public class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { // base case: if any o

在寻找一些考试练习时,我在Leetcode上遇到了这个问题,我提出了以下解决方案:

public class ListNode {
    int val;
    ListNode next;
    ListNode(int x) { val = x; }
}

public class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        // base case: if any one of the lists are empty then we are done. 
        if (l1 == null) return l2;
        else if (l2 == null) return l1;

        ListNode head = new ListNode(-1); 
        // dummy head node

        ListNode prev = head; // pointer to do the modifications on the list
        while ((l1 != null) && (l2 != null)) {
            // while both lists arent empty
            int val;
            if (l1.val < l2.val) {
                val = l1.val;
                l1 = l1.next;
            } else {
                val = l2.val;
                l2 = l2.next;
            }
            ListNode curr = new ListNode(val); // creates a new node with the chosen value
            prev.next = curr; // update pointers
            prev = curr;
        }

        // one of the list is finished. we add the rest onto the list ln
        if (l1 == null) prev.next = l2;
        else prev.next = l1;

        return head.next;
    }
}
公共类ListNode{
int-val;
listnodenext;
ListNode(intx){val=x;}
}
公共类解决方案{
公共ListNode合并列表(ListNode l1、ListNode l2){
//基本情况:如果任何一个列表为空,那么我们就完成了。
if(l1==null)返回l2;
else if(l2==null)返回l1;
ListNode头=新ListNode(-1);
//虚拟头节点
ListNode prev=head;//对列表进行修改的指针
而((l1!=null)和&(l2!=null)){
//虽然两个列表都不是空的
int-val;
if(l1.val

它似乎通过了所有测试——但我的问题是,它比提交的解决方案的90%慢。我最近学习了LinkedList,但我仍然对这个概念不太熟悉,这就是为什么在理解过程中可能会出现一些失误,导致这里的代码效率低下。如果有人能解释如何改进我的实现,我将不胜感激。

您的代码有两个问题

首先,它与输入数据不一致。如果其中一个输入列表为空,则例程返回另一个输入列表作为结果。另一方面,如果两个输入列表均为非空,则例程将创建新项以构建结果列表。但是,当一个输入列表在合并过程中耗尽时,另一个列表的其余部分将附加到结果列表中。最终,结果列表部分由新节点和其中一个输入列表的尾部组成

这会导致创建重复节点和销毁原始节点(这些节点已被其副本替换)的不必要开销

为了避免这种情况,直接使用从输入列表中获取的节点构建结果列表。这样就不需要创建新节点,不需要回收旧节点,在复制前不需要保留中间变量
val
,如果扩展了
ListNode
类,就不会忘记复制其他数据成员的风险

另一种是对输出节点进行排序。使用“小于”运算符决定是从
l1
还是从
l2
获取下一个节点。那是错误的。您应该使用“小于或等于”,因此对于相等键,您首先从
l1
获取节点,然后从
l2
获取节点。这样,具有相同键值
val
,但在其他方面不同(例如,它们具有其他数据成员)的节点将保持原始顺序。我们称之为稳定排序

实施:

public ListNode mergeTwoLists(ListNode l1, ListNode l2) {

    ListNode head = new ListNode(-1);  // temporary head node
    ListNode last = head; // the last item of the list; we append here

    while ((l1 != null) && (l2 != null)) { // while both lists arent empty
        if (l1.val <= l2.val) {            // 'or equal' for stable merging
            last.next = l1;                // append the chosen node to result list
            l1 = l1.next;                  // skip (effectively remove) it in input list
        } else {
            last.next = l2;
            l2 = l2.next;
        }
        last = last.next;                  // the appended node becomes last
    }

    // one of the lists is finished - append the rest of the other one
    if (l1 == null) last.next = l2;
    else last.next = l1;

    return head.next;
}

为什么只在方法末尾添加其余节点时创建新节点?似乎您不必创建新节点,只需(重新)使用已传递的节点就可以提高性能,特别是对于长列表。如何知道您的代码比解决某些未指定问题的其他未知代码慢?
null
list!=空列表。检查列表的
size()
及其空值value@pvg恐怕这是我能说的最具体的了。原来的问题是这样的:你只是想说得更具体一些,也许不是。这并没有回答问题,这是对练习的回答。@pvg它没有回答吗?OP询问“是否有人可以解释如何改进我的实现”。这是一个例子,如何改进它们的实现:避免创建不必要的对象,并重新链接输入数据;完全按照任务描述:不是“使用合并数据创建新列表”,而是“合并输入列表”(他们说:'')。它没有解释任何事情,只是删除了一个实现,没有说明它如何优于poster的实现,为什么性能特征不同,等等。它只是一堆代码。这是一个糟糕的答案,就像“为什么这一团代码不起作用”是一个可标记的糟糕问题一样。@pvg也许CiaPan可以通过添加更多的澄清来改进答案,但就我个人而言,我发现这个答案在消化代码后很有帮助-这,我想我的目标是找到并理解更好的实现背后的原因。@user2938375这很好,但网站的目的是收集许多人认为有用的问题和答案,而不是充分回答你个人的特定问题。这就是为什么它有关于什么是好的问题和答案的指导方针。
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {

    if (l1 == null) return l2;
    else if (l2 == null) return l1;    // make sure both lists aren't empty

    ListNode head = null;                  // the resulting list's head

    if (l1.val <= l2.val) {                // choose the head node
        head = l1;
        l1 = l1.next;
    } else {
        head = l2;
        l2 = l2.next;
    }

    ListNode last = head;  // the last item of the list; we append here

    while ((l1 != null) && (l2 != null)) { // while both lists arent empty
        if (l1.val <= l2.val) {            // 'or equal' for stable merging
            last.next = l1;                // append the chosen node to result list
            l1 = l1.next;                  // skip (effectively remove) it in input list
        } else {
            last.next = l2;
            l2 = l2.next;
        }
        last = last.next;                  // the appended node becomes last
    }

    // one of the lists is finished - append the rest of the other one
    if (l1 == null) last.next = l2;
    else last.next = l1;

    return head;
}