【C】单链表面试题(进阶)

1. 判断单链表是否带环?若带环,求环的长度?求环的入口点?

//判断是否带环
ListNode* IsCycle(ListNode* list)
{
	ListNode* fast = list, *slow = list;
	while (fast && fast->next)
	{
		slow = slow->next;
		fast = fast->next->next;
		if (fast == slow)
		{
			return NULL;
		}
	}
}


//求环的长度
int GetCycleLen(ListNode* list, ListNode* meetNode)
{
	if (NULL == list || meetNode == NULL)
	{
		return 0;
	}
	int count = 1;
	ListNode* cur = meetNode;
	while (cur->next != meetNode)
	{
		count++;
		cur = cur->next;
	}
	return count;
}


//求环的入口点
ListNode* GetcycleEntry(ListNode* list, ListNode* meetNode)
{
	if (NULL == list || meetNode == NULL)
	{
		return 0;
	}
	while (1)
	{
		if (list == meetNode)
		{
			return list;
		}
		list = list->next;
		meetNode = meetNode->next;
	}
	return meetNode;
}

2. 判断两个链表是否相交,若相交,求交点。(假设链表不带环)

两个链表相交有公共的链存在,即有相同的尾就相交。


//判断两个链表是否相交
bool CheckIsMeet(ListNode* list1, ListNode* list2)
{
	if (list1 == NULL || list2 == NULL)
	{
		return false;
	}
	ListNode* tail1 = list1;
	ListNode* tail2 = list2;
	while (tail1->next)
	{
		tail1 = tail1->next;
	}
	while (tail2->next)
	{
		tail2 = tail2->next;
	}
	if (tail1 == tail2)
	{
		return true;
	}
	else
	{
		return false;
	}
}

//求交点
ListNode* GetMeetNode(ListNode* list1, ListNode* list2)
{
	ListNode* cur1 = list1;
	ListNode* cur2 = list2;
	int len1 = 0, len2 = 0;
	while (cur1)
	{
		len1++;
		cur1 = cur1->next;
	}
	while (cur2)
	{
		len2++;
		cur2 = cur2->next;
	}

	ListNode* longList = list1, *shortList = list2;
	if (len1 < len2)
	{
		longList = list2;
		shortList = list1;
	}
	int gap = abs(len1 - len2);
	while (gap--)
	{
		longList = longList->next;
	}
	while (longList)
	{
		if (longList == shortList)
		{
			return longList;
		}
		longList = longList->next;
		shortList = shortList->next;
	}
	return NULL;
}

3.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】

1)L1 和 L2 都不带环,求链表的尾判断是否带环,及求交点。

2)L1 带环,L2 不带环;或 L1 不带环,L2 带环,不相交。

3)L1 和 L2 都带环,分三种情况:

(1)入口点在环外----交点+入口点

(2)入口点在环内----两个点既是交点,也是入口点。

(3)不相交。

ListNode *IntersectRing(ListNode *list, ListNode *plist)
//判断两个链表是否相交,若相交,求交点。
{
	ListNode* oep1 = OepRing(list);
	ListNode* oep2 = OepRing(plist);

	//两个链表都不带环
	if ((oep1 == NULL) && (oep2 == NULL))
	{
		return Intersect(list, plist);
	}

	//一个带环,一个不带环(不相交) 
	else if (((oep1 == NULL) && oep2) || ((oep2 == NULL) && oep1))
	{
		return NULL;
	}

	//两个都带环   
	else
	{
		//尾交(一个交点,一个入口点)
		//若两个链表的入口点一样则只有一个交点(交点也是入口点)
		//两链表各自环入口点已经求出,把list的环从入口点断开
		//可以转换成求不带环的相交链表求交点
		if (oep1 == oep2)
		{
			oep1->next = NULL;
			return Intersect(list, plist);

		}

		else
		{
			//环交 
			//环交会有两个入口点,从一个入口点出发遍历环
			//遍历的过程中有结点等于另一个入口点,则表示环交,返回指向那个结点的指针(就是交点)
			//有两个交点,交点也是入口点。
			//否则,就是两个带环链表不相交


			//在这里返回的是第二个链表的入口点
			//也是第一个链表在第二个链表中的交点
			ListNode* cur = oep1->next;
			while (cur != oep1)
			{
				if (cur == oep2)
				{
					return oep1;
				}
				cur = cur->next;
			}

			/*//在这里返回的是第一个链表的入口点
			//也是第二个链表在第一个链表中的交点

			ListNode* cur = oep2->next;
			while (cur != oep2)
			{
			if (cur == oep1)
			{
			return oep2;
			}
			cur = cur->next;
			}*/
			return NULL;    //不相交  
		}
	}
}


4.复杂链表的复制。一个链表的每个节点,有一个指向 next 指针指向下一个节点,还有一个 random 指针指向这个链表中的一个随机节点或者 NULL,现在要求实现复制这个链表,返回复制后的新链表。 


void NewBackPrime(ComplexNode *list)
//把新创建的每个结点链接到原先结点的后面
{
	ComplexNode *cur = list;
	while (cur)
	{
		//每次新创建一个结点,让它指向原先结点指向的结点
		//新创建结点的data和原先结点一样
		ComplexNode *head = Init(cur->_data);
		head->_next = cur->_next;

		//新创建结点的指向的随机结点置空
		head->_random = NULL;

		//原先结点指向新创建的结点,这样整个链表就连到了一块
		cur->_next = head;

		//cur依次后移
		cur = head->_next;

	}
}

void ComplexNodeRandom(ComplexNode *list)
//复制随机结点
{
	ComplexNode *cur = list;
	while (cur)
	{
		//找到插入的新结点
		ComplexNode *head = cur->_next;

		//让新结点指向的随机结点 
		//去指向 
		//原先结点指向随机结点的后一个
		if (cur->_random)
		{
			head->_random = cur->_random->_next;
		}
		cur = head->_next;

	}
}

ComplexNode *RemoveNewCode(ComplexNode *list)
//让新创建链表的结点链接起来,原先链表的结点链接起来
{
	ComplexNode *cur = list;
	ComplexNode *head = NULL;
	ComplexNode *tmp = NULL;
	if (cur)
	{
		head = tmp = cur->_next;
		cur->_next = tmp->_next;
		cur = cur->_next;
	}
	while (cur)
	{
		//让新创建链表的结点链接起来
		tmp->_next = cur->_next;
		tmp = tmp->_next;

		//原先链表的结点链接起来
		cur->_next = tmp->_next;
		cur = cur->_next;
	}
	return head;

}

ComplexNode *ComplexList(ComplexNode *list)
//复杂链表的复制
{
	NewBackPrime(list);
	ComplexNodeRandom(list);
	return RemoveNewCode(list);
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值