有一个单向链表,链表中有可能出现“环”,如何用程序判断该链表是否为环链表?
如果是环链表,如果链表有环,计算环的长度以及入环节点。
假设本次环链表如下:
5->3->7->2->6
| |
1<-8
思路:
1. 如何用程序判断该链表是否为环链表?
创建两个指针p1,p2(节点对象)指向链表头节点,然后p1每次向后移动1个节点,p2每次移动2个节点,然后比较p1和p2是否相同。如果相同,则链表是环链表。
2.如何计算环的长度以及入环节点?
- 创建一个map对象,先将head节点(data值)加入到map中;
- 然后将每个节点的next节点(data值)添加到一个map对象中;
- 每次往map中添加节点时,先判断map的key是否已经存在这个节点的next节点:
- 不存在,则加入:map的key=节点的data,map的value为一个自增的int值(可以认为是节点在map中的位置索引值);
- 存在,则找到了入环位置了: 入环节点=当前节点的next节点,环长度=(当前节点的索引值-next节点的索引值+1)。
代码实现如下:
1 public class IsCycleList { 2 /** 3 * 构建节点 4 */ 5 private static class Node{ 6 int data; 7 Node next; 8 Node (int data){ 9 this.data = data; 10 } 11 } 12 13 /** 14 * p1每次向后移动1个节点,p2向后移动2个节点 15 * @param head 16 * @return 17 */ 18 public static boolean isCycle(Node head){ 19 Node p1 = head; 20 Node p2 = head; 21 while (p2 != null && p2.next != null){ 22 p1 = p1.next; 23 System.out.print("p1: " + p1.data +", "); 24 p2 = p2.next.next; 25 System.out.println("p2: " + p2.data); 26 if (p1 == p2){ 27 return true; 28 } 29 } 30 return false; 31 } 32 33 /** 34 * 如果链表有环,计算环的长度以及入环节点 35 * @param head 36 * @return 37 */ 38 public static Map<String,Object> cycleLength(Node head){ 39 Map<String,Object> resultMap = new HashMap<>(); 40 Node p = head; 41 Map<Integer,Integer> indexMap = new HashMap(); 42 int i = 0; 43 indexMap.put(p.data,i++); 44 while(p.next != null){ 45 if (indexMap.get(p.data) != null && indexMap.get(p.next.data) != null){ 46 int end = indexMap.get(p.data); 47 int begin = indexMap.get(p.next.data); 48 resultMap.put("length",end-begin + 1); 49 resultMap.put("enterNode",p.next.data); 50 return resultMap; 51 } 52 p = p.next; 53 indexMap.put(p.data,i++); 54 } 55 return resultMap; 56 } 57 58 public static void main (String[] args){ 59 Node node1 = new Node(5); 60 Node node2 = new Node(3); 61 Node node3 = new Node(7); 62 Node node4 = new Node(2); 63 Node node5 = new Node(6); 64 Node node6 = new Node(8); 65 Node node7 = new Node(1); 66 node1.next = node2; 67 node2.next = node3; 68 node3.next = node4; 69 node4.next = node5; 70 node5.next = node6; 71 node6.next = node7; 72 node7.next = node4; //环
73 boolean result = isCycle(node1);
74 System.out.println("========"); 75 System.out.println("Is Cycle: " + result);
76 if(result){ 77 Map<String,Object> resultMap = cycleLength(node1); 78 System.out.println("Cycle Length is: " + resultMap.get("length")); 79 System.out.println("Cycle Enter Node is: " + resultMap.get("enterNode")); 80 } 81 } 82 83 }
结果:
p1: 3, p2: 7 p1: 7, p2: 6 p1: 2, p2: 1 p1: 6, p2: 6 ======== Is Cycle: true Cycle Length is: 4 Cycle Enter Node is: 2