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

从此篇博文开始,讲解一道古老的链表相交问题,共五篇

题目

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

解题步骤

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

此篇先从最简单的判断两个【无环】链表是否相交开始,顺便介绍一下链表的基础知识,方便一些对链表不太了解的同学学习。

基础知识

什么是链表?

链表是一种物理存储单元上非连续、非顺序的存储结构数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

——From BaiKe

画个图展示一下链表

数据结构如下

struct ListNode{
	int data;
	ListNode * nextNode;
	ListNode(ListNode * node,int value){
		nextNode=node;
		data=value;
	}
};

有环链表?

只需修改一下指针的指向,就会发现,这个链表永远不会走到尽头,如下

如何判断两个链表是否相交?

思路:只要有一个节点相同,那么两链表就相交

方法一: 遍历遍历

遍历链表一,每次遍历到链表一的一个节点时判断是否和链表二的节点相同(方法同样是遍历),有相同的则说明两链表相交。

此方法当然可行,可是时间复杂度=O(length1*length2)

方法二:哈希表法 

既然连个链表一旦相交,相交节点一定有相同的内存地址,而不同的节点内存地址一定是不同的,那么不妨利用内存地址建立哈希表,如此通过判断两个链表中是否存在内存地址相同的节点判断两个链表是否相交。具体做法是:遍历第一个链表,并利用地址建立哈希表,遍历第二个链表,看看地址哈希值是否和第一个表中的节点地址值有相同即可判断两个链表是否相交。

时间复杂度O(length1 + length2)

空间复杂度O(length1)  因为需要创建大小为length1的哈希表

分析:时间复杂度是线性的,可以接受,并且可以顺便找到第一个相交节点,但是却增加了O(length1)的空间复杂度,这显然不能令人满意。——ref:http://www.cnblogs.com/BeyondAnyTime/archive/2012/07/06/2580026.html

方法三:比较尾结点

只要两链表相交,那么相交后的那一段肯定是一样的,也就意味着尾结点是一样的

时间复杂度O(length1 + length2)

空间复杂度O(0)

寻找尾结点的函数,很简单,就不解释了

/**
寻找尾结点
*/
ListNode * getLastNode(ListNode * head){
	if(head==NULL)
		return NULL;
	while(head->nextNode!=NULL){
		head=head->nextNode;
	}
	return head;
}

源代码

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

using namespace std;

/**
1.判断两个【无环】链表是否相交
思路
判断尾节点是否相等
*/

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

ListNode * L1;
ListNode * L2;

//遍历链表
void ScanList(ListNode * node){
	while(NULL!=node){
		cout<<node->data<<endl;
		node = node->nextNode;
	}
}

/**
寻找尾结点
*/
ListNode * getLastNode(ListNode * head){
	if(head==NULL)
		return NULL;
	while(head->nextNode!=NULL){
		head=head->nextNode;
	}
	return head;
}

//测试无环相交
void testCross(){
	ListNode * node = new ListNode(NULL,0);
	node = new ListNode(node,1);
	node = new ListNode(node,2);

	L1 = new ListNode(node,11);
	L1 = new ListNode(L1,12);
	L1 = new ListNode(L1,13);

	L2 = new ListNode(node,21);
	L2 = new ListNode(L2,22);
	L2 = new ListNode(L2,23);
}

//测试无环不相交
void testNotCross(){
	L1 = new ListNode(NULL,11);
	L1 = new ListNode(L1,12);
	L1 = new ListNode(L1,13);

	L2 = new ListNode(NULL,21);
	L2 = new ListNode(L2,22);
	L2 = new ListNode(L2,23);
}

void main()
{
	testCross();
	//testNotCross();
	ListNode * node1 = getLastNode(L1);
	ListNode * node2 = getLastNode(L2);
	if(node1==node2)
		cout<<"相交"<<endl;
	else
		cout<<"不相交"<<endl;
	system("pause");
}

既然知道两个【无环】链表相交,那么怎么找到相交结点,下一节,聊聊这个。

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

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

(原创)用Java实现链表结构对象:单向无环链表

转载请注明本文出处:http://www.cnblogs.com/Starshot/p/6918569.html 链表的结构是由一个一个节点组成的,所谓链,就是每个节点的头尾连在一起.而单向链表就是:每个节点包含了当前节点的值和下一个节点引用.双向链表就是每个节点包含了当前节点的值和上下两个节点的引用.相对于数组结构,链表的增删效率会更加高. 这边文章主要讲怎么用Java实现一个简单的链表结构:单向无环链表.以及实现一些数据处理的方法. 首先,新建一个节点类(本次例子中的节点值都是字符串类型):

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

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

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

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

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

上一节结束后,我们已经可以判断链表是否有环了,如果无环,那么按照前两节所讲的方法去判断链表是否相交以及获取相交结点,如果有环呢?怎么判断是否相交? 题目 给出俩个单向链表的头指针,比如 h1,h2,判断这俩个链表是否相交 解题步骤 判断两个[无环]链表是否相交 找到两个[无环]链表的相交结点 判断链表是否带环 判断两个[有环]链表是否相交 找到两个[有环]链表的相交结点 思路 对于有环的链表,只要它们相交,则带环的那一段必定完全重复.所以我们只需要在链表一上找到环上的一个结点,判断该结点是否在链

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

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

判断两个链表是否相交

1 假设两个链表都没有环 解题思路 a. 直接循环判断第一个链表的每个节点是否在第二个链表中.但,这种方法的时间复杂度为O(Length(h1) * Length(h2)).显然,我们得找到一种更为有效的方法,至少不能是O(N^2)的复杂度. b. 针对第一个链表直接构造hash表,然后查询hash表,判断第二个链表的每个节点是否在hash表出现,如果所有的第二个链表的节点都能在hash表中找到,即说明第二个链表与第一个链表有相同的节点.时间复杂度为为线性:O(Length(h1) + Leng

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

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

7_1判断一个单链表是否有环

转载请注明出处:http://www.cnblogs.com/wuzetiandaren/p/4251303.html 声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己也方便有类似问题的朋友,本文的思想也许有所借鉴,但源码均为本人实现,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明.谢谢. 题目:判断一个单链表是否有环,如果有环,求出环的入口节点. 题目分析: 建一个待头节点的单链表,有两个指针p,q最开始都指向第一个真正节点,p,诶次走1步,q每次走

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

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