算法-连接两条排序的链表

之前在牛客网上面做的题目,感觉对自己很有帮助,而且以后面试可能会用到,整理了两种方法,递归的和非递归的,同时也是对代码再一次巩固了。

ok,第一种,用递归实现!

class Solution
{
	ListNode * Merge(ListNode* pHead1, ListNode *pHead2)
	{
		if (pHead1 == NULL)            //如果pHead1当前指向的节点为空返回当前pHead2指向的节点
		{
			return phead2;
		}
		if (pHead2 == NULL)
		{
			return pHead1;            //如果pHead2当前指向的节点为空返回当前pHead1指向的节点
		}
		if (pHead1->val < pHead2->val)//如果两个节点当前指向的都不为空的话那么就比较
		{
			pHead1->next = Merge(pHead1->next, pHead2);    //如果pHead1大,那么下一个节点将从pHead1->next和pHead2决出
			return pHead1;                                //第一次比较的头结点决定最后返回哪个头结点
		}
		else
		{
			pHead2->next = Merge(pHead1, pHead2->next);    //如果pHead2大,那么下一个节点将从pHead和pHead2->next决出
			return pHead2;
		}
	}

};


第二种,非递归算法。
   

class Solution
{
	ListNode * Merge(ListNode * pHead1, ListNode *pHead2)
	{
		ListNode * cur = NULL;                //当前结点位置
		ListNode * result = NULL;             //最后返回的头结点
		if (pHead1 == NULL)                   
		{
			return pHead2;
		}
		if (pHead2 == NULL)
		{
			return pHead1;
		}
		while (pHead1 != NULL && pHead2 != NULL)//两个头结点同时都不为空
		{
			if (pHead1->val < pHead2->val)
			{
				if (result == NULL)             //如果当前result为空那么当前节点和最后头结点都为pHead1
				{
					cur = result = pHead1;
				}
				else                            //如果不空那么当前节点的下一个肯定是这次比较小的那个
				{
					cur->next = pHead1;
					cur = cur->next;
				}
				pHead1 = pHead1->next;          //pHead则需要往后遍历一个
			}
			else
			{
				if (pHead1->val > pHead2->val)
				{
					if (result == NULL)
					{
						cur = result = pHead2;
					}
					else 
					{
						cur->next = pHead2;
						cur = cur->next;
					}
					pHead2 = pHead2->next;
				}
			}
		}
		if (pHead1 == NULL)                      //退出while循环后如果某一条链表还没有完全遍历则把cur指向
		{
			cur->next = pHead2;
		}
		if (pHead2 == NULL)
		{
			cur->next = pHead1;
		}
	}
};


### 如何求两个有序链表的交集 对于两个已排序链表,可以通过双指针的方法高效地找到它们的交集。以下是具体的实现方法: #### 方法概述 通过维护两个指针 `p` 和 `q` 分别指向两个链表的第一个节点,逐一比较两者的值。如果两者相等,则表示该值属于交集;如果不相等,则移动较小值对应的指针向前一步。 此过程的时间复杂度为 O(m+n),其中 m 和 n 是两个链表的长度[^1]。这是因为每个节点最多被访问一次。 #### 实现细节 以下是一个完整的 C++ 实现代码示例: ```cpp #include <iostream> using namespace std; // 定义链表节点结构体 struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(nullptr) {} }; ListNode* findIntersection(ListNode* head1, ListNode* head2) { ListNode dummy(0); // 创建虚拟头节点 ListNode* tail = &dummy; // 尾部指针 ListNode* p = head1; // 链表1的当前节点 ListNode* q = head2; // 链表2的当前节点 while (p && q) { // 当两个链表均未到达末尾时继续 if (p->val == q->val) { // 如果值相同 tail->next = new ListNode(p->val); // 添加到结果链表 tail = tail->next; // 移动结果链表的尾部指针 p = p->next; // 同时前进两个链表的指针 q = q->next; } else if (p->val < q->val) { // 值较小时前移对应链表的指针 p = p->next; } else { q = q->next; } } return dummy.next; // 返回结果链表的真实头部 } void printList(ListNode* head) { ListNode* cur = head; while (cur != nullptr) { cout << cur->val; if (cur->next != nullptr) cout << " "; cur = cur->next; } cout << endl; } int main() { // 输入第一个链表 ListNode* head1 = new ListNode(0); ListNode* temp1 = head1; int num; cout << "Enter first sorted list (-1 to end):"; while (cin >> num && num != -1) { temp1->next = new ListNode(num); temp1 = temp1->next; } // 输入第二个链表 ListNode* head2 = new ListNode(0); ListNode* temp2 = head2; cout << "Enter second sorted list (-1 to end):"; while (cin >> num && num != -1) { temp2->next = new ListNode(num); temp2 = temp2->next; } // 计算交集 ListNode* result = findIntersection(head1->next, head2->next); // 输出结果 if (!result) { cout << "NULL" << endl; } else { printList(result); } return 0; } ``` #### 关键点解析 - **初始化虚拟头节点**:为了简化边界条件处理,引入了一个虚拟头节点 `dummy`,其作用是作为结果链表的起始位置。 - **双指针技术**:利用两个指针分别遍历两条链表,当遇到相同的值时将其加入结果链表,并同步推进两个指针;否则仅推进指向较小值的那个指针。 - **内存管理**:在实际应用中需要注意动态分配的对象释放问题,这里省略了这部分逻辑以便专注于核心算法[^2]。 #### 测试案例分析 假设输入如下: - 第一条链表:1 -> 3 -> 5 -> 7 - 第二条链表:3 -> 5 -> 8 程序会输出: ``` 3 5 ``` 这表明只有数值 3 和 5 出现在两条链表中,因此构成了最终的结果集合。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值