LeetCode链表专题(一)

链表简介:

  定义:链表是一种物理存储单元上非连续、非顺序的存储结构;

  组成:数据 + 指针(这个指针为指向下一个或者上一个链表节点),注意:各个节点的位置不是排好的,他们可能相隔甚远,但是有指针牵引着,不会失联;

  优点:擅长插入和删除某个节点;

    

  :图片来自于《我的第一本算法书》,很适合纯小白作入门书籍;

  

  单链表简单实现--java

  1 import org.junit.jupiter.api.Test;
  2 
  3 /**
  4  * @ClassName SingleLinkedList
  5  * @Description 单链表的简单实现
  6  * @Author peanut
  7  * @DATE 2020/5/13 13:45
  8  * @Version 1.0
  9  */
 10 public class SingleLinkedList {
 11     /**
 12      * 链表节点个数,头节点
 13      */
 14     private int size;
 15     private Node head;
 16 
 17     public SingleLinkedList() {
 18         size = 0;
 19         head = null;
 20     }
 21 
 22     /**
 23      * 创建节点类
 24      */
 25     private class Node {
 26         private Object data;
 27         private Node next;
 28 
 29         public Node(Object data) {
 30             this.data = data;
 31         }
 32     }
 33 
 34     /**
 35      * 在链表头添加元素
 36      */
 37     public Object addHead(Object obj) {
 38         Node newHead = new Node(obj);
 39         if (size == 0) {
 40             head = newHead;
 41         } else {
 42             newHead.next = head;
 43             head = newHead;
 44         }
 45         size++;
 46         return obj;
 47     }
 48 
 49     /**
 50      * 在链表头删除元素
 51      */
 52     public Object deleteHead() {
 53         Object obj = head.data;
 54         head = head.next;
 55         size--;
 56         return obj;
 57     }
 58 
 59     /**
 60      * 查找指定元素,找到了返回节点Node,找不到返回null
 61      */
 62     public Node find(Object obj) {
 63         Node current = head;
 64         int tempSize = size;
 65         while (tempSize > 0) {
 66             if (obj.equals(current.data)) {
 67                 return current;
 68             } else {
 69                 current = current.next;
 70             }
 71             tempSize--;
 72         }
 73         return null;
 74     }
 75 
 76 
 77     /**
 78      * 删除指定的元素,删除成功返回true
 79      */
 80     public boolean delete (Object value) {
 81         if (size == 0) {
 82             return false;
 83         }
 84         Node current = head;
 85         Node previous = head;
 86         while (current.data != value) {
 87             if (current.next == null) {
 88                 return false;
 89             } else {
 90                 previous = current;
 91                 current = current.next;
 92             }
 93         }
 94         //如果删除的节点是第一个节点
 95         if (current == head) {
 96             head = current.next;
 97             size--;
 98         } else {
 99             previous.next = current.next;
100             size--;
101         }
102         return true;
103     }
104 
105     public boolean isEmpty() {
106         return (size == 0);
107     }
108 
109     public void display() {
110         if (size > 0) {
111             Node node = head;
112             int tempSize = size;
113             if (tempSize == 1) {
114                 System.out.println("["+node.data+"]");
115                 return;
116             }
117             while (tempSize > 0) {
118                 if (node.equals(head)) {
119                     System.out.print("["+node.data+"->");
120                 } else if (node.next == null) {
121                     System.out.print(node.data+"]");
122                 } else {
123                     System.out.print(node.data+"->");
124                 }
125                 node = node.next;
126                 tempSize--;
127             }
128 
129             System.out.println();
130         } else {
131             System.out.println("[]");
132         }
133     }
134 
135     @Test
136     public void testSingleLinkedList() {
137         SingleLinkedList singleLinkedList = new SingleLinkedList();
138         singleLinkedList.addHead("A");
139 
140 
141         singleLinkedList.display();
142         singleLinkedList.delete("A");
143         singleLinkedList.display();
144 
145         singleLinkedList.addHead("B");
146         System.out.println(singleLinkedList.find("B"));
147     }
148 }
View Code

  双端链表简单实现--java,注意区分双端链表和双向链表

  1 import org.junit.jupiter.api.Test;
  2 
  3 /**
  4  * @ClassName SingleLinkedList
  5  * @Description 单链表的简单实现
  6  * @Author peanut
  7  * @DATE 2020/5/13 13:45
  8  * @Version 1.0
  9  */
 10 public class DoublePointLinkedList {
 11     /**
 12      * 链表节点个数,头节点
 13      */
 14     private int size;
 15     private Node head;
 16     private Node tail;
 17 
 18     public DoublePointLinkedList() {
 19         size = 0;
 20         head = null;
 21         tail = null;
 22     }
 23 
 24     /**
 25      * 创建节点类
 26      */
 27     private class Node {
 28         private Object data;
 29         private Node next;
 30 
 31         public Node(Object data) {
 32             this.data = data;
 33         }
 34     }
 35 
 36     /**
 37      * 在链表头添加元素
 38      */
 39     public void addHead(Object data) {
 40         Node node = new Node(data);
 41         if (size == 0) {
 42             head = node;
 43             tail = node;
 44             size++;
 45         } else {
 46             node.next = head;
 47             head = node;
 48             size++;
 49         }
 50     }
 51 
 52     /**
 53      * 在链表尾添加元素
 54      */
 55     public void addTail(Object data) {
 56         Node node = new Node(data);
 57         if (size == 0) {
 58             head = node;
 59             tail = node;
 60             size++;
 61         } else {
 62             tail.next = node;
 63             tail = node;
 64             size++;
 65         }
 66     }
 67 
 68 
 69     /**
 70      * 在链表头删除元素
 71      */
 72     public boolean deleteHead() {
 73         if (size == 0) {
 74             return false;
 75         }
 76         if (head.next == null) {
 77             head = null;
 78             tail = null;
 79         } else {
 80             head = head.next;
 81         }
 82         size--;
 83         return true;
 84     }
 85 
 86     public boolean isEmpty() {
 87         return (size == 0);
 88     }
 89 
 90     public int getSize() {
 91         return size;
 92     }
 93 
 94     /**
 95      * 查找指定元素,找到了返回节点Node,找不到返回null
 96      */
 97     public Node find(Object obj) {
 98         Node current = head;
 99         int tempSize = size;
100         while (tempSize > 0) {
101             if (obj.equals(current.data)) {
102                 return current;
103             } else {
104                 current = current.next;
105             }
106             tempSize--;
107         }
108         return null;
109     }
110 
111 
112     /**
113      * 删除指定的元素,删除成功返回true
114      */
115     public boolean delete (Object value) {
116         if (size == 0) {
117             return false;
118         }
119         Node current = head;
120         Node previous = head;
121         while (current.data != value) {
122             if (current.next == null) {
123                 return false;
124             } else {
125                 previous = current;
126                 current = current.next;
127             }
128         }
129         //如果删除的节点是第一个节点
130         if (current == head) {
131             head = current.next;
132             size--;
133         } else {
134             previous.next = current.next;
135             size--;
136         }
137         return true;
138     }
139 
140 
141     public void display() {
142         if (size > 0) {
143             Node node = head;
144             int tempSize = size;
145             if (tempSize == 1) {
146                 System.out.println("["+node.data+"]");
147                 return;
148             }
149             while (tempSize > 0) {
150                 if (node.equals(head)) {
151                     System.out.print("["+node.data+"->");
152                 } else if (node.next == null) {
153                     System.out.print(node.data+"]");
154                 } else {
155                     System.out.print(node.data+"->");
156                 }
157                 node = node.next;
158                 tempSize--;
159             }
160 
161             System.out.println();
162         } else {
163             System.out.println("[]");
164         }
165     }
166 
167     @Test
168     public void testDoublePointLinkedList() {
169         DoublePointLinkedList doublePointLinkedList = new DoublePointLinkedList();
170         doublePointLinkedList.addHead("A");
171 
172 
173     }
174 }
View Code

  有序链表简单实现--java 

 1 /**
 2  * @ClassName OrderLinkedList
 3  * @Description TODO
 4  * @Author peanut
 5  * @DATE 2020/5/13 15:00
 6  * @Version 1.0
 7  */
 8 public class OrderLinkedList {
 9     private Node head;
10 
11     private class Node {
12         private int data;
13         private Node next;
14 
15         public Node(int data) {
16             this.data = data;
17         }
18     }
19 
20     public OrderLinkedList() {
21         head = null;
22     }
23 
24     public void insert(int value) {
25         Node node = new Node(value);
26         Node pre = null;
27         Node current = head;
28         while (current != null && value > current.data) {
29             pre = current;
30             current = current.next;
31         }
32         if (pre == null) {
33             head = node;
34             head.next = current;
35         } else {
36             pre.next = node;
37             node.next = current;
38         }
39     }
40 
41     public void deleteHead() {
42         head = head.next;
43     }
44 
45     public void display() {
46         Node current = head;
47         while (current != null) {
48             System.out.print(current.data + " ");
49             current = current.next;
50         }
51         System.out.println("");
52     }
53 }
View Code

  双向链表简单实现--java

 1 /**
 2  * @ClassName TwoWayLinkedList
 3  * @Description TODO
 4  * @Author peanut
 5  * @DATE 2020/5/13 15:22
 6  * @Version 1.0
 7  */
 8 public class TwoWayLinkedList {
 9     /**
10      * 链表节点个数,头节点
11      */
12     private int size;
13     private Node head;
14     private Node tail;
15 
16     private class Node {
17         private Object data;
18         private Node next;
19         private Node prev;
20 
21         public Node(Object data) {
22             this.data = data;
23         }
24     }
25 
26     public TwoWayLinkedList() {
27         size = 0;
28         head = null;
29         tail = null;
30     }
31 
32     public void addHead(Object value) {
33         Node newNode = new Node(value);
34         if (size == 0) {
35             head = newNode;
36             tail = newNode;
37             size++;
38         } else {
39             head.prev = newNode;
40             newNode.next = head;
41             head = newNode;
42             size++;
43         }
44     }
45 
46     public Node deleteHead() {
47         Node temp = head;
48         if (size != 0) {
49             head = head.next;
50             head.prev = null;
51             size--;
52         }
53         return temp;
54     }
55 
56     public Node deleteTail() {
57         Node temp = tail;
58         if (size != 0) {
59             tail = tail.prev;
60             tail.next = null;
61             size--;
62         }
63         return temp;
64     }
65     public int getSize() {
66         return size;
67     }
68 
69     public boolean isEmpty() {
70         return (size == 0);
71     }
72 
73     public void display() {
74         if (size > 0) {
75             Node node = head;
76             int tempSize = size;
77             if (tempSize == 1) {
78                 System.out.println("[" + node.data + "]");
79                 return;
80             }
81             while (tempSize > 0) {
82                 if (node.equals(head)) {
83                     System.out.print("[" + node.data + "->");
84                 } else if (node.next == null){
85                     System.out.print(node.data+"->");
86                 } else {
87                     System.out.println( node.data + "]");
88                 }
89                 node = node.next;
90                 tempSize--;
91             }
92             System.out.println();
93         } else {
94             System.out.println("[]");
95         }
96     }
97 }
View Code

