C语言强化(七)链表相交问题_4 判断两个有环链表是否相交

上一节结束后,我们已经可以判断链表是否有环了,如果无环,那么按照前两节所讲的方法去判断链表是否相交以及获取相交结点,如果有环呢?怎么判断是否相交?

题目

给出俩个单向链表的头指针,比如 h1,h2,判断这俩个链表是否相交

解题步骤

  1. 判断两个【无环】链表是否相交
  2. 找到两个【无环】链表的相交结点
  3. 判断链表是否带环
  4. 判断两个【有环】链表是否相交
  5. 找到两个【有环】链表的相交结点

思路

对于有环的链表,只要它们相交,则带环的那一段必定完全重复。所以我们只需要在链表一上找到环上的一个结点,判断该结点是否在链表二上,如果在,则相交,如果不在,则不相交。

那么怎么找到【链表一上找到环上的一个结点】??

没错,上一讲创建的判断链表是否带环函数,如果链表带环,返回的就是环上的一个结点!

根据上面的思路,我们需要新创建两个函数

函数一:判断结点是不是在链表上

/*判断结点是不是在链表上
head  链表头
node  结点
*/
bool ifNodeOnList(ListNode * head,ListNode * node){

	if(node==NULL)
		return 0;
	//为防止有环链表无限遍历,首先进行有无环判断
	ListNode * circleNode = ifCircle(head);
	int count = 0;//经过重复结点的次数
	while(head!=NULL&&count<2){
		if(head==node)
			return 1;
		if(head==circleNode)
			count++;
		head=head->nextNode;
	}
	return 0;
}

函数二:判断有环链表是否相交

//判断有环链表是否相交
bool ifCircleListCross(ListNode * L1,ListNode * L2){
	ListNode * node = ifCircle(L1);
	if(node!=NULL)
		return ifNodeOnList(L2,node);
	return 0;
}

源代码:

#include <stdio.h>
#include<stdlib.h>
#include <iostream>

using namespace std;

/**
4.判断两个【有环】链表是否相交
思路
	判断一链表上俩指针相遇的那个节点,【在不在另一条链表上】。
	如果在,则相交,如果不在,则不相交。
*/

/**
链表结构体
*/
struct ListNode{
	int data;
	ListNode * nextNode;
	ListNode(ListNode * node,int value){
		nextNode=node;
		data=value;
	}
};

ListNode * L1;
ListNode * L2;

/**
判断链表是否有环
node  链表头指针

方法:用两个指针,一个指针步长为1,一个指针步长为2,若最后相遇,则链表有环
有环 返回两指针相遇位置
无环 返回NULL
*/
ListNode * ifCircle(ListNode * node){
	if(NULL==node)
		return false;
	ListNode * fast = node->nextNode;
	ListNode * slow = node;
	while(NULL!=fast&&NULL!=fast->nextNode){
		fast=fast->nextNode->nextNode;//步长为2
		slow=slow->nextNode;//步长为1
		if(fast==slow){
			cout<<"链表有环"<<endl;
			return fast;
		}
	}
	cout<<"链表无环"<<endl;
	return NULL;
}

/*判断结点是不是在链表上
head  链表头
node  结点
*/
bool ifNodeOnList(ListNode * head,ListNode * node){

	if(node==NULL)
		return 0;
	//为防止有环链表无限遍历,首先进行有无环判断
	ListNode * circleNode = ifCircle(head);
	int count = 0;//经过重复结点的次数
	while(head!=NULL&&count<2){
		if(head==node)
			return 1;
		if(head==circleNode)
			count++;
		head=head->nextNode;
	}
	return 0;
}

//判断有环链表是否相交
bool ifCircleListCross(ListNode * L1,ListNode * L2){
	ListNode * node = ifCircle(L1);
	if(node!=NULL)
		return ifNodeOnList(L2,node);
	return 0;
}

//创建有环链表
ListNode * createCircleList(){
	ListNode * node = new ListNode(NULL,0);
	ListNode * enter = node;
	node = new ListNode(node,1);
	node = new ListNode(node,2);
	enter->nextNode=node;
	node = new ListNode(node,3);
	node = new ListNode(node,4);
	return node;
}

//创建有环链表相交
void createCircleListCross(){
	L1 = new ListNode(NULL,0);
	ListNode * enter2 = L1;//L2的入口
	L1 = new ListNode(L1,1);
	L1 = new ListNode(L1,2);
	enter2->nextNode=L1;//L1的入口
	L1 = new ListNode(L1,3);
	L1 = new ListNode(L1,4);

	L2 = new ListNode(enter2,0);
	L2 = new ListNode(L2,1);
	L2 = new ListNode(L2,2);
}

//创建有环链表不相交
void createCircleListNotCross(){
	L1=createCircleList();
	L2=createCircleList();
}

void main()
{
	/*
	ListNode * node = createCircleList();
	ListNode * node2 = new ListNode(NULL,0);
	cout<<ifNodeOnList(node,node2)<<endl;
	*/

	//createCircleListNotCross();
	createCircleListCross();
	if(ifCircleListCross(L1,L2))
		cout<<"相交"<<endl;
	else
		cout<<"不相交"<<endl;
	system("pause");
}

有环链表是否相交我们也可以判断了,剩下的就是获得有环链表相交结点,下一节,链表相交问题的最后一节,聊。

时间: 2024-10-26 19:30:35

C语言强化(七)链表相交问题_4 判断两个有环链表是否相交的相关文章

C语言强化(七)链表相交问题_5 找到两个有环链表的相交结点

