parent
							
								
									72f66183fe
								
							
						
					
					
						commit
						e8f43870ae
					
				| @ -0,0 +1,206 @@ | ||||
| --- | ||||
| 链表 | ||||
| --- | ||||
| 
 | ||||
| #### 目录 | ||||
| 
 | ||||
| 1. 链表分类 | ||||
|    - 单链表 | ||||
|    - 循环链表 | ||||
|    - 双向链表 | ||||
|    - 双向循环链表 | ||||
| 2. 常见链表算法题 | ||||
|    - 单链表反转 | ||||
|    - 链表中环的检测 | ||||
|    - 两个有序链表的合并 | ||||
|    - 删除链表倒数第 n 个结点 | ||||
|    - 求链表的中间结点 | ||||
| 3. 总结 | ||||
| 
 | ||||
| #### 链表分类 | ||||
| 
 | ||||
| ##### 单链表 | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| ##### 循环链表 | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| ##### 双向链表 | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| ##### 双向循环链表 | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| #### 常见链表算法题 | ||||
| 
 | ||||
| 1. 单链表的反转 | ||||
| 
 | ||||
|    ```java | ||||
|    public class LinkedListDemo { | ||||
|     | ||||
|        private static Node head; | ||||
|     | ||||
|        public static void main(String[] args) { | ||||
|            head = new Node(0); | ||||
|            head.next = new Node(1); | ||||
|            head.next.next = new Node(2); | ||||
|            head.next.next.next = new Node(3); | ||||
|     | ||||
|            reverseLinkedList(); | ||||
|     | ||||
|            while (head != null) { | ||||
|                System.out.println(head.value); | ||||
|                head = head.next; | ||||
|            } | ||||
|        } | ||||
|     | ||||
|        //单链表的反转 | ||||
|        private static void reverseLinkedList() { | ||||
|            if (head == null || head.next == null) { | ||||
|                return; | ||||
|            } | ||||
|            Node p1 = head; | ||||
|            Node p2 = head.next; | ||||
|            Node p3 = null; | ||||
|            while (p2 != null) { | ||||
|                p3 = p2.next; | ||||
|                p2.next = p1; | ||||
|                p1 = p2; | ||||
|                p2 = p3; | ||||
|            } | ||||
|            head.next = null; | ||||
|            head = p1; | ||||
|        } | ||||
|     | ||||
|        static class Node { | ||||
|            int value; | ||||
|            Node next; | ||||
|     | ||||
|            Node(int value) { | ||||
|                this.value = value; | ||||
|            } | ||||
|        } | ||||
|    } | ||||
|    ``` | ||||
| 
 | ||||
|    参考:[漫画:如何将一个链表“逆序”?](https://mp.weixin.qq.com/s/MR_qAbonFqGF_ljeWUC26w) | ||||
| 
 | ||||
| 2. 链表中环的检测 | ||||
| 
 | ||||
|    这道题有三种解法: | ||||
| 
 | ||||
|    ```java | ||||
|    public class LinkedListDemo { | ||||
|     | ||||
|        private static Node head; | ||||
|     | ||||
|        public static void main(String[] args) { | ||||
|            head = new Node(0); | ||||
|            head.next = new Node(1); | ||||
|            head.next.next = new Node(2); | ||||
|            head.next.next.next = new Node(3); | ||||
|            head.next.next.next.next = head.next; | ||||
|     | ||||
|            boolean isHasCycleBySet = hasCycleBySet(); | ||||
|            System.out.println(isHasCycleBySet); | ||||
|            boolean isHasCycleByRun = hasCycleByRun(); | ||||
|            System.out.println(isHasCycleByRun); | ||||
|            boolean isHasCycleByMagic = hasCycleByMagic(); | ||||
|            System.out.println(isHasCycleByMagic); | ||||
|        } | ||||
|     | ||||
|        //用 HashSet 判断 | ||||
|        private static boolean hasCycleBySet() { | ||||
|            if (head == null || head.next == null) { | ||||
|                return false; | ||||
|            } | ||||
|            Set<Node> set = new HashSet<>(); | ||||
|            while (head != null) { | ||||
|                if (set.contains(head)) { | ||||
|                    return true; | ||||
|                } else { | ||||
|                    set.add(head); | ||||
|                } | ||||
|                head = head.next; | ||||
|            } | ||||
|            return false; | ||||
|        } | ||||
|     | ||||
|        //快慢指针 | ||||
|        private static boolean hasCycleByRun() { | ||||
|            if (head == null || head.next == null) { | ||||
|                return false; | ||||
|            } | ||||
|            Node p1 = head; | ||||
|            Node p2 = head.next; | ||||
|            while (p1 != p2) { | ||||
|                if (p2 == null || p2.next == null) { | ||||
|                    return false; | ||||
|                } | ||||
|                p1 = p1.next; | ||||
|                p2 = p2.next.next; | ||||
|            } | ||||
|            return true; | ||||
|        } | ||||
|     | ||||
|        //魔法数解法 | ||||
|        private static boolean hasCycleByMagic() { | ||||
|            if (head == null || head.next == null) { | ||||
|                return false; | ||||
|            } | ||||
|            while (head != null) { | ||||
|                if (head.value == 2 << 30) { | ||||
|                    return true; | ||||
|                } else { | ||||
|                    head.value = 2 << 30; | ||||
|                } | ||||
|                head = head.next; | ||||
|            } | ||||
|            return false; | ||||
|        } | ||||
|     | ||||
|        static class Node { | ||||
|            int value; | ||||
|            Node next; | ||||
|     | ||||
|            Node(int value) { | ||||
|                this.value = value; | ||||
|            } | ||||
|        } | ||||
|    } | ||||
|    ``` | ||||
| 
 | ||||
| 3. 两个有序链表的合并 | ||||
| 
 | ||||
|    ```java | ||||
|     | ||||
|    ``` | ||||
| 
 | ||||
| 4. 删除链表倒数第 n 个结点 | ||||
| 
 | ||||
|    ```java | ||||
|     | ||||
|    ``` | ||||
| 
 | ||||
| 5. 求链表的中间结点 | ||||
| 
 | ||||
|    ```java | ||||
|     | ||||
|    ``` | ||||
| 
 | ||||
|     | ||||
| 
 | ||||
| #### 总结 | ||||
| 
 | ||||
| 面试中手写算法题最多的就是链表相关的,链表算法到底难不难?难?难得话一个题再写十遍还难不难?(气急败坏中... | ||||
| 
 | ||||
| 不过,链表中需要注意几个边界条件: | ||||
| 
 | ||||
| 1. 如果链表为空 | ||||
| 2. 如果链表只有一个结点时 | ||||
| 3. 如果链表只有两个结点时 | ||||
| 4. 代码逻辑在处理头结点和尾结点时 | ||||
| After Width: | Height: | Size: 141 KiB | 
| Before Width: | Height: | Size: 30 KiB | 
| After Width: | Height: | Size: 44 KiB | 
| After Width: | Height: | Size: 67 KiB | 
| After Width: | Height: | Size: 48 KiB | 
| After Width: | Height: | Size: 39 KiB | 
					Loading…
					
					
				
		Reference in new issue