================================================================================================

2. Add Two Numbers     难度:Medium

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode() {}
 7  *     ListNode(int val) { this.val = val; }
 8  *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 9  * }
10  */
11 
12 /**
13  * 1.首先用两个链表存储2个数, 243,564
14  * 2.首先循环第一个链表,先取出最低位,保留至val,然后进入第二个链表,取出最低为,与
15  *     val 相加,结果保留至val;
16  * 3. 然后验证val是否大于10,若大于10,则进位,进位结果保留至ex,留着下一次循环加在  val上,此次结果保留至节点node
17  * 4. 往复循环,直至两个链表的数都循环完了
18  * 5. 不要忘记最后的进位也要加上;
19  */
20 class Solution {
21     public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
22         int ex = 0;
23         ListNode head = null, tail = null;
24         while (l1 != null || l2 != null) { // 保证两个链表不同时为空
25             // 如果上一次结果大于10,则将进位数加载这一次,循环如此
26             int val = ex;
27             if (l1 != null) {
28                 val += l1.val;
29                 l1 = l1.next;
30             }
31             
32             if (l2 != null) {
33                 val += l2.val;
34                 l2 = l2.next;
35             }
36             ex = val / 10;
37             ListNode node = new ListNode(val % 10);
38             if (head == null) {  // 此时为空链表,给头节点和为节点赋值
39                 head = node;
40                 tail = node;
41             } else {
42                 tail.next = node;
43                 // 链表后移
44                 tail = tail.next;
45             }
46         }
47         if (ex > 0) {
48             tail.next = new ListNode(ex);
49         }
50         return head;
51     }
52 }
View Code

 ====================================================================================

