第二阶段-day03_Linked

今天我们主要讲了一些链表的练习题,希望大家可以从中体会链表的使用方式,加深对链表的理解。

回顾昨天内容:

总结:
List
    List subList(int fromIndex, int toIndex) 视图技术
    ListIterator listIterator()
    ListIterator listIterator(int index)

ListIterator
    概述:列表特有的迭代器
    API:
        boolean hasNext()
        boolean hasPrevious()
        E next()
        E previous()
        
        int previousIndex()
        int nextIndex()
        
        void add(E e)
        void remove()
        void set(E e)

数组
    Q1
    Q2
    Q3
    数组的基本操作 总结:增删慢,查找快

链表
    概述:
    分类:
        单链表
        双向链表
        循环链表
        双向循环链表
    单链表的操作
    双向链表的操作
    
    例子:
        a. LRU算法
        b. 求单表的中间元素
        c. 判断单链表是否有环

3个练习:

 1 package com.cskaoyan.exercise;
 2 
 3 public class Node {
 4     int value;
 5     Node next;
 6 
 7     public Node(int value) {
 8         this.value = value;
 9     }
10 
11     public Node(int value, Node next) {
12         this.value = value;
13         this.next = next;
14     }
15 
16     @Override
17     public String toString() {
18         return "Node{" +
19                 "value=" + value +
20                 '}';
21     }
22 }

Ex2:

方法1. 给一个阈值(10ms),如果在遍历链表的过程中10ms还没有结束,就认为有环。
   2. 迷雾森林

 1 package com.cskaoyan.exercise;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Collection;
 5 import java.util.HashSet;
 6 
 7 /*
 8 判断链表中是否有环
 9 1. 给一个阈值(10ms),如果在遍历链表的过程中10ms还没有结束,就认为有环。
10 2. 迷雾森林
11    Collection visited = new ArrayList();
12    a.遍历链表,获取每一个结点。
13      判断结点是否在visited集合中存在。
14      存在:返回true
15      不存在:将该结点添加到visited中,然后遍历下一个结点
16    b.遍历结束后,返回false
17 3. 跑道(快慢指针)
18     a.创建了快指针和慢指针,快指针每次走两步,慢指针每次走一步
19     b.遍历链表
20       如果快指针到到终点:返回false
21       如果快指针和慢指针相遇:返回true
22       快指针移动两步
23       慢指针移动一步
24  */
25 public class Ex1 {
26     /*
27     时间复杂度:O(n^2) --> O(n)
28     空间复杂度:O(n)
29      */
30     /*public static boolean hasCircle(Node head) {
31         // Collection visited = new ArrayList();
32         Collection visited = new HashSet();
33         Node x = head;
34         while (x != null) {
35             if (visited.contains(x)) return true;
36             visited.add(x);
37             x = x.next;
38         }
39         // 遍历结束
40         return false;
41     }*/
42 
43     /*
44     时间复杂度:
45         最好情况:O(a)
46         最坏情况:O(a+r)
47         平均情况:O(a+r/2)
48     空间复杂度:O(1)
49      */
50     public static boolean hasCircle(Node head) {
51         // 创建快慢指针
52         Node fast = head;
53         Node slow = head;
54         // 遍历链表
55         do {
56             // 快指针是否到达终点
57             if (fast == null || fast.next == null) return false;
58             fast = fast.next.next;
59             slow = slow.next;
60         } while (fast != slow);
61         // fast == slow
62         return true;
63     }
64 
65     public static void main(String[] args) {
66         // 1 --> 2 --> 3 --> 4
67         /*Node head = new Node(4);
68         head = new Node(3, head);
69         head = new Node(2, head);
70         head = new Node(1, head);
71         System.out.println(hasCircle(head));*/
72 
73         // 1 --> 2 --> 3 --> 4 --> 2 --> ...
74         /*Node node = new Node(4);
75         Node head = new Node(3, node);
76         head = new Node(2, head);
77         node.next = head;
78         head = new Node(1, head);
79         System.out.println(hasCircle(head));*/
80 
81         // 1 --> 2 --> 3 --> 4 --> 4 --> ...
82         Node node = new Node(4);
83         node.next = node;
84         Node head = new Node(3, node);
85         head = new Node(2, head);
86         head = new Node(1, head);
87         System.out.println(hasCircle(head));
88     }
89 }

