概念
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。
创建链表
下面的代码实现了基本的单向链表:
public class ListNode {
ListNode next = null;
int val;
public ListNode(int val) {
this.val = val;
}
void appendToTail(int d) {
ListNode end = new ListNode(d);
ListNode n = this;
while(n.next != null) {
n = n.next;
}
n.next = end;
}
}
反转链表
public ListNode ReverseList(ListNode head) {
if(head == null) {
return head;
}
ListNode pre = null, next = null;
while(head != null) {
next = head.next;
head.next = pre;
pre = head;
head = next;
}
return pre;
}
删除节点
(1)删除值为d的节点:
public ListNode deleteNode(ListNode head, int d) {
ListNode fade = head;
if(fade.val == d) {
return head.next;
}
while(fade.next != null) {
if(fade.next.val == d) {
fade.next = fade.next.next;
return head;
}
fade = fade.next;
}
return head;
}
(2)删除重复的节点:
- 如果可以使用临时缓存:
public void deleteDups(ListNode head) {
HashMap<Integer, Boolean> map = new HashMap<>();//记录重复的元素
ListNode pre = null;
while(head != null) {
if(map.containsKey(head.val)) {
pre.next = head.next;
} else {
map.put(head.val, true);
}
}
head = head.next;
}
- 如果不可以使用临时缓存:
public void deleteDups(ListNode head) {
if(head == null) return;
ListNode curr = head;
while(curr != null) {
/*
* 移除后续所有相同节点
*/
ListNode run = curr;
while(run.next != null) {
if(run.next.val == curr.val) {
run.next = run.next.next;
} else {
run = run.next;
}
}
curr = curr.next;
}
}
(3)删除倒数第k个节点:
public void deleteKthToTail(ListNode head,int k) {
ListNode h1 = head;
ListNode h2 = head;
/*
* h1前进k+1步
*/
while(k>=0 && h1!=null){
h1 = h1.next;
k--;
}
/*
* 找到倒数第k+1的节点:h2
*/
while(h1 != null){
h1 = h1.next;
h2 = h2.next;
}
h2.next = h2.next.next;//删除
}
(4)删除某个节点(只能访问该节点):
public void removeNode(ListNode pNode) {
if(pNode.next == null) {
pNode = null;
}
pNode.val = pNode.next.val;
pNode.next = pNode.next.next;
}