19. Remove Nth Node From End of List   难度Medium

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode() {}
 7  *     ListNode(int val) { this.val = val; }
 8  *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 9  * }
10  */
11 
12 /**
13  * 定义连个指针,一个快指针,一个慢指针,快指针先走n步,然后和慢指针一起走到链表尾部,
14  * 此时慢指针.next 是正在要删除节点位置,将慢指针.next 指向 慢指针.next.next
15  * 然后返回head
16  * 此题依旧是单链表的应用
17  */
18 class Solution {
19     public ListNode removeNthFromEnd(ListNode head, int n) {
20         ListNode dummy = new ListNode(0);
21         dummy.next = head;
22         ListNode fast = dummy;
23         ListNode low = dummy;
24         
25         for (int i = 1; i <= n + 1; i++) {
26             fast = fast.next;
27         }
28         
29         
30         while (fast != null) {
31             fast = fast.next;
32             low = low.next;
33         }
34         low.next = low.next.next;
35         return dummy.next;
36     }
37 }
View Code

======================================================================================

21. Merge Two Sorted Lists    难度Easy

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode() {}
 7  *     ListNode(int val) { this.val = val; }
 8  *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 9  * }
10  */
11 /**
12  * 先检验 l1, l2 是否有空链表,若有,然后直接返回不空的
13  * 创建一个新链表
14  * 比较两个链表节点值大小,将小的先接入之前创建的链表,
15  * 当其中某个链表被循环到头了,则直接将较长链表的剩余部分直接接入之前创建的链表
16  */
17 
18 class Solution {
19     public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
20         if (l1 == null || l2 == null) {
21             return (l1  != null ? l1 : l2);
22         }
23         
24         ListNode dummy = new ListNode(0);
25         ListNode cur = dummy;
26         while (l1 != null && l2 != null) {
27             if (l1.val < l2.val) {
28                 cur.next = l1;
29                 l1 = l1.next;
30             } else {
31                 cur.next = l2;
32                 l2 = l2.next;
33             }
34             cur = cur.next;
35         }
36         cur.next = l1 != null ? l1 : l2;
37         return dummy.next;
38     }
39 }
View Code

