一个认为一切根源都是“自己不够强”的INTJ
个人主页:用哲学编程-CSDN博客
专栏:每日一题——举一反三
Python编程学习
Python内置函数
目录
快慢指针 (Floyd's Cycle-Finding Algorithm)
我的写法
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */
bool hasCycle(struct ListNode *head) {
// 定义两个指针,slow 和 quick,初始都指向链表的头节点
struct ListNode *slow = head;
struct ListNode *quick = head;
// 如果链表为空或只有一个节点,则不可能存在环,返回 false
if (!head || !head->next) {
return false;
}
// 使用 for 循环来遍历链表,循环条件是 slow 和 quick 及其下一个节点都不为 NULL
for (; slow && slow->next && quick && quick->next && quick->next->next;) {
// slow 指针每次移动一步
slow = slow->next;
// quick 指针每次移动两步
quick = quick->next->next;
// 如果 slow 和 quick 指针相遇,则说明链表中存在环
if (slow == quick) {
return true;
}
}
// 如果循环结束后没有相遇,说明链表中不存在环,返回 false
return false;
}
这段代码实现了一个检测单链表是否存在环的功能,采用的是经典的快慢指针(Tortoise and Hare)算法。下面是对这段代码的专业点评及其时间复杂度和空间复杂度分析。
专业点评
- 代码结构清晰:
- 代码结构合理,使用变量命名清晰,便于理解。
- 初始检查部分有效地处理了特殊情况(空链表或只有一个节点的链表)。
- 循环条件:
- 循环条件健全,确保在链表遍历过程中不会发生空指针引用错误。
- for 循环中使用多个条件确保 slow 和 quick 及其下一个节点都有效。
- 快慢指针逻辑:
- 快指针每次移动两步,慢指针每次移动一步,有效地检测链表中的环。
- 如果存在环,快慢指针必定会相遇。
- 代码简洁性:
- 代码简洁,逻辑明确,没有冗余的操作。
时间复杂度分析
- 最坏情况:在没有环的情况下,快指针和慢指针遍历链表的每个节点。
- 在这种情况下,快指针遍历节点数大约为 n/2,慢指针遍历节点数为 n,其中 n 是链表的节点数。
- 因此,时间复杂度为 O(n)。
- 最优情况:在存在环的情况下,快慢指针会在环内相遇。
- 最多需要 O(n) 的时间,因为快指针和慢指针最终会在环内相遇。
综合来看,时间复杂度为 O(n)。
空间复杂度分析
- 该算法只使用了两个额外的指针变量 slow 和 quick,不依赖于链表的大小。
- 因此,空间复杂度为 O(1)。