算法训练营(day5)

Posted flyyyya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法训练营(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;
    }
};

以上是关于算法训练营(day5)的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode刷题笔记-动态规划-day5

LeetCode刷题笔记-动态规划-day5

LeetCode刷题笔记-动态规划-day5

LeetCode算法,每日一题,冲击阿里巴巴,day5

培训补坑(day5:最小生成树+负环判断+差分约束)

2021年SWPUACM暑假集训day5单调栈算法