=========================================================================================

 23. Merge k Sorted Lists    难度:Hard

 

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode() {}
 7  *     ListNode(int val) { this.val = val; }
 8  *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 9  * }
10  */
11 class Solution {
12     public ListNode mergeKLists(ListNode[] lists) {
13         if (lists == null || lists.length == 0) {
14             return null;
15         }
16         /**
17          * 因为是ListNode,所以需要自定义比较函数,我们需要将小的值放在前面,下面为lambda表达式
18          * (a,b) -> a.val-b.val表示如果a.val > b.val时,正好会反过来;
19          * public ListNode compare(ListNode a, ListNode b) {
20          *       return a.val - b.val; // 重载优先级使其变为小根堆
21          *   }
22          *  这是容易看懂的方式
23          * public PriorityQueue(int initialCapacity,Comparator<? super E> comparator) {这是源码的函数声明}
24          */
25         PriorityQueue<ListNode> priorityQueue = new PriorityQueue<ListNode>(lists.length ,(a,b) -> a.val-b.val);
26         
27         for (ListNode node : lists) { // 将每个链表头节点放到priorityQueue
28             if (node != null) {
29                 priorityQueue.offer(node);
30             }
31         }
32         ListNode head = new ListNode(0);
33         ListNode tail = head;
34         
35         
36         /**
37          * 记得上面将几个链表的头节点放到 pq中,比较完一轮,poll出一个最小的
38          * 然后将poll的节点的下一个节点放到pq中(如果存在的话);就这样一点点比较完所有链表的所有节点
39          */
40         while (!priorityQueue.isEmpty()) {
41             tail.next = priorityQueue.poll();
42             tail = tail.next;
43             if (tail.next != null) {
44                 priorityQueue.offer(tail.next);
45             }
46         }
47         return head.next;
48     }
49 }
View Code

 =========================================================================================

24. Swap Nodes in Pairs    难度:Medium

 1 /**
 2  * Definition for singly-linked list.
 3  * public class ListNode {
 4  *     int val;
 5  *     ListNode next;
 6  *     ListNode() {}
 7  *     ListNode(int val) { this.val = val; }
 8  *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 9  * }
10  */
11 
12 class Solution {
13     public ListNode swapPairs(ListNode head) {
14         // // 在链表上创建临时节点,用于移动,应为原头节节点位置不能动
15         // ListNode dummy = head;
16         // while (itr != null) {
17         //     // 交换相邻节点的值
18         //     int temp = dummy.val;
19         //     dummy.val = dummy.next.val;
20         //     dummy.next.val = temp;
21         //     dummy = dummy.next.next;
22         // }
23         // return head;
24         // 这种方法虽然可以通过测试,但是违背了题目原则
25         // ===========================================================================================================
26         // 下面这种方法是创建一个新链表,将交换过的节点放到新链表中
27         if( head == null || head.next == null)
28             return head;
29         ListNode firstNode = null;
30         ListNode firstNodeLast = null;
31         while( head != null && head.next != null)  {
32             ListNode temp = head;
33             head = head.next;
34             temp.next = head.next;
35             head.next = temp;
36             if( firstNode == null) {
37                 firstNode = head;
38                 firstNodeLast = firstNode.next;
39             } else {
40                 firstNodeLast.next = head;
41                 firstNodeLast = firstNodeLast.next.next;
42             }
43             head = head.next.next;
44         }
45         return firstNode;
46         
47     }
48 }
View Code

 

posted @ 2020-05-14 21:21  巧克力可不是用来添的  阅读(181)  评论(0)    收藏  举报