第一关__ 链表 __青铜局
1. 前言
第一关是链表的基本问题,第二关是链表反转以及拓展问题。
2. 重点
- 算法的基础是数据结构,任何数据结构的基础操作都是创建+增删改查。
- 所以关于学习数据结构,重点首先是前面5个来进行学习算法里的数据结构。
- 另外,还需要时不时的思考时间复杂度和空间复杂度的问题。
3. 本节要点
- 理解Java/Python是如何构造出链表的
- 链表增加元素,首部、中间和尾部分别会有什么问题,该如何处理?
- 链表删除元素,首部、中间和尾部分别会有什么问题,该如何处理?
- 双向链表是如何构造的,如何实现元素的插入和删除
4.链表内部结构
代码:
public class ListNode {
public int val;
public ListNode next;
}
5. 遍历链表
遍历时,从头开始逐个访问
public static int getLength(Node head) {
int length = 0;
Node node = head;
while (node != null) {
length++;
node = node.next;
}
return length;
}
6. 链表插入
考虑三种情况:
- 首部,即表头插入
- 中间
- 尾部
6.1 表头插入
🎯创建新结点后,要把head重新指向newNode新结点,过程如图所示:
6.2 中间插入
-
找到插入节点的前驱结点pre
-
newNode节点指向
pre.next
,pre
指向newNode==(先指向后继,后指向前驱)==newNode.next=pre.next; pre.next=newNode
6.3 尾部插入
- 尾结点直接指向新结点
- 新结点指向null
代码实现
public static Node insertNode(Node head, Node nodeInsert, int position) {
// 需要判空,否则后面可能会有空指针异常
if (head == null) {
return nodeInsert;
}
//越界判断
int size = getLength(head);
if (position > size + 1 || position < 1) {
System.out.println("位置参数越界");
return head;
}
//在链表开头插入
if (position == 1) {
nodeInsert.next = head;
// return nodeInsert;
//上面return还可以这么写:
head = nodeInsert;
return head;
}
Node pNode = head;
int count = 1;
//找到要插入节点的前序结点
while (count < position - 1) {
pNode = pNode.next;
count++;
}
nodeInsert.next = pNode.next;
pNode.next = nodeInsert;
return head;
}
值得注意的是,链表插入结点:
int count = 1;
//找到要插入节点的前序结点
while (count < position - 1) {
pNode = pNode.next;
count++;
}
nodeInsert.next = pNode.next;
pNode.next = nodeInsert;
7. 链表删除
- 删表头
- 删尾结点
- 删中间结点
7.1 删除表头结点
head=head.next
- 执行此段代码即可,将head向前移动删除
- 原来结点会被JVM回收掉
7.2 删除尾结点
-
同样,需要==找到删除结点的前驱节点==——提前一个位置判断
举例:
删除40,前驱结是7,遍历时候需判断
cur.next
是否为40:若是,执行cur.next=null
即可。此时40会被JVM回收
7.3 删除中间结点
- 找出删除结点的前驱结点(这里我们统称为cur)
cur.next=cur.next.next
/**
* 删除节点
*
* @param head 链表头节点
* @param position 删除节点位置,取值从1开始
* @return 删除后的链表头节点
*/
public static Node deleteNode(Node head, int position) {
if (head == null) {
return null;
}
int size = getLength(head);
if (position > size || position <= 0) {
System.out.println("输入的参数有误");
return head;
}
if (position == 1) {
// head.next就是链表的新head
return head.next;
}
Node preNode = head;
int count = 1;
while (count < position) {
preNode = preNode.next;
count++;
}
Node curNode=preNode.next;
preNode.next=curNode;
return head;
}