【问题标题】:Merging two sorted linked list of unequal length合并两个长度不等的排序链表
【发布时间】:2013-07-18 16:42:34
【问题描述】:

我正在尝试合并两个排序的链表。

代码 sn-p 不适用于以下两个列表:

List 1 : 1->3->5->7->9->null
List 2 : 2->4->6->8->10->null

Expected List : 1->2->3->4->5->6->7->8->9->10->null

但是下面程序的输出结果是这样的:

Output :  1->2->3->4->5->6->7->8->9->null // element 10 is missing.

我错过了什么吗?现场演示:http://ideone.com/O7MBlo

class Node {

    Node next;
    int value;

    Node(int val) {
        this.value = val;
        this.next = null;
    }

    @Override
    public String toString() {
        Node cur = this;
        String str = "";

        while(cur != null) {
            str += cur.value+"->";
            cur = cur.next;
        }

        return str;
    }
}

class MergeLL {

    public static Node merge(Node n1, Node n2) {

        Node result = null;

        if(n1 != null && n2 != null) {
            if(n1.value < n2.value) {
                result = n1;
                result.next = merge(n1.next, n2);
            } else {
                result = n2;
                result.next = merge(n1, n2.next);
            }
        }
        return result;
    }

    public static void main(String[] args) {
        Node n1 = new Node(1);
        Node n3 = new Node(3);
        Node n5 = new Node(5);
        Node n7 = new Node(7);
        Node n9 = new Node(9);

        n1.next = n3;
        n3.next = n5;
        n5.next = n7;
        n7.next = n9;
        n9.next = null;

        Node n2 = new Node(2);
        Node n4 = new Node(4);
        Node n6 = new Node(6);
        Node n8 = new Node(8);
        Node n10 = new Node(10);

        n2.next = n4;
        n4.next = n6;
        n6.next = n8;
        n8.next = n10;
        n10.next = null;

        System.out.println("Merge : " + merge(n1, n2));
    }
}

【问题讨论】:

  • 如何将所有元素添加到单个集合中,对其进行排序然后循环以更新属性next
  • @ArnaudDenoyelle:排序是 O(n log n)。直接合并是 O(n)。当你拥有一百万件物品时,差异是巨大的。
  • 顺便说一句,递归合并有一个巨大的缺点:堆栈空间。如果没有尾递归删除,递归合并将消耗 O(n) 堆栈帧。因此,如果列表中的项目总数相当大(例如,100,0000 左右),您可能会破坏堆栈。

标签: java algorithm data-structures linked-list mergesort


【解决方案1】:

您需要再添加两个条件,当n1n2 提前耗尽时。因此,您的条件 - n1 != null &amp;&amp; n2 != null 仅适用于两个列表大小相同的情况。

只需添加以下两个条件的代码,然后如果:

if(n1 != null && n2 != null) {
        if(n1.value < n2.value) {
            result = n1;
            result.next = merge(n1.next, n2);
        } else {
            result = n2;
            result.next = merge(n1, n2.next);
        }

} else if (n1 != null) {  
    result = n1;  // Add all the elements of `n1` to `result`
} else if (n2 != null) {
    result = n2;  // Add all the elements of `n2` to `result`
}

实际上,您不需要在那里建立一个新的result 列表。您可以简单地扩展其中一个传递的节点。

你可以修改你的方法如下:

public static Node merge(Node n1, Node n2) {
    if (n1 == null) return n2;
    if (n2 == null) return n1;

    if (n1.value < n2.value) {
        n1.next = merge(n1.next, n2);
        return n1;
    } else {
        n2.next = merge(n2.next, n1);
        return n2;
    }
}

【讨论】:

  • 我试过这个.. else if(n1 != null) { result.next = n1; } else if(n2 != null) { result.next = n2; } .. 但它会抛出 NPE .. !!
  • @tm99。更新了代码。还要检查我发布的第二个代码。会干净很多。
  • 你能帮我解决这个问题吗? stackoverflow.com/questions/17748078/…
【解决方案2】:

递归算法有一个基本条件。所以你的基本条件是:

  • 空列表 n1 和 n2
  • n1 为空,n2 不为空。
  • n2 为空,n1 为空。

处理好基本条件 2 和 3:

