一步一步写算法(之链表重合)

原文:一步一步写算法(之链表重合)

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】

链表重合是一个好玩的问题。原题目是这样的:有两个链表,那么如何判断这两个链表是不是重合的?至于这个链表在什么时候重合的,这不重要,关键是判断这个链表究竟有没有重合。究竟有什么方法呢?

最简单的方法就是查看两者有没有共同点。那么依次判断就行了。

int find_node_in_link(LINK_NODE* pLink, LINK_NODE* pNode)
{
	while(pLink){
		if(pLink == pNode)
			return 1;
		pLink = pLink->next;
	}

	return 0;
}

STATUS find_if_link_merge(LINK_NODE* pLinkOne, LINK_NODE* pLinkTwo)
{
	LINK_NODE* pHead;

	if(NULL == pLinkOne || NULL == pLinkTwo)
		return FALSE;

	pHead = pLinkTwo;
	while(pHead){
		if(find_node_in_link(pLinkOne, pHead))
			return TRUE;
		pHead = pHead->next;
	}

	return FALSE;
}

另外一种方法就是计数的方法,既然链表在某处重合,那么此点访问的次数就是2,所以我们可以依次把两个链表遍历一下,最后查看有没有节点的count为2即可。

typedef struct _LINK_NODE
{
	int data;
	int count;
	struct _LINK_NODE* next;
}LINK_NODE;

void process_all_link_node(LINK_NODE* pNode)
{
	assert(NULL != pNode);

	while(pNode){
		pNode->count ++;
		pNode = pNode->next;
	}
}

从计数的方法,我们可以发现如果两个链表是重合的,那么他们的最后一个节点必然是相同的,所以只要判断最后一个节点是否相同即可。

STATUS find_if_link_merge(LINK_NODE* pLinkOne, LINK_NODE* pLinkTwo)
{
	assert(NULL != pLinkOne && NULL != pLinkTwo);

	while(pLinkOne->next) pLinkOne = pLinkOne->next;
	while(pLinkTwo->next) pLinkTwo = pLinkTwo->next;

	return (pLinkOne == pLinkTwo) ? TRUE : FALSE;
}

总结:

1)链表重合的题目虽然简单,但是从不同的角度可以有不同的答案;

2)本题目来自《编程之美》, 如果对解法还有兴趣的朋友可以参考《编程之美》。

时间: 2024-11-06 14:15:12

一步一步写算法(之链表重合)的相关文章

一步一步写算法(之链表排序)

原文:一步一步写算法(之链表排序) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 相比较线性表的排序而言,链表排序的内容稍微麻烦一点.一方面,你要考虑数据插入的步骤:另外一方面你也要对指针有所顾虑.要是有一步的内容错了,那么操作系统会马上给你弹出一个exception.就链表的特殊性而言,适合于链表的排序有哪些呢? (1)插入排序    (适合) (2)冒泡排序    (适合) (3)希尔排序    (适合) (4)选择排序    (适

一步一步写算法(之单向链表)

原文:一步一步写算法(之单向链表) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 有的时候,处于内存中的数据并不是连续的.那么这时候,我们就需要在数据结构中添加一个属性,这个属性会记录下面一个数据的地址.有了这个地址之后,所有的数据就像一条链子一样串起来了,那么这个地址属性就起到了穿线连结的作用. 相比较普通的线性结构,链表结构的优势是什么呢?我们可以总结一下: (1)单个节点创建非常方便,普通的线性内存通常在创建的时候就需要设定数据的

一步一步写算法(之循环单向链表)

原文:一步一步写算法(之循环单向链表) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面的博客中,我们曾经有一篇专门讲到单向链表的内容.那么今天讨论的链表和上次讨论的链表有什么不同呢?重点就在这个"循环"上面.有了循环,意味着我们可以从任何一个链表节点开始工作,可以把root定在任何链表节点上面,可以从任意一个链表节点访问数据,这就是循环的优势. 那么在实现过程中,循环单向链表有什么不同? 1)打印链表数据 void pri

一步一步写算法(之链表逆转)

原文:一步一步写算法(之链表逆转) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 链表逆转是面试环境中经常遇到的一道题目,也是我们在实际开发中可能会遇到的开发需求.和线性逆转不一样,单向链表的节点需要一个一个进行处理.为了显示两者之间的区别,我们分别对线性内存和链表进行逆转: (1)普通连续内存数据的反转分析 STATUS normal_revert(int array[], int length) { int* pData ; int

一步一步写算法(之双向链表)

原文:一步一步写算法(之双向链表) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面的博客我们介绍了单向链表.那么我们今天介绍的双向链表,顾名思义,就是数据本身具备了左边和右边的双向指针.双向链表相比较单向链表,主要有下面几个特点: (1)在数据结构中具有双向指针 (2)插入数据的时候需要考虑前后的方向的操作 (3)同样,删除数据的是有也需要考虑前后方向的操作 那么,一个非循环的双向链表操作应该是怎么样的呢?我们可以自己尝试一下: (

一步一步写算法(之排序二叉树)

原文:一步一步写算法(之排序二叉树) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 前面我们讲过双向链表的数据结构.每一个循环节点有两个指针,一个指向前面一个节点,一个指向后继节点,这样所有的节点像一颗颗珍珠一样被一根线穿在了一起.然而今天我们讨论的数据结构却有一点不同,它有三个节点.它是这样定义的: typedef struct _TREE_NODE { int data; struct _TREE_NODE* parent; str

一步一步写算法(之图结构)

原文:一步一步写算法(之图结构) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 图是数据结构里面的重要一章.通过图,我们可以判断两个点之间是不是具有连通性:通过图,我们还可以计算两个点之间的最小距离是多少:通过图,我们还可以根据不同的要求,寻找不同的合适路径.当然,有的时候为了计算的需要,我们还需要从图中抽象出最小生成树,这样在遍历计算的时候就不需要持续判断是不是遇到了循环节点.当然,这所有的一切都是从图的表示开始的. 1)矩阵表示 矩

一步一步写算法(之查找)

原文:一步一步写算法(之查找) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 无论是数据库,还是普通的ERP系统,查找功能数据处理的一个基本功能.数据查找并不复杂,但是如何实现数据又快又好地查找呢?前人在实践中积累的一些方法,值得我们好好学些一下.我们假定查找的数据唯一存在,数组中没有重复的数据存在. (1) 普通的数据查找 设想有一个1M的数据,我们如何在里面找到我们想要的那个数据.此时数据本身没有特征,所以我们需要的那个数据可能出现

一步一步写算法(之 算法总结)

原文:一步一步写算法(之 算法总结) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 自10月初编写算法系列的博客以来,陆陆续续以来写了几十篇.按照计划,还有三个部分的内容没有介绍,主要是(Dijkstra算法.二叉平衡树.红黑树).这部分会在后面的博客补充完整.这里主要是做一个总结,有兴趣的朋友可以好好看看,欢迎大家提出宝贵意见. (1) 排序算法 快速排序 合并排序 堆排序 选择排序 基数排序 冒泡排序 插入排序 希尔排序 链表排序