203.移除链表元素
解法:代码随想录
链表题之前做过类似的所以,很快想到用虚拟节点。虚拟节点的next指向head,然后从虚拟节点开始扫。最后直接return 虚拟节点的next。这道题一开始没有考虑连续出现val == target的情况所以在大while里面只设置了一个if,应该再用一个while来持续扫。
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode slide = new ListNode();
slide.next = head;
head = slide;
while(slide != null) {
while (slide.next != null && slide.next.val == val) {
slide.next = slide.next.next;
}
slide = slide.next;
}
return head.next;
}
}
看了解析此题还有别的解法:
1.不设置虚拟节点,在前面用一个while扫到一个val != traget的节点,然后从此节点开始操作。
2.同时可以设置一个节点来记录之前的一个节点(prev). 当有val == target的情况,prev.next = cur.next; 并且 cur = cur.next;
707.设计链表
一开始自己做的时候把head当作一个实际节点而不是虚拟节点,导致需要判定的东西很多,同时addAtTaile和addAtLast也分别需要独自的判定才能完成。最后又写成一坨,接着就开始看讲解。
第二遍写的时候有两点导致无法AC
1. addAtIndex的时候可以index等与size想当与添加到末尾。(我想当然写成 index >= size就return
2. 在add的时候如果index小于0直接将index设置成0,完全没有注意到这点。看了答案才知道。
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 MyLinkedList {
ListNode head;
int size;
public MyLinkedList() {
head = new ListNode();
int size = 0;
}
public int get(int index) {
if (index < 0 || index >= size) return -1;
ListNode slide = head;
while (index > 0) {
index--;
slide = slide.next;
}
return slide.next.val;
}
public void addAtHead(int val) {
addAtIndex(0, val);
}
public void addAtTail(int val) {
//index 可以等于size, 再次注意
addAtIndex(size, val);
}
public void addAtIndex(int index, int val) {
//index可以等于size
if (index > size) return;
if (index < 0) index = 0;
ListNode slide = head;
while (index > 0) {
index--;
slide = slide.next;
}
slide.next = new ListNode(val, slide.next);
size++;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) return;
ListNode slide = head;
while (index > 0) {
index--;
slide = slide.next;
}
size--;
slide.next = slide.next.next;
}
}
double linked周末再看吧
206.反转链表
这道题上个月做过还有,所以还有印象。上次第一次自己做的时候,用的stack来实现的反转,第一遍遍历存储到stack里面,第二遍遍历在pop的同时翻转。
看别人的code,发现除了stack,此题可以设置一个节点来记录前一个节点(ListNode prev = null), 这样可以实现在遍历的同时实现翻转。所以这次重新写,就用了这个方法。
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev = null;
while (head != null) {
ListNode tmp = head.next;
head.next = prev;
prev = head;
head = tmp;
}
return prev;
}
}
同时试了试递归的写法,绕了半天绕出来了,递归本质上逻辑一致,还是需要一个prev来记录之前的node。在扫到null的时候递归终止,直接return上一个prev,而在此之前的loop只需要记录这个最后一个node并且return,这个node就是新的head。
class Solution {
public ListNode reverseList(ListNode head) {
return helper(head, null);
}
public ListNode helper(ListNode node, ListNode prev) {
if (node == null) return prev;
ListNode tmp = node.next;
node.next = prev;
return helper(tmp, node);
}
}
看了解析,差不多一样,发现还有一种从后往前递归,这个有缘再看。