203. 移除链表元素
题目链接:203. 移除链表元素 - 力扣(LeetCode)
思路: 两个指针一个pre指向虚拟头节点,一个cur指向head,cur不为null时,进行循环,当cur的值等于target时,pre指向cur的next节点,cur向后移。如果cur不等于目标值,pre和cur同时向后移。
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummy = new ListNode(-1, head);
ListNode pre = dummy, cur = head;
while (cur != null) {
if (cur.val == val) {
pre.next = cur.next;
} else {
pre = pre.next;
}
cur = cur.next;
}
return dummy.next;
}
}
总结:
707. 设计链表
思路: 每个方法的思路都是正确的,但是具体实现的时候总是有各种问题orz。刚开始没有想到构造函数里要放size来存储链表的长度。addAtHead方法刚开始写的是 cur.next = head.next, 缺了 head.next = cur这一步。
//正解
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.next;
while (index > 0) {
cur = cur.next;
index--;
}
return cur.val;
}
public void addAtHead(int val) {
ListNode cur = new ListNode(val);
cur.next = head.next;
head.next = cur;
size++;
}
public void addAtTail(int val) {
ListNode cur = new ListNode(val);
ListNode pre = head;
while (pre.next != null) {
pre = pre.next;
}
pre.next = cur;
size++;
// addAtIndex(size, val);
}
public void addAtIndex(int index, int val) {
if (index < 0 || index > size) {
return;
}
ListNode cur = new ListNode(val);
ListNode pre = head;
while (index > 0) {
pre = pre.next;
index--;
}
cur.next = pre.next;
pre.next = cur;
size++;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
ListNode pre = head;
while (index > 0) {
pre = pre.next;
index--;
}
pre.next = pre.next.next;
size--;
}
}
总结:
构造函数中初始化size来记录链表的长度,并且在每次删除、添加、插入之后更新size的值。使用dummyhead作为虚拟头节点来方便处理,链表删除和插入操作中,指针应该指向待插入/删除的节点前一位,同时在操作的时候要注意顺序。
206. 反转链表
思路:
- 常规解法,一前一后两个指针,用temp保存cur.next的值。
- 递归做法没有思路
我的代码:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode dummy = new ListNode();
dummy.next = head;
ListNode pre = dummy;
ListNode cur = head;
pre.next = null;
while (cur != null) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
Output: [5,4,3,2,1,0]
Expected Output: [5,4,3,2,1]
正确解法:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
while (cur != null) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
递归解法:
和双指针一样的逻辑,同样是当cur为空的时候循环结束,不断将cur指向pre的过程。
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
return reverse(cur, pre);
}
public ListNode reverse(ListNode cur, ListNode pre) {
// 终止条件
if (cur == null) return pre;
ListNode temp = cur.next;
cur.next = pre;
return reverse(temp, cur);
}
}
问题:
- 头节点的初始化搞错了,知道pre的值应该设置为null,但是忘了可以直接写ListNode pre = null;
- return的返回值搞错了,第一遍写成return dummy.next,发现错误之后又改成return cur.next。
总结:
复习了反转链表的过程。