C++寻找两个链表的交点

算法思想

链表明确无环下 findIntersectWithoutRing

这种情况,只需要使用两个指针进行一次遍历就可以了。
注:可以假想成两个链表彼此相连,即list2连到list1后面,list1连在list2后面;

链表可能有环 findIntersect

首先需要判断两个链表是否有环,环的入口,以及不重复节点的数量;

  1. 当两个链表其中一个无环,另一个有环时,必然没有交点;
  2. 当两个链表都有环,且环的入口不一致时,需要判断是否为同一个环;如果是同一个环,则返回其中一个环入口,否则,必然没有交点;
  3. 其它情况下(即链表无环,或者环的入口一致),将长链表先前进n步,使得两个链表剩下的长度相等,之后同时遍历一下,尝试找到第一个交点即可;

源代码

#pragma once
#include<vector>
using namespace std;
struct ListNode {
	int val;
	ListNode* next;
	ListNode(int val):val(val),next(NULL){}
};

//发现环入口,以及链表长度
//快慢指针
pair<ListNode*,int> findRing(ListNode* list) {
	int len = 0;
	ListNode* fast = list;
	ListNode* slow = list;
	while (fast != NULL) {
		slow = slow->next;
		++len;
		fast = fast->next;
		if (fast != NULL) 
			fast=fast->next;
		if (slow == fast)
			break;
	}
	//无环情况下
	if (fast == NULL) {
		while (slow != NULL) {
			slow = slow->next;
			++len;
		}
		return pair<ListNode*, int>(NULL, len);
	}
	slow = list;
	while (slow != fast) {
		slow = slow->next;
		fast = fast->next;
		++len;
	}
	return pair<ListNode*, int>(slow, len);
}

//找到链表交点(可能有环)
ListNode* findIntersect(ListNode* list1, ListNode* list2) {
	auto p1 = findRing(list1);
	auto p2 = findRing(list2);
	bool hasRing1 = p1.first != NULL;
	bool hasRing2 = p2.first != NULL;
	//其中一个有环,另一个无环,肯定没有交点;
	if (hasRing1 ^ hasRing2)
		return NULL;
	//两个都有环,且入口不一致
	if (hasRing1 && hasRing2&& p1.first != p2.first) {
		ListNode* node = p1.first;
		while (node!=p2.first) {
			node = node->next;
			if (node == p1.first) break;
		}
		//同一个环,返回其中一个入口
		return node == p2.first ? node : NULL;
	}
	//两个都无环,或者两个都有环且环入口一致
	ListNode* node1 = list1; 
	ListNode* node2 = list2;
	int k= p1.second - p2.second;
	//保证node1链表要长
	if (k < 0) {
		k = -k;
		swap(node1, node2);
	}
	while (k-- > 0) 
		node1 = node1->next;
	while (node1 != NULL && node2 != NULL && node1 != node2) {
		node1 = node1->next;
		node2 = node2->next;
	}
	return node1;
}

//找到链表是否相交(无环)
ListNode* findIntersectWithoutRing(ListNode* list1, ListNode* list2) {
	ListNode* node1 = list1;
	ListNode* node2 = list2;
	while (node1 != node2) {
		if (node1 == NULL) node1 = list2;
		else node1 = node1->next;
		if (node2 == NULL) node2 = list1;
		else node2 = node2->next;
	}
	return node1;
}

测试代码

#include"ListIntersect.h"
#include<iostream>
#include<unordered_map>
using namespace std;

//创建链表
//需要保证输入合理
pair<ListNode*, ListNode*>create(const vector<int>& nums1, const vector<int>& nums2) {
	ListNode tmp(-1);
	unordered_map<int, ListNode*> hashMap;
	ListNode* node = &tmp;
	for (int i = 0; i < nums1.size(); ++i) {
		ListNode* next = NULL;
		if (hashMap.find(nums1[i]) != hashMap.end())
			next = hashMap[nums1[i]];
		else {
			next = new ListNode(nums1[i]);
			hashMap[nums1[i]] = next;
		}
		node->next = next;
		node = node->next;
	}
	ListNode* list1 = tmp.next;
	tmp.next = NULL;
	node = &tmp;
	for (int i = 0; i < nums2.size(); ++i) {
		ListNode* next = NULL;
		if (hashMap.find(nums2[i]) != hashMap.end())
			next = hashMap[nums2[i]];
		else {
			next = new ListNode(nums2[i]);
			hashMap[nums2[i]] = next;
		}
		node->next = next;
		node = node->next;
	}
	ListNode* list2 = tmp.next;
	return pair<ListNode*, ListNode*>(list1, list2);
}

int main() {
	vector<int>nums1 = { 1,2,3,4,5,6,7,3};
	vector<int>nums2 = { 9,6};
	auto p= create(nums1, nums2);
	auto node=findIntersect(p.first, p.second);
	if (node == NULL)cout << "no" << endl;
	else cout << node->val << endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值