判断环形链表
题目示意
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
示例1
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例2
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
分析
判断是否环的问题,可以类似转化为判断是否重复的问题,那么判断重复问题我们一般首先考虑哈希表来做,如果问题对空间有限制,用双指针策略来做
先来看看简单的哈希表策略
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
//hashMethod
public class Solution {
public boolean hasCycle(ListNode head) {
Set<ListNode> set = new HashSet<>();
while (head!=null){
if (set.contains(head)){ return true ;}
else {
set.add(head);
head = head.next;
}
}
return false ;
}
}
- 不用像之前判断重复问题一样,得先把链表结点放入哈希表,在判断环问题,我们只需边遍历边入表即可
双指针
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!=null&&fast.next!=null){
if (fast==slow) return true ;
slow = slow.next ;
fast = fast.next.next ;
}
return false ;
}
}
这个…直接看代码能看懂吧
在删除排序链表(或数组)中的重复元素这个问题中,我们也使用了双指针,可以类比看看
==========update by 2020 4/16 ==================
C++源代码(经VS2015、devC++运行通过)
#include "stdio.h"
#include "string.h"
#include "ctype.h"
#include "stdlib.h"
#include "io.h"
#include "math.h"
#include "time.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 /* 存储空间初始分配量 */
typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */
Status visit(ElemType c)
{
printf("%d ", c);
return OK;
}
typedef struct ListNode
{
ElemType val;
struct ListNode *next;
}ListNode;
typedef struct ListNode *LinkList; /* 定义LinkList */
/* 初始化顺序线性表 */
Status InitList(LinkList *L)
{
*L = (LinkList)malloc(sizeof(ListNode)); /* 产生头结点,并使L指向此头结点 */
if (!(*L)) /* 存储分配失败 */
return ERROR;
(*L)->val = NULL;
(*L)->next = NULL; /* 指针域为空 */
return OK;
}
/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
Status ListInsert(LinkList *L, int i, ElemType e)
{
int j;
LinkList p, s;
p = *L;
j = 1;
while (p && j < i) /* 寻找第i个结点 */
{
p = p->next;
++j;
}
if (!p || j > i)
return ERROR; /* 第i个元素不存在 */
s = (LinkList)malloc(sizeof(ListNode)); /* 生成新结点(C语言标准函数) */
s->val = e;
s->next = p->next; /* 将p的后继结点赋值给s的后继 */
p->next = s; /* 将s赋值给p的后继 */
return OK;
}
/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
Status ListTraverse(LinkList L)
{
LinkList p = L->next;
while (p)
{
visit(p->val);
p = p->next;
}
printf("\n");
return OK;
}
int ListLength(LinkList L)
{
int i = 0;
LinkList p = L->next; /* p指向第一个结点 */
while (p)
{
i++;
p = p->next;
}
return i;
}
Status CircleLink(int len, LinkList *L ,int pos) {
if (pos!=(-1)) //若pos=-1则代表不设环
{
LinkList p,s;
p = *L;
s = *L;
/*找到末尾指针*/
for (int i = 1; i <= len; i++) {
p = p->next;
}
for (int j = 1; j <= pos; j++) {
s = s->next;
}
p->next = s->next;
return 1;
}
return 0;
}
int main()
{
LinkList L;
Status i;
int len,pos;
/*1.初始化单链表*/
i = InitList(&L);
/*2.依次采用尾插法插入abcde元素*/
ListInsert(&L, 1, 3);
ListInsert(&L, 2, 2);
ListInsert(&L, 3, 0);
ListInsert(&L, 4, -4);
ListTraverse(L);
len = ListLength(L);
printf("请输入位置position");
scanf_s("%d", &pos);
i = CircleLink(len, &L, pos);
if (i)
{ printf("true\nthe position = %d\n",pos);
}
else {
printf("false");
}
system("pause");
}