题目:
203.移除链表元素, 707.设计链表,206.反转链表
学习内容:
链表基础
链表是通过指针连在一起的线性结构,每个节点由data(数据)和next(指向下一个节点的指针),最后一个节点的next指向null。
链表分为:单链表、双链表和循环链表。由于指针可以连接内存中的各个节点,所以链表在内存中不连续分布,数组在内存中是连续分布的。
对比可以发现 数组适合查,链表适合增删改。
链表的定义:
public class ListNode() {
int val; // 定义data
ListNode next; // 定义next
// 定义空参构造函数
public ListNode() {
}
// 定义data参数的构造函数
public ListNode(int val) {
this.val = val;
}
// 定义data和next的构造函数
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
203.移除链表元素
使用虚拟头节点法会满足循环不变量原则。使用两个指针,cur用来遍历链表。pre是cur的前一个指针,用来更改连接,实际上就是移除元素。
/**
* 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) {
ListNode dummyhead = new ListNode(-1, head); // 定义虚拟头节点,指向真实头节点
ListNode cur = head; // 定义指针,从真实头节点开始
ListNode pre = dummyhead; // 定义在cur前一位的指针pre
while (cur != null) {
if (cur.val == val) {
pre.next = cur.next; // 找到要删除的节点,则连接要删除节点的下一个
} else {
pre = pre.next; // 没有找到则pre向后移动一位
}
cur = cur.next; // 指针往后走一位
}
return dummyhead.next; // 返回除了虚拟头节点的ListNode
}
}
时间复杂度:O(n)
空间复杂度:O(1)
707.设计链表
206.反转链表
/**
* 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 = head;
ListNode pre = null;
while (cur != null) {
ListNode temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
}
学习时间
2024.3.8