题目:判断链表中是否有环
描述:判断给定的链表中是否有环。如果有环则返回true,否则返回false。
你能给出空间复杂度的解法么?输入分为2部分,第一部分为链表,第二部分代表是否有环,然后回组成head头结点传入到函数里面。-1代表无环,其他的数字代表有环,这些参数解释仅仅是为了方便读者自测调试。
示例1:输入:{3,2,0,-4},1,返回值:true,说明:第一部分{3,2,0,-4}代表一个链表,第二部分的1表示,-4到位置1,即-4->2存在一个链接,组成传入的head为一个带环的链表,返回true。
解法一:
思路分析:判断链表当中是否存在环,我们可以使用指针判别法,定义两个指针的存在,将两个指针同时从链表的头部出发,一个指针一次走一个next的值,另一个指针走两个next,如果走的快的指针追上慢的指针,就说明该链表为环形链表;如果走的快的指针到了链表末尾也没有追上走的慢的指针,那么链表就不是环形链表。
举例图示:输入:{3,2,0,-4},1
题上说明,1代表-4到位置1存在着一个链表,所以我们得到这道题应该返回true。下面进行判断。
| 链表 | 3 | 2 | 0 | -4 |
| 指针所指方位 | i和j |
|
|
|
| i = i -> next,j = j -> next ->next | ||||
| 第一次 |
| i | j |
|
| 第二次 |
| j | i |
|
| 第三次 |
|
|
| i,j |
| 返回结果值true | ||||
具体C语言程序如下所示:
#include<stdbool.h>
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/**
*
* @param head ListNode类
* @return bool布尔型
*/
bool hasCycle(struct ListNode* head ) {
struct ListNode*p1 = head,*p2 = head;//定义两个指针
while((p2 != NULL) && (p2->next != NULL) ){//停止条件
p1 = p1->next;//走一步
p2 = p2->next->next;//走两步
if(p1 == p2){
return 1;
}
}
return 0;
}
假设链表的节点数量为n,则该算法的时间复杂度为O(n)。除两个指针外,没有使用任何额外的存储空间,所以空间复杂度是O(1)。
解法二:
思路分析:同样可以采用java来解决问题,首先创建一个HashSet集合,用来存储曾经遍历过的结点,通过从头节点开始,依次遍历链表当中的每一个结点,每次遍历一个结点就与HashSet集合当中存储的结点作比较,如果发现HashSet当中存在相同结点的序号,则说明链表当中有环,如果不存在相同序号,就把新节点存入HashSet集合当中,重复以上操作。
具体java程序如下所示:
import java.util.Set;
import java.util.HashSet;
/**
* 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) {
Set<ListNode> new1 = new HashSet<>();
while(head != null){
if(new1.contains(head))//如果一旦包含
return true;
new1.add(head);//否则将其添加进去
head = head.next;//下一个
}
return false;
}
}
假设从链表表头到刚开始的距离是D,链表的长度为S,则每一次HashSet查找元素的时间复杂度为O(1),总体的时间复杂度为O(N),空间复杂度为D+S-1,所以为O(N)。

京公网安备 11010502036488号