【算法训练营】(day5)

环形链表

在这里插入图片描述
解题思路:
这道题我们使用快慢指针的方法,如果有节点,快指针走到会回头于慢指针汇合,根据这个思想我们解答一下这个题目。

bool hasCycle(struct ListNode *head) {
	if (head == NULL || head->next == NULL)
	{
		return false;
	}
	ListNode* slow = head;
	ListNode* fast = head->next;
	while (slow!=fast)
	{
		if (fast == NULL || fast->next == NULL)
			return false;
		slow = slow->next;
		fast = fast->next->next;
	}
	return true;
}

环形链表Ⅱ

在这里插入图片描述
解题思路:
假设链表环前有 aa 个节点,环内有 bb 个节点
本题核心思路:走 a+nba+nb 步一定处于环的入口位置

利用快慢指针 fast 和 slow,fast 一次走两步,slow 一次走一步
当两个指针第一次相遇时,假设 slow走了 ss 步,下面计算 fast 走过的步数
i. fast 比 slow 多走了 nn 个环:f = s + nbf=s+nb
ii. fast 比 slow 多走一倍的步数:f = 2sf=2s --> 跟上式联立可得 s = nbs=nb
iii. 综上计算得,f = 2nbf=2nb,s = nbs=nb
也就是两个指针第一次相遇时,都走过了环的倍数,那么再走 aa 步就可以到达环的入口
让 fast 从头再走,slow 留在原地,fast 和 slow均一次走一步,当两个指针第二次相遇时,fast 走了 aa 步,slow 走了 a+nba+nb 步
此时 slow 就在环的入口处,返回 slow

struct ListNode *detectCycle(struct ListNode *head) {
	if (head == NULL || head->next == NULL)
	{
		return false;
	}
	ListNode* slow = head;
	ListNode* fast = head->next;
	while (fast != NULL)
	{
		slow = slow->next;
		if (fast->next == NULL)
		{
			return NULL;
		}
		fast = fast->next->next;
		if (fast == slow)
		{
			ListNode* ptr = head;
			while (ptr != slow)
			{
				ptr = ptr->next;
				slow = slow->next;
			}
			return ptr;
		}
		return NULL;
	}

复制带随机指针的链表

在这里插入图片描述
解题思路:
我们首先将该链表中每一个节点拆分为两个相连的节点这样,我们可以直接找到每一个拷贝节点 的随机指针应当指向的节点,即为其原节点的随机指针指向的节点 的后继节点需要注意原节点的随机指针可能为空,我们需要特别判断这种情况。
当我们完成了拷贝节点的随机指针的赋值,我们只需要将这个链表按照原节点与拷贝节点的种类进行拆分即可,只需要遍历一次。同样需要注意最后一个拷贝节点的后继节点为空,我们需要特别判断这种情况。

class Solution {
public:
    Node* copyRandomList(Node* head) {
        if (head == nullptr) {
            return nullptr;
        }
        for (Node* node = head; node != nullptr; node = node->next->next) {
            Node* nodeNew = new Node(node->val);
            nodeNew->next = node->next;
            node->next = nodeNew;
        }
        for (Node* node = head; node != nullptr; node = node->next->next) {
            Node* nodeNew = node->next;
            nodeNew->random = (node->random != nullptr) ? node->random->next : nullptr;
        }
        Node* headNew = head->next;
        for (Node* node = head; node != nullptr; node = node->next) {
            Node* nodeNew = node->next;
            node->next = node->next->next;
            nodeNew->next = (nodeNew->next != nullptr) ? nodeNew->next->next : nullptr;
        }
        return headNew;
    }
};

评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值