算法训练营(day03)

链表理论基础

  • 链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。
  • 链表的入口节点称为链表的头结点也就是head。
链表1
  • 链表是通过指针域的指针链接在内存中各个节点。所以链表中的节点在内存中不是连续分布的 ,而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理

链表的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ListNode {
// 结点的值
int val;

// 下一个结点
ListNode next;

// 节点的构造函数(无参)
public ListNode() {
}

// 节点的构造函数(有一个参数)
public ListNode(int val) {
this.val = val;
}

// 节点的构造函数(有两个参数)
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}

203.移除链表元素

题目链接:https://leetcode.cn/problems/remove-linked-list-elements/description/

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点

解题思路

解题过程:

  1. 定义一个虚拟头节点dum,遍历链表
  2. 判断 head.next 节点的值是否与 val 相等
    • == 则 head.next = head.next.next
    • != 则 head = head.next
  3. 返回 dum.next ;

详细代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head == null){
return null;
}
ListNode dum = new ListNode(0);
dum.next = head;
ListNode pre = dum;

while(pre.next != null){
if(pre.next.val == val){
pre.next = pre.next.next;
}else{
pre = pre.next;
}
}
return dum.next;
}
}

707.设计链表

题目链接:https://leetcode.cn/problems/design-linked-list/description/

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

解题思路

解题过程:

  1. 本题的关键在于 自行构造链表结构
  2. 功能实现主要是:查、改(插)、删
    • 查:遍历到index下标的位置,返回值即可
    • 改:根据index位置将新增节点连接前节点和后节点
    • 删:将index节点的前节点和后节点连接
  3. 其中 addAtHead(val)addAtTail(val) 都可以使用 addAtIndex(index,val) 实现

详细代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
class ListNode{
int val;
ListNode next;

public ListNode(){}

public ListNode(int val){
this.val = val;
}

public ListNode(int val, ListNode next){
this.val = val;
this.next = next;
}
}
class MyLinkedList {
int size;
ListNode head;

public MyLinkedList() {
size = 0;
head = new ListNode(0);
}

public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
ListNode cur = head;
for(int i = 0; i <= index; i++){
cur = cur.next;
}
return cur.val;
}

public void addAtHead(int val) {
addAtIndex(0, val);
}

public void addAtTail(int val) {
addAtIndex(size, val);
}

public void addAtIndex(int index, int val) {
if(index < 0 || index > size){
return;
}
index = Math.max(0, index);
size++;
ListNode pre = head;
for(int i = 0; i < index; i++){
pre = pre.next;
}
ListNode add = new ListNode(val);
add.next = pre.next;
pre.next = add;
}

public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
return;
}
size--;
if(index == 0){
head = head.next;
return;
}
ListNode pre = head;
for(int i = 0; i < index; i++){
pre = pre.next;
}
pre.next = pre.next.next;
}
}

/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList obj = new MyLinkedList();
* int param_1 = obj.get(index);
* obj.addAtHead(val);
* obj.addAtTail(val);
* obj.addAtIndex(index,val);
* obj.deleteAtIndex(index);
*/

206.反转链表

题目链接:https://leetcode.cn/problems/reverse-linked-list/description/

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

解题思路

解题过程:

  1. 保留 head.next 的值
  2. head 指向 前节点
  3. head = head.next 重复操作

详细代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode cur = null;
ListNode pre = null;
while(head != null){
cur = head.next;
head.next = pre;
pre = head;
head = cur;
}
return pre;
}
}