1. 移除链表元素
- 第一想法:之前刷过,能想到使用虚拟头节点
- 看到题解想法:本人和题解基本相同
- 遇到困难:无
public ListNode removeElements(ListNode head, int val) {
ListNode vHead = new ListNode();
vHead.next = head;
ListNode pre = vHead;
ListNode n = head;
while (n != null) {
if (n.val == val) {
pre.next = n.next;
n = n.next;
} else {
pre = n;
n = n.next;
}
}
return vHead.next;
}
2. 设计链表
- 第一想法:重要的逻辑有插入、删除、修改,每个逻辑的分类讨论情况比较多
- 看到题解想法:
- 遇到困难:逻辑分类情况比较多,容易混乱
1class MyLinkedList {
ListNode vHead;
int size;
public MyLinkedList() {
vHead = new ListNode();
}
public int get(int index) {
ListNode n = vHead.next;
if (index >= 0 && index < size) {
for (int i = 0; i < index; i++) {
if (n == null) return -1;
n = n.next;
}
return n.val;
}
return -1;
}
public void addAtHead(int val) {
addAtIndex(-1, val);
}
public void addAtTail(int val) {
addAtIndex(size, val);
}
public void addAtIndex(int index, int val) {
ListNode n = vHead.next;
ListNode pre = vHead;
ListNode curr = new ListNode(val);
// index小于0,插到头部
if (index < 0) {
curr.next = vHead.next;
vHead.next = curr;
// index正常范围
} else if (index >= 0 && index < size) {
for (int i = 0; i < index; i++) {
pre = pre.next;
n = n.next;
}
curr.next = n;
pre.next = curr;
// index == size 插到尾部
} else if (index == size) {
while (n != null) {
pre = pre.next;
n = n.next;
}
pre.next = curr;
// 什么也不做
} else {
return;
}
size++;
}
public void deleteAtIndex(int index) {
ListNode n = vHead.next;
ListNode pre = vHead;
if (index >= 0 && index < size) {
for (int i = 0; i < index; i++) {
pre = pre.next;
n = n.next;
}
ListNode ln = n.next;
pre.next = ln;
size--;
}
}
}
class ListNode {
int val;
ListNode next;
ListNode prev;
public ListNode(int val) {
this.val = val;
}
public ListNode() {}
}
- 总结与收获:时长1h,设计链表可以从整体到特殊。比如先实现addAtIndex()后,addAtHead()和addAtTail()都是前者的特殊情况
3. 反转链表
- 第一想法:二刷,模拟法比较容易上手
- 看到题解想法:和自己想的差不多
- 遇到困难:没有大问题
// 1. 个人解答
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode pre = head;
ListNode n = head.next;
ListNode aft = n.next;
while (n != null) {
if (pre == head) pre.next = null;
n.next = pre;
pre = n;
n = aft;
if (aft != null) aft = aft.next;
}
return pre;
}
// 2. 题解:将后指针仅仅当成一个临时存下个节点的变量
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) return head;
ListNode pre = head;
ListNode n = head.next;
while (n != null) {
// 先保存后指针,再执行后续语句
ListNode aft = n.next;
if (pre == head) pre.next = null;
n.next = pre;
pre = n;
n = aft;
}
return pre;
}
- 总结与收获:
- 后指针在循环开始之前保存一下后续的值就好