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

两个有序链表的合并

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

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

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

  

时间: 2024-10-20 11:35:57

[链表]同时遍历两个链表的相关文章

27、输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 思路:同归并算法 本题: 1 public class Solution { 2 public ListNode Merge(ListNode list1, ListNode list2) { 3 ListNode head; 4 if (list1 == null) { 5 return list2; 6 } 7 if (list2 == null) { 8 return list1; 9 } 10

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

新增一个链表,然后分别采用2个指针指向这两个链表,每次比较链表的值,将较小的那一个存入新链表中.需要主要的是对空链表进行处理,主要还是考察代码的鲁棒性.总共2个链表,数组分别是1,3,5,7,和2, 4, 6,8 采用java进行实现. package com.test.algorithm; class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } public class Me

无表头单链表的总结----两个链表合并

#include"head.h" struct Student* insert(struct Student*ahead, struct Student*bhead) { struct Student *pa1, *pa2, *pb1, *pb2; pa1 = pa2 = ahead; pb1 = pb2 = bhead; if ((ahead != NULL)&&(bhead != NULL)) { do { while ((pb1->num > pa1-

C++单链表反转、两有序链表合并仍有序

1 #include<iostream> 2 3 struct Node 4 { 5 int data; 6 Node *next; 7 }; 8 9 typedef struct Node Node; 10 11 Node *Reverse(Node *head) 12 { 13 if (NULL == head || NULL == head->next) 14 return head; 15 Node *p1 = head; 16 Node *p2 = p1->next; 1

哈希(4) - 求两个链表的交集(intersection)以及并集(union)

给定两个链表,求它们的交集以及并集.用于输出的list中的元素顺序可不予考虑. 例子: 输入下面两个链表: list1: 10->15->4->20 list2: 8->4->2->10 输出链表: 交集list: 4->10 并集list: 2->8->20->4->15->10 方法1 (简单方法) 可以参考链表系列中的"链表操作 - 求两个链表的交集(intersection)以及并集(union)" 方法2

两个链表第一个公共结点

题目:输入两个链表,找出它们的第一个公共节点.链表的定义如下: struct ListNode { int m_nValue; ListNode *m_pNext; }; 思路1:采用蛮力的方法:在第一个链表上顺序遍历每个节点,每遍历到一个节点的时候,在第二个链表上顺序遍历每个节点.如果第二个链表上的节点和第一个链表上的节点一样,就说明两个链表在节点上重合,于是就找到了公共的节点.而通常蛮力并不是好的方法. 思路2:首先遍历两个链表得到它们的长度,就能知道哪个链表比较长,以及长的链表比短的链表多

LeetCode OJ:Intersection of Two Linked Lists(两个链表的插入)

Write a program to find the node at which the intersection of two singly linked lists begins. For example, the following two linked lists: A: a1 → a2 c1 → c2 → c3 B: b1 → b2 → b3 begin to intersect at node c1. 找出第一个合并的节点的位置(或者说插入),注意复杂度为O(N),那么先遍历两个链

#21 合并排序后的两个链表

思路 使用三个游标:cur指向合并后链表的尾部,l1,l2分别用于遍历两个链表,较小的元素增加到合并后链表. 小技巧 使用冗余的头结点可以精简地判断一下情形,其中一个链表,或两个都为空链表. 从而精简代码. 朴素代码 class Solution { public: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { ListNode * head, *ptr; if (!l1 && !l2) return NULL; if (!l1

160. 两个链表的相交点 Intersection of Two Linked Lists

Write a program to find the node at which the intersection of two singly linked lists begins. For example, the following two linked lists: A: a1 → a2 c1 → c2 → c3 B: b1 → b2 → b3 begin to intersect at node c1. Notes: If the two linked lists have no i