(Java代码实现)单链表有环的一系列问题
2017-07-12 12:32
375 查看
本文主要用Java实现关于单链表有环的5个问题:
解决每个问题的方法:
具体详细的数学推导参见
http://blog.csdn.net/doufei_ccst/article/details/10578315
Java 代码实现如下:
run结果:
本文结束,谢谢浏览!
1. 判断一个单链表是否存在环? 2. 若存在环,找到环的入口位置? 3. 进一步,计算换上的节点数? 4. 进一步,计算环外的长度、链表的长度? 5. 环上对面的结点如何求?
解决每个问题的方法:
1. 利用快、慢指针从表头开始往后next,慢指针去追击快指针,若遍历完返回null,就没有环;若慢指针追上快指针相遇,就有环。 2. 经过数学推导,有这么个规律:从相遇点位置和从表头位置同时往后next,会在环的入口处相遇。 3. 基于以上,可以有2种方法: (1)从环的入口处开始,在环上转一圈,计数。 (2)从相遇点位置同时开始,快慢指针继续转,直到下次二者相遇,二者走过步数差值(或者慢指针走过的步数)就是环的长度。当然,上面的理论是建立在 快指针一次走2步,慢指针一次走一步。 4. 基于以上,知道了入口的位置,从表头开始往入口走,计数。链表长度=环外长度+环长度。 5. 基于这个规律:在环内,快慢指针同时出发,快指针回到原点,慢指针走到距离原点最远处。
具体详细的数学推导参见
http://blog.csdn.net/doufei_ccst/article/details/10578315
Java 代码实现如下:
public class ListNode { int val; ListNode next; public ListNode(int val) { this.val = val; } public ListNode(int val, ListNode next) { this.val = val; this.next = next; } public int getVal() { return val; } public void setVal(int val) { this.val = val; } public ListNode getNext() { return next; } public void setNext(ListNode next) { this.next = next; } @Override public String toString() { return "ListNode{" + "val=" + val + '}'; } } ---------- public class BooleanCircular { private static ListNode pos; private static ListNode joint; public static void main(String[] args) { ListNode listNode1 = new ListNode(1); ListNode listNode2 = new ListNode(2); ListNode listNode3 = new ListNode(3); ListNode listNode4 = new ListNode(4); ListNode listNode5 = new ListNode(5); ListNode listNode6 = new ListNode(6); ListNode listNode7 = new ListNode(7); ListNode listNode8 = new ListNode(8); ListNode listNode9 = new ListNode(9); listNode1.setNext(listNode2); listNode2.setNext(listNode3); listNode3.setNext(listNode4); listNode4.setNext(listNode5); listNode5.setNext(listNode6); listNode6.setNext(listNode7); listNode7.setNext(listNode8); listNode8.setNext(listNode9); listNode9.setNext(listNode4); System.out.println(hasCycle(listNode1)); System.out.println(FindJoint(listNode1)); System.out.println(CircluarCount2(listNode1)); calculateLength(listNode1); System.out.println(oppositeListNode(listNode4)); } //判断单链表是否有环 public static boolean hasCycle(ListNode head) { ListNode fast = head; ListNode slow = head; while (slow != null && fast.next != null) { fast = fast.next.next; slow = slow.next; if (slow == fast) { return true; } } return false; } //找到环的入口 public static ListNode FindJoint(ListNode head) { ListNode fast = head; ListNode slow = head; while (slow != null && fast.next != null) { fast = fast.next.next; slow = slow.next; if (slow == fast) { break; } } if (slow == null || fast.next == null) { System.out.println("没有环"); return null; } //记录相遇位置 pos = slow; ListNode node = slow; ListNode start = head; while (node != start) { node = node.next; start = start.next; } //记录环入口位置 joint = start; return start; } //计算环上的节点数,两种方法 public static int CircluarCount1(ListNode head) { int count = 1; //joint是入口位置 ListNode node = joint.next; while (node != joint) { node = node.next; count++; } return count; } public static int CircluarCount2(ListNode head) { int count = 1; //pos是相遇位置 ListNode fast = pos.next.next; ListNode slow = pos.next; while (fast != slow) { fast = fast.next.next; slow = slow.next; count++; } return count; } //计算头结点到环入口的长度、链表的长度 public static void calculateLength(ListNode head) { int count = 0; //joint是入口位置 for (ListNode node = head; node != joint; node = node.next, count++) ; System.out.println("头结点到入口的长度:" + count); int listCount = count+CircluarCount1(head); System.out.println("链表的长度:" + lis a5bf tCount); } //求环上对面的结点,这里以 listNode4 对面结点 listNode7 来验证 public static ListNode oppositeListNode(ListNode listNode){ ListNode slow = listNode; ListNode fast = listNode; do{ slow=slow.next; fast=fast.next.next; }while(fast!=listNode); return slow; } }
run结果:
true ListNode{val=4} 6 头结点到入口的长度:3 链表的长度:9 ListNode{val=7}
本文结束,谢谢浏览!
相关文章推荐
- 约瑟夫问题java语言实现代码
- 自己用java代码实现的:“约瑟夫”问题
- Java底层代码实现单文件读取和写入(解决中文乱码问题)
- java单链表代码实现
- java 实现新浪微博内容计数器 Java问题通用解决代码
- 利用链表实现队列的Java代码
- 【Java基础】“数三退一”问题的代码实现
- 着色问题的代码实现(java版)使用回溯法和贪心思想
- 分治算法---棋盘覆盖问题java代码实现
- java单链表代码实现
- 约瑟夫环问题(丢手帕游戏)Java 链表实现
- 关于亮灯,1,2,3倍数开灯和灭灯问题的Java代码实现
- 链表问题之无头单链表删节点<Java实现>
- 瓶子质量问题的Java代码实现
- 环形链表实现约瑟夫问题 java语言
- java代码中实现字符编码转换(解决中文乱码问题)
- 人狼羊菜过河问题 (Java代码实现)
- 最长公共子序列问题-求所有公共子序列(java核心代码实现)
- Java除法结果带小数、进一法的实现 Java问题通用解决代码
- 单链表是否有环的问题解决与讨论(java实现)