题目:一个链表中包括环。怎样找出环的入口结点?


解题思路

  能够用两个指针来解决问题。先定义两个指针P1和P2指向链表的头结点。假设链表中环有n个结点,指针P1在链表上向前移动n步,然后两个指针以同样的速度向前移动。

当第二个指针指向环的入口结点时,第一个指针已经环绕着环走了一圈又回到了入口结点。

  剩下的问题就是怎样得到环中结点的数目。我们在面试题15的第二个相关题目时用到了一快一慢的两个指针。

假设两个指针相遇,表明链表中存在环。两个指针相遇的结点一定是在环中。

能够从这个结点出发。一边继续向前移动一边计数,当再次回到这个结点时就能够得到环中结点数了。

结点定义

  1. private static class ListNode {
  2. private int val;
  3. private ListNode next;
  4. public ListNode() {
  5. }
  6. public ListNode(int val) {
  7. this.val = val;
  8. }
  9. @Override
  10. public String toString() {
  11. return val +"";
  12. }
  13. }

代码实现

  1. public class Test56 {
  2. private static class ListNode {
  3. private int val;
  4. private ListNode next;
  5. public ListNode() {
  6. }
  7. public ListNode(int val) {
  8. this.val = val;
  9. }
  10. @Override
  11. public String toString() {
  12. return val +"";
  13. }
  14. }
  15. public static ListNode meetingNode(ListNode head) {
  16. ListNode fast = head;
  17. ListNode slow = head;
  18. while (fast != null && fast.next != null) {
  19. fast = fast.next.next;
  20. slow = slow.next;
  21. if (fast == slow) {
  22. break;
  23. }
  24. }
  25. // 链表中没有环
  26. if (fast == null || fast.next == null) {
  27. return null;
  28. }
  29. // fast又一次指向第一个结点
  30. fast = head;
  31. while (fast != slow) {
  32. fast = fast.next;
  33. slow = slow.next;
  34. }
  35. return fast;
  36. }
  37. public static void main(String[] args) {
  38. test01();
  39. test02();
  40. test03();
  41. }
  42. // 1->2->3->4->5->6
  43. private static void test01() {
  44. ListNode n1 = new ListNode(1);
  45. ListNode n2 = new ListNode(2);
  46. ListNode n3 = new ListNode(3);
  47. ListNode n4 = new ListNode(4);
  48. ListNode n5 = new ListNode(5);
  49. ListNode n6 = new ListNode(6);
  50. n1.next = n2;
  51. n2.next = n3;
  52. n3.next = n4;
  53. n4.next = n5;
  54. n5.next = n6;
  55. System.out.println(meetingNode(n1));
  56. }
  57. // 1->2->3->4->5->6
  58. // ^ |
  59. // | |
  60. // +--------+
  61. private static void test02() {
  62. ListNode n1 = new ListNode(1);
  63. ListNode n2 = new ListNode(2);
  64. ListNode n3 = new ListNode(3);
  65. ListNode n4 = new ListNode(4);
  66. ListNode n5 = new ListNode(5);
  67. ListNode n6 = new ListNode(6);
  68. n1.next = n2;
  69. n2.next = n3;
  70. n3.next = n4;
  71. n4.next = n5;
  72. n5.next = n6;
  73. n6.next = n3;
  74. System.out.println(meetingNode(n1));
  75. }
  76. // 1->2->3->4->5->6 <-+
  77. // | |
  78. // +---+
  79. private static void test03() {
  80. ListNode n1 = new ListNode(1);
  81. ListNode n2 = new ListNode(2);
  82. ListNode n3 = new ListNode(3);
  83. ListNode n4 = new ListNode(4);
  84. ListNode n5 = new ListNode(5);
  85. ListNode n6 = new ListNode(6);
  86. n1.next = n2;
  87. n2.next = n3;
  88. n3.next = n4;
  89. n4.next = n5;
  90. n5.next = n6;
  91. n6.next = n6;
  92. System.out.println(meetingNode(n1));
  93. }
  94. }

执行结果