方法2. 跑道(快慢指针)

                                                          判断链表是否有环--快慢指针

 1 package com.cskaoyan.exercise;
 2 
 3 import java.util.Collection;
 4 import java.util.HashSet;
 5 
 6 /*
 7 如果有环:返回入环的第一个结点
 8 如果无环:返回null
 9 1. 迷雾森林
10    Collection visited = new ArrayList();
11    a.遍历链表,获取每一个结点。
12      判断结点是否在visited集合中存在。
13      存在:返回该节点
14      不存在:将该结点添加到visited中,然后遍历下一个结点
15    b.遍历结束后,返回null
16 2. 跑道(快慢指针)
17  */
18 public class Ex2 {
19     /*
20     时间复杂度:O(n)
21     空间复杂度:O(n)
22      */
23     /*public static Node hasCircle(Node head) {
24         Collection visited = new HashSet();
25         Node x = head;
26         while (x != null) {
27             if (visited.contains(x)) return x;
28             visited.add(x);
29             x = x.next;
30         }
31         return null;
32     }*/
33 
34     /*
35     时间复杂度:
36         最好情况:O(2a)
37         最坏情况:O(2a+r)
38         平均情况:O(2a+r/2)
39     空间复杂度:O(1)
40      */
41     public static Node hasCircle(Node head) {
42         Node fast = head;
43         Node slow = head;
44         do {
45             if (fast == null || fast.next == null) return null;
46             fast = fast.next.next;
47             slow = slow.next;
48         } while (fast != slow);
49         // fast == slow
50         // 将fast移动到开头
51         fast = head;
52         while (fast != slow) {
53             fast = fast.next;
54             slow = slow.next;
55         }
56         // fast == slow 再一次相遇
57         return fast;
58     }
59 
60     public static void main(String[] args) {
61         // 1 --> 2 --> 3 --> 4
62         Node head = new Node(4);
63         head = new Node(3, head);
64         head = new Node(2, head);
65         head = new Node(1, head);
66         System.out.println(hasCircle(head));
67 
68         // 1 --> 2 --> 3 --> 4 --> 2 --> ...
69         /*Node node = new Node(4);
70         Node head = new Node(3, node);
71         head = new Node(2, head);
72         node.next = head;
73         head = new Node(1, head);
74         System.out.println(hasCircle(head));*/
75 
76         // 1 --> 2 --> 3 --> 4 --> 4 --> ...
77         /*Node node = new Node(4);
78         node.next = node;
79         Node head = new Node(3, node);
80         head = new Node(2, head);
81         head = new Node(1, head);
82         System.out.println(hasCircle(head));*/
83     }
84 }

Ex3:反转单链表

方法1:头插法

 1 package com.cskaoyan.exercise;
 2 
 3 /*
 4 反转单链表
 5 举例:
 6     输入:1 --> 2 --> 3 --> null
 7     输出:3 --> 2 --> 1 --> null
 8 1.头插法
 9 2.递归
10  */
11 public class Ex3 {
12     public static Node reverse(Node head) {
13         Node prev = null;
14         Node curr = head;
15         while (curr != null) {
16             // 保留下一个结点
17             Node next = curr.next;
18             // 头插法
19             curr.next = prev;
20             prev = curr;
21             // curr移动到下一个结点
22             curr = next;
23         }
24         return prev;
25     }
26 
27     public static void print(Node head) {
28         Node x = head;
29         while (x != null) {
30             System.out.print(x.value);
31             if (x.next != null) System.out.print(" --> ");
32             x = x.next;
33         }
34         System.out.println();
35     }
36 
37     public static void main(String[] args) {
38         Node head = new Node(3);
39         head = new Node(2, head);
40         head = new Node(1, head);
41         print(head);
42         head = reverse(head);
43         print(head);
44     }
45 }

 方法二:递归

原文地址:https://www.cnblogs.com/dust2017/p/12892082.html