转载请注明出处:http://blog.csdn.net/ns_code/article/details/22097191


    题目:

Given a circular linked list, implement an algorithm which returns node at the beginning of the loop.

DEFINITION

Circular linked list: A (corrupt) linked list in which a node’s next pointer points to an earlier node, so as to make a loop in the linked list.

EXAMPLE

Input: A -> B -> C -> D -> E -> C [the same C as earlier]

Output: C

    翻译:

给定一个循环链表,实现一个算法返回这个环的开始结点。

定义:

循环链表:链表中一个结点的指针指向先前已经出现过的某个结点,导致链表中出现环。

示例:

输入:A -> B -> C -> D -> E -> C [结点C在之前已经出现过]

输出:结点C

    思路:

最直观且容易理解的方法(借鉴编程之美上的思路)是:

设两个指针p1和p2,一个移动速度快(每次移动两个节点的距离),一个移动速度慢(每次移动一个节点的距离),刚开始均指向表头,如果链表中存在环,则快指针最终会追上慢指针。二者遇的节点肯定是环中的一个节点,此时我们固定其中一个指针p1,而后以每次一个节点的速度移动p2,记录下p2最终又回到p1所在节点位置时走过的节点数M,M即为环中节点的个数。而后我们再将两个指针同时指向表头,先固定p1,让p2以每次一个节点的速度移动M个节点,而后让p1和p2同时移动,这样当p1刚到环入口时,p2刚好转了一圈回到环入口,因此二者相遇的节点便是环开始的节点。

Hawstein的blog中给出了另外两种方法,一种也是设置上面两个指针来分析的,貌似有点繁琐,没仔细看。另一种用哈希表,这个我也想到了,但是感觉没法恰当地契合,而且用地址做哈希表的键值,对内存貌似有很大的浪费哦,所以感觉这个不算是个很好的方法!另外,对C++也不熟啊!哎。。。搞java的人伤不起啊!

我还想了另外一种方法,在链表中多加一个域(这种方法可能很离谱,就好像给你个问题去解决,你把问题的参数给改了,然后再去解决它,但我觉得可以作为解决一些问题的思路,其实依然有哈希的思想在里面),如下:

typedef struct Node
{ElemType data;bool flag;struct Node *next;
}

建链表时,flag全部置为false,而后从头遍历时,每遍历一个节点,如果发现其flag为false,则将其置为true,如果发现其为true,则说明该节点已经遍历过了,那第一次出现访问到flag为ture的节点便是环开始的节点。

    实现代码:

我们这里采用第一种方法,我们在程序中构建好如下循环链表:

完整代码如下:

/*********************************
题目描述:
求一个有环的单链表中环开始处的节点
Date:2014-03-26
**********************************/
typedef int ElemType;typedef struct Node
{ElemType data;struct Node *next;
}Node,*pNode;#include<stdio.h>
#include<stdlib.h>/*
定义一个速度为2的快指针,一个速度为1的慢指针,
如果链表中有环,则返回两个指针相遇的节点,
如果没有链表中没有环,则返回NULL。
*/
pNode WetherCircle(pNode pHead)
{if(!pHead)return NULL;pNode p1 = pHead;pNode p2 = pHead;//直到二者相遇,退出循环while((p1 && p2 && p1!=p2) || (p1==p2 && p1==pHead && p2==pHead)){p1 = p1->next;p2 = p2->next->next;}if(p1 == p2)return p1;elsereturn NULL;
}/*
计算环中的节点个数
*/
int CircleLen(pNode pHead)
{pNode p = WetherCircle(pHead);if(!p)return 0;int count = 1;//固定一个指针,另一个指针在环中移动pNode p1 = p->next;while(p1 != p){count++;p1 = p1->next;}return count;
}/*
求环开始的节点
*/
pNode CircleBegin(pNode pHead)
{int len  = CircleLen(pHead);if(len < 1)return NULL;pNode p1 = pHead;pNode p2 = pHead;int i;//第一个指针先移动len个节点for(i=0;i<len;i++)p1 = p1->next;//而后一起移动while(p1 != p2){p1 = p1->next;p2 = p2->next;}return p1;
}/*
建立如下所示的带环的单链表
1->2->3->4->5->6->7->4
即环的入口节点为date域为4的节点
*/
pNode create_CircleList()
{pNode pHead = (pNode)malloc(sizeof(Node));if(!pHead){printf("malloc faild!\n");exit(-1);}pHead->data = 1;pNode r = pHead;int i;for(i=0;i<6;i++){pNode pNew = (pNode)malloc(sizeof(Node));if(!pNew){printf("malloc faild!\n");exit(-1);}pNew->data = i + 2;r->next = pNew;r = pNew;}//将最后一节点的next指向第四个节点,形成环r->next = pHead->next->next->next;return pHead;
}int main()
{pNode pHead = create_CircleList();pNode p = CircleBegin(pHead);printf("The date in the beginNode of the Circle is:%d\n",p->data);return 0;
}

    测试结果:

    注:代码开源到我的Github:https://github.com/mmc-maodun/CareerCup

