[链表]同时遍历两个链表

两个有序链表的合并

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

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

 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这个元素,
	再往前才是对应的前半部分。

  

原文地址:https://www.cnblogs.com/stemon/p/4683373.html