【剑指Offer学习】【面试题56:链表中环的入口结点】的更多相关文章

  1. 【剑指offer】面试题 23. 链表中环的入口节点

    面试题 23. 链表中环的入口节点

  2. 剑指offer五十五之链表中环的入口结点

    一.题目 一个链表中包含环,请找出该链表的环的入口结点. 二.思路 方法一: 假设x为环前面的路程(黑色路程),a为环入口到相遇点的路程(蓝色路程,假设顺时针走), c为环的长度(蓝色+橙色路程). ...

  3. 剑指Offer(书):链表中环的入口节点

    题目:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null. public ListNode EntryNodeOfLoop(ListNode pHead) { //第一步,查找是 ...

  4. (剑指Offer)面试题56:链表中环的入口结点

    题目: 一个链表中包含环,请找出该链表的环的入口结点. 思路: 1.哈希表 遍历整个链表,并将链表结点存入哈希表中(这里我们使用容器set),如果遍历到某个链表结点已经在set中,那么该点即为环的入口 ...

  5. 【剑指offer】面试题 22. 链表中倒数第 K 个节点

    面试题 22. 链表中倒数第 K 个节点

  6. 【剑指offer】面试题 8. 二叉树的下一个结点

    面试题 8. 二叉树的下一个结点 NowCoder 题目描述 给定一棵二叉树和其中的一个结点,如何找出中序遍历顺序的下一个结点?树中的结点除了有两个分别指向左右子结点的指针以外,还有一个指向父结点的指 ...

  7. 【剑指Offer】面试题22. 链表中倒数第k个节点

    题目 输入一个链表,输出该链表中倒数第k个节点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点.例如,一个链表有6个节点,从头节点开始,它们的值依次是1.2.3.4.5.6. ...

  8. 《剑指offer》面试题22. 链表中倒数第k个节点

    问题描述 输入一个链表,输出该链表中倒数第k个节点.为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点.例如,一个链表有6个节点,从头节点开始,它们的值依次是1.2.3.4.5. ...

  9. 《剑指offer》面试题15 链表中的倒数第k个节点 Java版

    书中方法:用两个节点一次遍历求得倒数第k个节点.注意头节点为空,k<=0,k大于节点个数的情况. public ListNode find(ListNode head, int k){ if(h ...

  10. 《剑指offer》面试题56 - I. 数组中数字出现的次数

    问题描述 一个整型数组 nums 里除两个数字之外,其他数字都出现了两次.请写程序找出这两个只出现一次的数字.要求时间复杂度是O(n),空间复杂度是O(1). 示例 1: 输入:nums = [4,1 ...

随机推荐

  1. Windows Native API

    http://en.wikipedia.org/wiki/Native_API Windows 的原生 API 函数通常在系统启动时(这里其他 Windows 组件还不可用).kernel32.dll ...

  2. win7下如何执行批处理文件

    经过了一段时间的适应之后,某C也基本摸透了Win7的习性,然后突然发现无聊,就上了VeryCD去下载几个游戏玩.R大是电驴游戏版块的大神,某C怀着崇敬的心情,每每都追寻着他的足迹下载游戏.这次正好下载 ...

  3. stax解析XML-----Demo

    Demo public void staxDemo() throws Exception { XMLStreamReader xml= XMLInputFactory.newInstance().cr ...

  4. crtmpserver组网方案

    A Powerful Live Streaming Setup 搭建强大的直播系统 Recently we had a project requiring live streaming setup, ...

  5. epoll 中EPOLLIN 和 EPOLLOUT

    epoll主要是事件回调运行的,我们使用socket的时候主要使用两个事件 EPOLLOUT事件:EPOLLOUT事件只有在连接时触发一次,表示可写,其他时候想要触发,那你要先准备好下面条件:1.某次 ...

  6. mysql 整形的长度问题

    tinyint  有符号的范围是-128至127: 无符号的范围是0到255,2的8 次方-1: 存储大小为 1 字节. smallint  有符号的范围是-32768至32767: 无符号的范围是0 ...

  7. php单词里的大写字母

    $flag = preg_match("/[A-Z]/","abcDddd",$matches,PREG_OFFSET_CAPTURE);if($flag){ ...

  8. php cgi 与 cli 区别

    以CGI方式运行时,web server将用户请求以消息的方式转交给PHP独立进程,PHP与web服务之间无从属关系:CLI则是命令行接口,用于在操作系统命令行模式下执行PHP,比如可以直接在win的 ...

  9. NET MVC+EF6+Bootstrap

    开源:ASP.NET MVC+EF6+Bootstrap开发框架   前言 我在博客园潜水两三年了,在这里看过很多大神的文章,也学到了很多东西.可以说我是汲取着博客园的营养成长的. 想当年,我也是拿1 ...

  10. UIApplication-备用

    iPhone应用程序是由主函数main启动,它负责调用UIApplicationMain函数,该函数的形式如下所示: int UIApplicationMain ( int argc, char *a ...