在条件 2 中,基本条件 n2 为空,因此我们将返回 n1:

else if(n1!=null ){
        result=n1;
    }

在条件 3 中,基本条件 n1 为空,因此我们将返回 n2:

else if(n2!=null ){
        result=n2;
    }

因此问题在于算法中基本条件的设计!!

所以试试这个,它确实有效

public static Node merge(Node n1, Node n2) {
    Node result = null;

    if(n1 != null && n2 != null) {
        if(n1.value < n2.value) {
            result = n1;
            result.next = merge(n1.next, n2);
        } else {
            result = n2;
            result.next = merge(n1, n2.next);
        }

    }
    else if(n1!=null ){
        result=n1;
    }
    else if(n2!=null){
        result=n2;
    }
    return result;
}

祝你好运!

编辑This 链接应该可以帮助您设计递归算法。

【讨论】:

    【解决方案3】:
    if(n1 != null && n2 != null) {
    

    当其中一个列表为空而另一个不为空时会发生什么?

    它返回空值。但它应该返回不为空的列表。

    一个可能的解决方案是这样的;

    if(n1 == null)
      return n2;
    if(n2 == null)
      return n1;
    
    if(n1.value < n2.value) {
      result = n1;
      result.next = merge(n1.next, n2);
      } else {
      result = n2;
      result.next = merge(n1, n2.next);
    }
    

    【讨论】:

      【解决方案4】:

      合并两个有序链表的解决方案: https://leetcode.com/problems/merge-two-sorted-lists/

      虽然循环将执行到其中一个列表完成,但另一个列表的剩余数据将稍后附加到 while 循环之外。

          /**
           * Definition for singly-linked list.
           * public class ListNode {
           *     int val;
           *     ListNode next;
           *     ListNode(int x) { val = x; }
           * }
           */
          class Solution {
              public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
                  ListNode dummy = new ListNode(0);
                  ListNode head = dummy;
      
                  while(l1 != null && l2 != null) {
                      if(l1.val <= l2.val) {
                          dummy.next = l1;
                          l1 = l1.next;
                      }else{
                          dummy.next = l2;
                          l2 = l2.next;
                      }
      
                      dummy = dummy.next;
                  }
      
                  if(l1 != null) {
                      dummy.next = l1;
                  }else {
                      dummy.next = l2;
                  }
      
                  return head.next;
              }
          }
      

      【讨论】:

        【解决方案5】:

        它也可以优化。只是为了理解

        public static Node merge(Node n1, Node n2) {
        
                Node result = null;
        
                if(n1 != null && n2 != null) {
                    if(n1.value < n2.value) {
                        result = n1;
                        result.next = merge(n1.next, n2);
                    } else {
                        result = n2;
                        result.next = merge(n1, n2.next);
                    }
                }
                else if(n1 != null) {
                    result = n1;
                    result.next = merge(n1.next, n2);
                }
                else if(n2 != null) {
                    result = n2;
                    result.next = merge(n1, n2.next);
                }
                return result;
            }
        

        【讨论】:

          【解决方案6】:
          package test;
          
          import java.util.*;
          
          public class TestMergeLists<T extends Comparable<? super T>>
          {
              static <T extends Comparable<? super T>> List<T> merge(List<T> a,List<T>b)
              {
                  Collections.sort(a);
                  Collections.sort(b);
                  List<T> result = new ArrayList<T>();
                  int i = 0;
                  int j = 0;
          
                  for (;;)
                  {
                      T a1 = a.get(i);
                      T b1 = b.get(j);
                      if (a1.compareTo(b1) > 0)
                      {
                          result.add(b1);
                          j++;
                          if (j == b.size())// no more
                          {
                              if (i < a.size() - 1)
                                  result.addAll(a.subList(i + 1, a.size()));
                              break;
                          }
                      } else if (a1.compareTo(b1) == 0)
                      {
                          result.add(a1);
                          result.add(b1);
                          i++;
                          if (i == a.size())
                          {
                              if (j < b.size() - 1)
                                  result.addAll(b.subList(j + 1, b.size()));
                              break;
                          }
                          j++;
                          if (j == b.size())// no more
                          {
                              if (i < a.size() - 1)
                                  result.addAll(a.subList(i + 1, a.size()));
                              break;
                          }
                      } else
                      {
                          result.add(a1);
                          i++;
                          if (i == a.size())// no more
                          {
                              if (j < b.size() - 1)
                                  result.addAll(b.subList(j + 1, b.size()));
                              break;
                          }
                      }
                  }
                  return result;
              }
              public static void main(String args[])
              {
                  List<String> a = new ArrayList<String>();
                  a.addAll(Arrays.asList("the statement you found confusing is how MergeSort merges two ".split(" ")));
                  List<String> b = new ArrayList<String>();
                  b.addAll(Arrays.asList("then increment the current index for ".split(" ")));
                  List<String> result = merge(a,b);
                  System.out.println(result);
              }
          }
          

          【讨论】:

            【解决方案7】:

            这里是合并两个排序链表的简单迭代(非递归)代码:

            import java.util.*;
            class Node
            {
             public int data;
             public Node next;
             Node(int x)
             {
                 data=x;
                 next=null;
             }
            }
            public class Test {
                    public static Node merge(Node a, Node b)
                    {
                      Node res=null; 
                      Node first=null;
                      if(a.data < b.data)
                          {
                              res=a;
                              first=a;
                              a=a.next;
                          }
                          else
                          {   
                              first=b;
                              res=b;
                              b=b.next;
                          }
            
                      while(a!=null && b!=null)
                      {
                          if(a.data < b.data)
                          { 
                              res.next=a;
                              res=res.next;
                              a=a.next;
                          }
                          else
                          {  
                              res.next=b;
                              res=res.next;
                              b=b.next;
                          }   
                      } 
                      if(a!=null)
                      {
                          res.next=a;
                      }
                      else if(b!=null)
                      {
                          res.next=b;
                      }
            
                      return first;
                    }
            
                    public static void display(Node first)
                    {
                        while(first!=null)
                        {
                            System.out.print(first.data+" ");
                            first=first.next;
                        }
                    }
                    public static void main(String[] args)
                    {
                        Node n1=new Node(4);
                        Node n2=new Node(5);
                        Node n3=new Node(7);
                        Node n4=new Node(10);
                        n1.next=n2;
                        n2.next=n3;
                        n3.next=n4;
                        n4.next=null;
            
                        Node n5=new Node(3);
                        Node n6=new Node(6);
                        Node n7=new Node(9);
                        Node n8=new Node(15);
                        n5.next=n6;
                        n6.next=n7;
                        n7.next=n8;
                        n8.next=null;
            
                        Node f = merge(n1,n5);
                        display(f);
                    }
            }
            

            【讨论】:

            • 如果ab 在输入时为空会怎样?
            【解决方案8】:

            合并两个排序列表 | Leetcode 问题 | Javascript解决方案

            class ListNode {
              constructor(val, next=null) {
                this.val = val;
                this.next = next;
              }
            }
            
            const c = new ListNode(4);
            const b = new ListNode(2, c);
            const a = new ListNode(1, b);
            const z = new ListNode(3);
            const y = new ListNode(2, z);
            const x = new ListNode(1, y);
            
            var mergeTwoLists = function(l1, l2) {
            
              let p1 = l1;
              let p2 = l2;
              let l3, p3;
              if(l1) {
                  if (l2){
                      if(p1.val < p2.val) {
                        l3 = new ListNode(p1.val);
                        p1 = p1.next;
                      } else {
                        l3 = new ListNode(p2.val);
                        p2 = p2.next;
                      }
                  } else {
                      return l1;
                  }
              } else if(l2) {
                  return l2;
              } else {
                  return "";
              }
              p3 = l3;
            
              while(p1 && p2) {
                if(p1.val < p2.val) {
                  p3.next = new ListNode(p1.val);
                  p1 = p1.next;
                } else {
                  p3.next = new ListNode(p2.val);
                  p2 = p2.next;
                }
                p3 = p3.next;
              }
              if (p1) {
                p3.next = p1;
              } else {
                p3.next = p2;
              }
              return l3;
            }
            
            console.log(mergeTwoLists(a, x));
            

            【讨论】:

              猜你喜欢
              • 2023-03-11
              • 2011-01-21
              • 2017-08-23
              • 1970-01-01
              相关资源
              最近更新 更多