链表理论基础
这段代码定义了一个名为ListNode的公共类。该类具有三个成员变量:val(表示节点的值)、next(表示指向下一个节点的指针)和构造函数。
int val;:这是一个整型变量,用于存储节点的值。ListNode next;:这是一个指向下一个节点的指针。它是一个ListNode类型的变量,用于构建链表结构。ListNode() {}:这是一个无参构造函数,用于创建一个空的ListNode对象。ListNode(int val):这是一个带有一个参数的构造函数,用于创建一个具有指定值的ListNode对象。ListNode(int val, ListNode next):这是一个带有两个参数的构造函数,用于创建一个具有指定值和指向下一个节点的指针的ListNode对象。
在这段代码中,它定义了一个基本的链表节点类,用于构建链表数据结构。每个节点都包含一个值和一个指向下一个节点的指针。这个类可以用来创建链表,并进行节点的插入、删除和遍历等操作。
// 定义单链表
public class ListNode {
int val; // 当前节点值
ListNode next; // 下一个节点
public ListNode() {} // 无参构造函数,创建一个空的ListNode对象
public ListNode(int val) { // 有一个参数的构造函数,创建一个指定值为val的ListNode对象
this.val = val;
}
public ListNode(int val, ListNode next) { // 有两个参数的构造函数,创建一个具有指定值val和指向下一个节点的指针的ListNode对象
this.val = val;
this.next = next;
}
}
// 又敲了几遍
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. 移除链表元素 - 力扣(LeetCode)
思考:
方法一: 老久不做好陌生,先循环处理头节点,后定义临时节点进行循环遍历判断处理,这个过程操作的就是目标链表!!
方法二: 直接设置虚拟头节点忽略单个头节点的影响,后续循环遍历、判断是否相等、更换节点指针指向操作和方法一一致。
代码实现:
/**
* 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) {
while (head != null && head.val == val) {
head = head.next;
}
if (head == null) {
return head;
}
// 以上逻辑处理头节点内容
// 以下逻辑处理值不为val头节点后的节点
ListNode prev = head;
while (prev.next != null) {
if (prev.next.val == val) {
prev.next = prev.next.next;
} else {
prev = prev.next;
}
}
return head;
}
}
// 方法二:虚拟头节点
// class Solution {
// public ListNode removeElements(ListNode head, int val) {
// ListNode dummyHead = new ListNode(0, head); // 创建一个指向链表头节点的虚拟头节点 dummyHead,并赋值为0
// ListNode cur = dummyHead; // 临时节点指向虚拟头节点进行遍历,同时改变链表内的指针
// while (cur.next != null) {
// if (cur.next.val == val) {
// cur.next = cur.next.next;
// } else {
// cur = cur.next;
// }
// }
// return dummyHead.next;
// }
// }
题目:707. 设计链表 - 力扣(LeetCode)
代码实现:
// 定义一个单链表
class ListNode {
int val;
ListNode next;
ListNode() {
}
ListNode(int val) {
this.val = val;
}
}
class MyLinkedList {
int size; // 存储链表元素的个数
ListNode head; // 虚拟头节点
public MyLinkedList() { // 构造方法,初始化链表
size = 0; // 将链表大小初始化为 0
head = new ListNode(0); // 创建一个带有 0 值的头节点
}
public int get(int index) { // 获取下标为 index 的节点的数值,注意 index 是从 0 开始的,第 0 个节点就是头节点
if (index < 0 || index >= size) {
return -1;
}
ListNode currentNode = head; // 包含一个虚拟头节点
for (int i = 0; i <= index; i++) { // 所以查找下标为 index 的节点
currentNode = currentNode.next;
}
return currentNode.val;
}
public void addAtHead(int val) { // 在链表的最前面插入一个节点,等价于在第 0 个元素前添加
addAtIndex(0, val);
}
public void addAtTail(int val) { // 在链表的尾部添加一个节点,等价于在(末尾+1)个元素前添加
addAtIndex(size, val);
}
public void addAtIndex(int index, int val) {
if (index > size) {
return;
}
if (index < 0) {
index = 0;
}
size++;
ListNode prev = head; // 前驱节点用于遍历
for (int i = 0; i < index; i++) {
prev = prev.next;
}
ListNode toAdd = new ListNode(val); // 插入节点的值赋予 val 值
toAdd.next = prev.next;
prev.next = toAdd;
}
public void deleteAtIndex(int index) { // 删除指定下标 index 位置的节点
if (index < 0 || index >= size) { // 如果下标不合法,直接返回
return;
}
size--; // 链表大小减 1
if (index == 0) { // 要删除的是头节点
head = head.next; // 将头节点指向下一个节点
return;
}
ListNode prev = head; // 删除非头节点的前驱节点
for (int i = 0; i < index; i++) {
prev = prev.next;
}
prev.next = prev.next.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. 反转链表 - 力扣(LeetCode)
代码实现
// 双指针法
class Solution {
public ListNode reverseList(ListNode head) {
// 双指针
ListNode cur = head;
ListNode prev = null;
while (cur != null) {
ListNode temp = cur.next;
cur.next = prev;
prev = cur;
cur = temp;
}
return prev;
}
}
// 递归法
class Solution {
public ListNode reverseList(ListNode head) {
return reverse(head, null);
}
private ListNode reverse(ListNode cur, ListNode prev) {
if (cur == null) return prev;
ListNode temp = cur.next;
ListNode res = reverse(temp, cur);
cur.next = prev;
return res;
}
}