留个疑问解决,c语言实现链表哈希原理待掌握
快慢指针理解
没环很好判断,下面只证明有环,好比快指针走的是慢指针两倍,如果慢指针走了k步后进入环中,那么快指针走了2k步,快指针比慢指针多走了k步,k一定可以是环的长度整数倍,因为k.可以一直一个一个往上加,肯定可以是环长度整数倍。刚开始即使快指针在慢指针前面一个时候,也同理,一下一个一个追,肯定可以相遇,而且还是在慢指针走完一圈内相遇。
每次多一步,肯定会在慢指针走一圈内相遇,每次多一步,快指针终会赶上。而且不会错过。
如果快指针走的速度是慢指针n倍,如果慢指针走了k步后进入环中,那么快指针走了nk步,快指针比慢指针多走了(n-1)k步,(n-1)k一定可以是环的长度整数倍., 因为k一直一个一个加,肯定可以是环的长度整数倍,肯定能相遇。
所以肯定能推出一定能相遇
同理可以推出慢指针不论走多少步,只要快指针比慢指针快就行.肯定能相遇.
题目内容
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
进阶:
你能用 O(1)(即,常量)内存解决此问题吗?
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
提示:
链表中节点的数目范围是 [0, 104]
-105 <= Node.val <= 105
pos 为 -1 或者链表中的一个 有效索引 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/linked-list-cycle
c语言解答(快慢指针)
/**
*快慢指针
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head) {
//增加这句话是防止定义的指针指向空指针导致报错
if (head == NULL || head->next == NULL) {
return false;
}
//定义快慢指针,快指针每次走的步数是慢指针两倍
struct ListNode*slow=head;
struct ListNode*fast=head->next;
//如果两指针相遇,那么只有一种情况那就是链表中存在环
while(slow!=fast){
//判断fastf和她下一步是否为空,否则要不又会导致fast指向空指针的下一个,导致报错
if(fast==NULL||fast->next==NULL){
return false;
}
slow=slow->next;
fast=fast->next->next;
}
return true;
}
java语言解答(快慢指针)
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
//增加这句话是防止定义的指针指向空指针导致报错
if(head==null||head.next==null){
return false;
}
//定义快慢指针,快指针每次走的步数是慢指针两倍
ListNode slow=head;
ListNode fast=head.next;
//如果两指针相遇,那么只有一种情况那就是链表中存在环
while(fast!=slow){
//判断fastf和她下一步是否为空,否则要不又会导致fast指向空指针的下一个,导致报错
if(fast==null||fast.next==null){
return false;
}
slow=slow.next;
fast=fast.next.next;
}
return true;
}
}
放个大佬的邪道解法,说明了解计算机工作原理对算法了解是有帮助的,虽然我原本就这么认为,但是感觉这个例子也恰好证明了,没有白学习的知识
堆大小足够的话,操作系统malloc一般是向上生长的,如果链表有环的话,那么next的地址一般比当前地址小,所以:
bool hasCycle(struct ListNode *head) {
struct ListNode *p = head;
while (p != NULL && p->next != NULL) {
if (p->next <= p) {
return true;
}
p = p->next;
}
return false;
}
作者:blanca
链接:https://leetcode-cn.com/problems/linked-list-cycle/solution/xie-dao-jie-fa-zhan-sheng-9261-by-blanca/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
我认为还可以直接暴力遍历,如果遍历的数量超过10的5次方直接返回有环
总结
我忽然感觉认为练习一题多解,自己解决出来看看别人的另一种解法对自己的思维也是另一种提升.