代码随想录Day03
今日任务
● 链表理论基础
● 203.移除链表元素
● 707.设计链表
● 206.反转链表
203 移除链表元素
LeetCode203
自己没想出的的原因就是没有使用双指针,没有这个思想,=
代码实现:
//未采用虚拟头结点
public ListNode removeElements(ListNode head, int target) {
while (head != null && head.val == target) {
head = head.next;
}
if (head == null) {
return head;
}
ListNode pre = head;
ListNode current = pre.next;
while (current != null) {
if (current.val == target) {
pre.next = current.next;
} else {
pre = pre.next;
}
current = current.next;
}
return head;
}
虚拟头结点
public ListNode removeElements(ListNode head, int val) {
ListNode virtualHead = new ListNode(-1, head);
ListNode pre = virtualHead;
ListNode current = virtualHead.next;
while (current != null) {
if (current.val == val) {
pre.next = pre.next.next;
} else {
pre = pre.next;
}
current = current.next;
}
return virtualHead.next;
}
虚拟头结点的优势在于头结点边界值特殊情况好处理
707.设计链表
LeetCode707
代码如下,这里只实现了未使用虚拟头结点的单链表,有时间试试双向链表
static class MyLinkedList {
ListNode head;
public MyLinkedList() {
}
public int get(int index) {
if (head == null) {
return -1;
}
ListNode current = head;
while (current != null && index > 0) {
current = current.next;
index--;
}
if (current == null) {
return -1;
}
return current.val;
}
public void addAtHead(int val) {
ListNode newHead = new ListNode(val);
newHead.next = head;
this.head = newHead;
}
public void addAtTail(int val) {
if (head == null) {
head = new ListNode(val);
return;
}
ListNode current = head;
while (current.next != null) {
current = current.next;
}
current.next = new ListNode(val);
}
public void addAtIndex(int index, int val) {
if (index == 0) {
addAtHead(val);
return;
}
if (head == null) {
return;
}
ListNode pre = head;
ListNode current = head.next;
while (current != null && index > 1) {
pre = current;
current = current.next;
index--;
}
//如果index还大于1,说明index长度大于链表长度
if (index == 1) {
pre.next = new ListNode(val, current);
}
}
public void deleteAtIndex(int index) {
if (head == null) {
return;
}
if (index == 0) {
head = head.next;
return;
}
ListNode pre = head;
ListNode current = head.next;
while (current != null && index > 1) {
pre = pre.next;
current = current.next;
index--;
}
if (current != null && index == 1) {
pre.next = current.next;
}
}
}
206.反转链表
LeetCode206
双指针法:
自己想的是把头结点一个一个指向下下个节点,然后将头结点的下一个节点放到最前,上次做题的时候也是这样想的。直接的反转使用temp保存临时节点的方式需要理解。
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode currentHead = head;
ListNode next = head.next;
while (next != null) {
head.next = next.next;
next.next = currentHead;
currentHead = next;
next = head.next;
}
return currentHead;
}
双指针-代码随想录版:
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode cur = head;
ListNode temp = null;
while (cur != null) {
temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
递归法,递归法就是将大问题拆解成一个个可以用同样方法解决的小问题,这个看了代码随想录的视频讲解后可以理解,从前往后的写法,这种写法是将双指针法“翻译”为递归法,思想是一样的
public ListNode reverseList(ListNode head) {
return reverse(null, head);
}
public ListNode reserve(ListNode pre, ListNode current) {
if (current == null) {
return pre;
}
ListNode temp = current.next;
current.next = pre;
return reserve(current, temp);
}
leetcode官方给出的是从后往前的递归法,更符合一般情况下递归的场景,都是从后往前,但是万万是想不出来的,以后再理解吧~
总结
1.链表的重点是指针,链表题的重点是双指针法,一般是要保存当前节点和上一个节点
2.打字的时候错别字太多了,导致我写这几个字也很慢
今天先补昨天的,明天再补前天的