有环链表是否相交我们也可以判断了,剩下的就是获得有环链表相交结点 题目 给出俩个单向链表的头指针,比如 h1,h2,判断这俩个链表是否相交 解题步骤 判断两个[无环]链表是否相交 找到两个[无环]链表的相交结点 判断链表是否带环 判断两个[有环]链表是否相交 找到两个[有环]链表的相交结点 思路: 显然,有环链表的相交点其实就是环的入口 如图 所以 问题转为求环的入口 直接上理论,具体解释不难,纯粹是一道小学数学追赶问题 若在头结点和快慢指针相遇结点分别设一指针,同步(单步)前进,则最后一定相遇

1.11判断两个无环单链表是否相交

判断两个无环单链表是否交叉 题目描述: 如上图,这两个链表相交于结点5,要求判断两个链表是否相交,如果相交,找出相交处的结点. 解题思路: 方法一:Hash 法 如上图所示,如果两个链表相交,那么它们一定会有公共的结点,由于结点的地址或引用可以作为结点的唯一标识,因此,可以通过判断两个链表中的结点是否有相同的地址或引用来判断链表是否相交. 方法二:首尾相接法 将这两个链表首尾相连(例如把链表headl尾结点链接到head2的头指针),然后检测这个链表是否存在环,如果存在,则两个链表相交,而环入口

链表相交问题:判断两个链表是否相交,若相交求交点

默认为不带环链表,若带环则延伸为判断链表是否带环,若带环,求入口点 看看两个链表相交到底是怎么回事吧,有这样的的几个事实:(假设链表中不存在环) (1)一旦两个链表相交,那么两个链表中的节点一定有相同地址. (2)一旦两个链表相交,那么两个链表从相交节点开始到尾节点一定都是相同的节点. #include<iostream> #include<assert.h> using namespace std; template<class T> struct LinkNode

判断两个单链表是否相交

题目描述: 给定两个单链表的头节点head1和head2,如何判断两个链表是否相交?相交的话返回true,不想交的话返回false. 给定两个链表的头结点head1和head2.请返回一个bool值代表它们是否相交. 链表中节点的类型设置如下: class ListNode { int val; ListNode next = null; ListNode(int val) { this.val = val; } } 思路: 1.首先判断是否有环, 若两个链表都没有环,则进行无环单链表判断是否相

C语言强化(七)链表相交问题_3 判断链表是否带环

前两篇讨论的前提都是链表是无环的,但是如果链表有环呢? 显然,如果链表有环,那么之前的寻找链表尾结点的函数将陷入死循环,之前的算法也将崩掉. 所以对于链表相交的问题,首先要判断的是链表是否有环. 题目 给出俩个单向链表的头指针,比如 h1,h2,判断这俩个链表是否相交 解题步骤 判断两个[无环]链表是否相交 找到两个[无环]链表的相交结点 判断链表是否带环 判断两个[有环]链表是否相交 找到两个[有环]链表的相交结点 思路 用两个指针,一个指针步长为1,一个指针步长为2,若最后相遇,则链表有环

C语言强化(七)链表相交问题_1 判断无环链表相交

从此篇博文开始,讲解一道古老的链表相交问题,共五篇 题目 给出俩个单向链表的头指针,比如 h1,h2,判断这俩个链表是否相交 解题步骤 判断两个[无环]链表是否相交 找到两个[无环]链表的相交结点 判断链表是否带环 判断两个[有环]链表是否相交 找到两个[有环]链表的相交结点 此篇先从最简单的判断两个[无环]链表是否相交开始,顺便介绍一下链表的基础知识,方便一些对链表不太了解的同学学习. 基础知识 什么是链表? 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指

C语言强化(七)链表相交问题_2 找到无环链表相交结点

上一节聊了判断两个[无环]链表是否相交,那么如果相交,怎么找到相交结点呢? 题目 给出俩个单向链表的头指针,比如 h1,h2,判断这俩个链表是否相交 解题步骤 判断两个[无环]链表是否相交 找到两个[无环]链表的相交结点 判断链表是否带环 判断两个[有环]链表是否相交 找到两个[有环]链表的相交结点 思路 遍历的过程中记录链表的长度L1和L2(假设L1>L2) 遍历找到第一个链表中的第L1 - L2节点, 链表一从第L1-L2个节点开始遍历,链表二从第一个节点遍历,相当于两链表从与相交点距离相同

判断两个链表是否相交(不带环)

1---2---3 ---4---5---6---7 11---12--- 链表1:1---2---3---4---5---6---7 链表2:11---12---4---5---6---7 解决方案: 1.直接将链表1中的节点与链表2中的节点进行比较:如果存在相同的则相交.缺点:效率慢. 2.将链表1建立hash表:用链表2中的节点在hash表中进行查询:缺点:增加了内存消耗. 3.将链表1的尾节点指针指向链表2的头节点:转而进行链表是否有环判断:如果有环,则相交: 由于链表2的头节点必然在环

如何判断两个链表相交及找到第一个相交点

参考原文地址:https://www.cnblogs.com/BeyondAnyTime/archive/2012/07/06/2580026.html 1.问题分析 看看两个链表相交到底是怎么回事吧,有这样的的几个事实:(假设链表中不存在环) (1)一旦两个链表相交,那么两个链表中的节点一定有相同地址. (2)一旦两个链表相交,那么两个链表从相交节点开始到尾节点一定都是相同的节点. 分析出来了问题的本质,那么思路也就自然有了. 2.问题解法 2.1 哈希解法: 既然连个链表一旦相交,相交节点一