【CareerCup】 Linked Lists—Q2.5相关推荐

  1. 【leetcode】Linked List Cycle I II

    Given a linked list, determine if it has a cycle in it. Can you solve it without using extra space? ...

  2. 【leetcode】Intersection of Two Linked Lists

    Write a program to find the node at which the intersection of two singly linked lists begins. For ex ...

  3. 【LeetCode从零单排】No.160 Intersection of Two Linked Lists

    题目 Write a program to find the node at which the intersection of two singly linked lists begins. For ...

  4. 114. Flatten Binary Tree to Linked List【Medium】【将给定的二叉树转化为“只有右孩子节点”的链表(树)】...

    Given a binary tree, flatten it to a linked list in-place. For example, given the following tree: 1/ ...

  5. 【TensorRT】TensorRT was linked against cudnn 8.6.0 but loaded cudnn 8.3.2

    [TensorRT]TensorRT was linked against cudnn 8.6.0 but loaded cudnn 8.3.2 1 电脑环境 2 问题描述 3 直接原因 4 解决办法 ...

  6. 【LeetCode】【数组归并】Merge k Sorted Lists

    描述 Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity ...

  7. 【LeetCode】深搜DFS(共85题)

    [98]Validate Binary Search Tree [99]Recover Binary Search Tree [100]Same Tree [101]Symmetric Tree [1 ...

  8. C#LeetCode刷题之#160-相交链表(Intersection of Two Linked Lists)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3824 访问. 编写一个程序,找到两个单链表相交的起始节点. 例如 ...

  9. 【缓存】Redis入门

    redis命令 命令行链接redis  redis-cli -h localhost -p 6478 -a password keys * 可以查看系统中所有的key值,在开发环境非常有用的命令 se ...

最新文章

  1. C - Catch That Cow(BFS)
  2. python 多级菜单_python多级菜单
  3. 磁头号和起始扇区的计算方法------软盘结构
  4. delphi的接口support_学习到的关于Delphi的接口
  5. python把英语句子成分字母_句子成分的表达字母
  6. 重返数学史的黄金时代,由数学推动诞生的人工智能,一部人类智慧形成的历史...
  7. c 语言比较三个字符串,C语言字符篇(三)字符串比较函数
  8. Linux内存管理:转换后备缓冲区(TLB)原理
  9. 35张动图:关于机房空调水冷系统和风冷系统
  10. 蓝星微商城源码+搭建教程源码
  11. hyper-v与Docker for windows和VMBox的冲突
  12. 计算机英语朗读音频,新课标小学英语阅读精选(MP3+中英字幕) 第72期:电脑
  13. 如何让你的Linux程序程序后台运行
  14. Google搜索从入门到精通
  15. 【开源WebGIS】07-Openlayers+Vue 测量功能-02
  16. 自定义Dialog 实现 仿网易云音乐的隐私条款声明弹框
  17. 2021-08-17 WPF控件专题 Canvas 控件详解
  18. 使用Ultra Libraian生成Altium Designer元件库
  19. oracle中lt;gt;是什么意思,c++中vectorlt;intgt;和vectorlt;int*gt;的用法区别
  20. 谷歌电子市场学习笔记第三天

热门文章

  1. 鸿蒙轻量设备侧Camera应用中的Surface使用
  2. 华为新平板以美好体验定义青春
  3. webpack4踩坑——图片打包
  4. 2021年全球拍立得消耗品(胶片和相纸)收入大约205.8百万美元,预计2028年达到291百万美元
  5. Charles工具使用教程,以及注意事项。
  6. Win10彻底关闭Windows Defender
  7. VGA、HDMI、DP你都懂吗?显示接口大盘点
  8. 三个蛤蜊三块肉才能称得上“老板”
  9. 云南将建5G基站20万个,总投资达500亿实现5G网络全覆盖
  10. 平面几何中的几个著名定理