国庆,同学来我这里,疯了几天,什么都没学,好有罪恶感,关键是学习有点进入不了状态,看到两个小算法题,找找学习的感觉
一、检查链表中是否有环
题目描述:
给定一个单链表,判定其中是否有环,即链表的最后一个结点的next指针不是空指针,而是指向了链表中的某一个结点。
思考:
假设最后一个结点的next指针指向的是头结点,即:1->2->3->4->5->1,
整体成环,这种情况比较好解决,只需一个指针指向头结点,另一个指针向后遍历,当两个指针指向同一结点时,可以判定是有环的。
假设最后一个结点的next指针指向的是除头结点外的某一结点,如:1->2->3->4->5->3,
局部成环,这种情况就不能用一个指针指向某一指定的结点,然后遍历,从而判断是否为环,因为这一“某一指定的结点”是不确定的,你不能让一个指针指向2(例子中是2)。
于是,有了下面的思路。
思路一:
反转链表,反转时,会用到3个指针,分别为指向遍历时当前的结点的current指针,指向反转后的子链表的头结点的指针temp,及指向遍历时当前结点的下一个结点的next指针,如果在反转时,出现了next指向头结点的情况,那么肯定是有环的。
如:1->2->3->4->5->3,反转时,会有以下步骤:
①temp = NULL; current = 1; next = 2; 此时,反转生成的子链表:1->NULL
②temp = 1; current = 2; next = 3; 此时,反转生成的子链表:2->1->NULL
③temp = 2; current = 3; next = 4; 此时,反转生成的子链表:3->2->1->NULL
④temp = 3; current = 4; next = 2; 此时,反转生成的子链表:4->3->2->1->NULL
⑤temp = 4; current = 5; next = 3; 此时,反转生成的子链表:5->4->3->2->1->NULL
⑥temp = 5; current = 3; next = 2; 此时,反转生成的子链表:3->5->4->3 断开了 2->1->NULL
⑦temp = 3; current = 2; next = 1; 此时,反转生成的子链表:2->3->5->4->3 断开了 1->NULL
⑧判断到了next指向了头结点,说明有环。
代码为:
int is_cycle_list(Node* head) {
Node *temp, *current, *next;
if(!head)
return FALSE;
temp = NULL;
current = head;
next = head->next;
current->next = temp;
while(next) {
if(next == head) {
return TRUE;
}
temp = current;
current = next;
next = next->next;
current->next = temp;
}
return FALSE;
}
思路二:
用两个指针one_step,two_step,一块向后遍历,遍历时,one_step每次向后跳一步,two_step每次向后跳两步,直到two_step指向NULL,说明没有环(two_step肯定比one_step先到链表的尾部),或者两个指针都没有遍历到NULL结点,而两指针指向了同一结点,说明two_step赶上了one_step,此时肯定是有环的。
代码为:
int is_cycle_list(Node *list) {
Node *one_step, *two_step;
one_step = two_step = list;
if(!list) {
return FALSE;
}
while(two_step) {
one_step = one_step->next;
two_step = two_step->next;
if(!two_step) {
return FALSE;
}
two_step = two_step->next;
if(one_step == two_step) {
return TRUE;
}
}
return FALSE;
}
第一种方法反转了链表,需要再反转回来,才能还原到初始链表
扩展一下,如果判断到一个链表内部是有环的,如何找到从哪个结点开始,形成的环???
谁有好方法啊!!!!
分享到:
相关推荐
在软件开发、算法设计以及计算机科学的笔试或面试中,经常会遇到需要检查链表中是否存在环的问题。环是指在链表中,某个节点的next指针指向了链表中的任意一个节点,从而形成了一个闭环。这种结构如果在实际应用中...
1. **首尾相连法**:将其中一个链表的尾部连接到其头部形成环,然后利用上述方法检测另一个链表是否有环。如果有环,则两个链表相交,且环的入口即为相交的第一个点。 2. **遍历比较法**:分别遍历两个链表,记录下...
通过while循环,每次迭代都检查当前报数是否等于m,如果是,则该节点出列,更新m为出列者的密码,并移除该节点。出列顺序通过输出编号来记录。 在主函数`main`中,首先创建一个单循环链表,然后读取用户输入的总...
在处理链表问题时,有时候我们需要检查链表是否存在环,即是否存在某个节点的`next`指针指向了链表中的早期节点,形成了一个闭环。LeetCode 的第 141 题就是这样一个问题,它要求我们判断给定的链表是否包含环。 ...
2. 检查链表是否有环,因为有环的链表求交集问题需要特殊处理。 3. 在创建新的交集链表时,要注意不要改变原始链表的结构。 在编写代码时,应注重代码的清晰性和可读性,合理地使用注释来解释每一步操作的目的。...
由于题目中假设链表不含环,可以尝试将两个链表拼接在一起形成一个新的链表,然后检查新的链表是否存在环。如果存在环,则说明两个原始链表相交;否则,不相交。具体操作是将第二个链表的尾部连接到第一个链表的头部...
检查时间复杂度是双向链表操作的重要考虑因素,因为插入操作通常比单向链表更快。 在链表操作中,时间复杂度是非常关键的性能指标。对于单向链表,插入或删除一个节点通常需要O(n)的时间,因为在最坏的情况下,可能...
7. **判断链表环**:检查链表中是否存在环。Floyd's Cycle-Finding Algorithm(快慢指针)是常用的方法,快指针每次移动两个节点,慢指针每次移动一个,如果存在环,两者会在环内相遇。 8. **链表排序**:对链表...
为了处理这种情况,我们需要先检测链表中是否有环。常用的检测方法包括快慢指针法(Floyd判断环算法)和龟兔赛跑算法。一旦发现环,可以使用特定的算法将其解开,然后再判断链表是否相交。 总之,判断链表是否相交...
`josephus`函数内部可能包含一个循环,每次循环代表一次报数,循环体内会检查当前节点是否是被剔除的目标,如果是,则更新链表并剔除节点,然后移动到下一个节点继续报数。这个过程会一直持续,直到链表只剩下最后一...
#### 二、链表是否有环的检测 链表如果有环,则存在一个或多个节点,这些节点可以通过跟随`next`指针被重复访问。本篇内容还介绍了一种简单的方法来判断链表是否存在环。 ##### 1. 快慢指针法 快慢指针法是检测...
对于数组,可以用for循环来迭代数组,检查每个元素是否被淘汰;对于链表,可以使用while循环,通过遍历链表节点直到找到最后一个。为了优化算法,还可以使用栈或队列来辅助处理,例如,将被淘汰的节点放入栈中,以...
- 如果链表有环,先判断两链表是否都有环,然后检查一链表的相遇点是否在另一链表上。 - 无环时,直接比较两个链表的尾节点。 - 有环时,用快慢指针判断各自的环,然后判断相遇点是否在另一个链表上。 理解这些...
这种方法简化了链表操作,尤其是插入和删除,因为头结点的存在使得无需检查是否为空链表。 这些链表结构各有优缺点,适用于不同的场景。例如,单链表适合简单的线性操作,双向链表适用于需要频繁进行正反向遍历的...
18. **循环检测**:通过特定算法,如Floyd-Warshall,检查图中任意两点间是否存在环。 19. **可达性判断**:确定图中任意两个顶点是否可达。 20. **最短路径矩阵**:计算图中所有顶点对之间的最短路径。 这些方法...
然后,通过循环遍历链表,每次遍历时检查当前节点是否需要被删除,如果是,则通过修改指针关系来移除该节点。为了记录“幸存者”,我们可以设置一个特殊标记的节点,或者用额外的变量保存其位置。 例如,`...
通过检查链表头节点的next指针是否指向头节点本身来判断链表是否为空。 8. **合并循环链表**: 如果有两个循环链表,可以设计算法将它们合并为一个新的循环链表。这通常涉及到找到两个链表的适当连接点。 9. **...
7. **其他辅助方法**:如检查链表是否为空、获取链表长度等。 ```cpp bool isEmpty() { ... } int size() { ... } ``` 接下来,`main.cpp` 文件可能包含测试这些功能的代码,例如创建循环链表实例,插入元素,然后...
5. `boolean isEmpty()`:检查链表是否为空。 6. `int size()`:返回链表中的元素数量。 7. `void display()`:打印链表中的所有元素,用于调试和展示链表状态。 接下来是实现这个接口的类,我们称之为`...