zoukankan      html  css  js  c++  java
  • [链表]同时遍历两个链表

    两个有序链表的合并

    对于两个有序链表合并成一个新的有序链表的代码很简单,但是要注意一些测试用例:

    比如说一个为空链表;两个链表不一样长,肯定最后有一个链表要单独的挂到结果链表中去的。

     ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) 
     {
    	 if(l1 == NULL)
    		 return l2;
    	 if(l2 == NULL)
    		 return l1;
    
    	 ListNode dummy(-1);
    	 ListNode *p = &dummy;
    
    	 while(l1 != NULL && l2 != NULL)
    	 {
    		 if(l1->val < l2->val)
    		 {
    			 p->next = l1;
    			 p = p->next;
    			 l1 = l1->next;
    			 p->next = NULL;
    		 }
    		 else
    		 {
    			 p->next = l2;
    			 p = p->next;
    			 l2 = l2->next;
    			 p->next = NULL;
    		 }
    	 }//while
    
    	 p->next = l1 == NULL ? l2 : l1;
    
    	 return dummy.next;
     }
    

      注意程序中用到了一个头结点,这个头结点就是为了链表插入的方便,真正返回的时候还是放回的dummy.next。

    K个有序链表的合并

    这个问题当然可以利用上面的合并两个有序链表的方法,把前两个合并成一个,然后再同第三个合并,这样一次下去。但是这让我们想起来归并算法,把非常小的子问题首先合并,然后再合并中等的问题,最后再把中等的问题合并成大的问题。这样的时间复杂度要比一次合并小得多。所以利用归并的思想,设计代码如下:

    ListNode* mergeKLists(vector<ListNode*>& lists) 
    {
    	int n = lists.size();
    	if(n == 0)
    	 return NULL;
    	 while(n > 1)
    	 {
    		 int k = (1 + n) / 2;
    		 for(int i = 0; i < n / 2; i++)
    		 {
    			 lists[i] = mergeTwoLists(lists[i], lists[i + k]);
    		 }
    		 n = k;
    	 }
    	 
    	 return lists[0];
    }
    

      这里利用归并的时候,把整个的问题划分还是有一定的技巧的。

    int k = (n + 1) / 2;
    1.如果n是偶数,那么k是后半部分的开始,并且前面直接就是前半部分。
    2.如果n是奇数,那么k是后半部分的开始,但是前面隔着一个n/2这个元素,
    	再往前才是对应的前半部分。
    

      

  • 相关阅读:
    RDD的五个属性
    惰性求值的概念
    大数据shuffle的理解
    简单说明hadoop和hbase的异同
    Linux 下命令有哪几种可使用的通配符?分别代表什么含义?
    linux命令知识点复习
    >/dev/null 2>&1
    JAVA内存泄漏和内存溢出的区别和联系
    Linux各个目录的作用
    JVM标准参数-server与-client参数的区别
  • 原文地址:https://www.cnblogs.com/stemon/p/4683373.html
Copyright © 2011-2022 走看看