203.移除链表元素
题目链接/文章讲解/视频讲解::代码随想录
- 第一想法:
- dummy node, 没有用pre, cur, 只用了一个cur
- while loop 更新条件可以只需要while (cur.next != null)
- 时间复杂度O(n)
-
class Solution { public ListNode removeElements(ListNode head, int val) { if (head == null) return head; ListNode dummy = new ListNode(0); dummy.next = head; ListNode cur = dummy; while (cur!=null && cur.next!=null) { if (cur.next.val == val) cur.next = cur.next.next; else cur = cur.next; } return dummy.next; } }
- 看完讲解:
- 1. dummy, pre, cur
- 2. pre, cur
- if (head == null) return head; 要放在while loop更新完后面
class Solution { public ListNode removeElements(ListNode head, int val) { while (head != null && head.val == val) head = head.next; if (head == null) return head; ListNode prev = head; ListNode cur = head.next; while (cur!=null) { if (cur.val == val) prev.next = cur.next; else prev = cur; cur = cur.next; } return head; } }
- if (head == null) return head; 要放在while loop更新完后面
- 3. 只用cur
- 注意两个while loop条件:
- while (cur!=null) {
while (cur.next != null && cur.next.val == val) -
class Solution { public ListNode removeElements(ListNode head, int val) { while (head!= null && head.val == val) head = head.next; if (head == null) return head; ListNode cur = head; while (cur!=null) { while (cur.next != null && cur.next.val == val) cur.next = cur.next.next; cur = cur.next; } return head; } }
- while (cur!=null) {
- 注意两个while loop条件:
707.设计链表
题目链接/文章讲解/视频讲解:代码随想录
- 第一想法:singly linked list
- class ListNode{} 在整个class MyLinkedList{} 外面并列的,复习OOP
- 熟记class ListNode{} (这道题应该不需要this.next)
- MyLinkedList{}里面的variable:int size, ListNode head
- add()三个function都有点问题
-
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 { int size; ListNode head; public MyLinkedList() { head = new ListNode(0); size = 0; } public int get(int index) { if (index < 0 || index >= size) return -1; ListNode cur = head; while (index > 0) { cur = cur.next; index--; } return cur.val; } public void addAtHead(int val) { if (head == null) { head = new ListNode(val); size++; return; } ListNode temp = new ListNode(val); temp.next = head; size++; } public void addAtTail(int val) { ListNode cur = head; while(cur.next != null) { cur = cur.next; } cur.next = new ListNode(val); cur.next.next = null; size++; } public void addAtIndex(int index, int val) { if (index == 0) addAtHead(val); if (index == size) addAtTail(val); if (index > size) return; ListNode cur = head; for (int i=0; i<index-1; i++) { cur = cur.next; } ListNode temp = new ListNode(val); temp.next = cur.next; cur.next = temp; size++; } public void deleteAtIndex(int index) { if (index < 0 || index >= size) return; if (index == 0) head = head.next; ListNode cur = head; for (int i=0; i<index-1; i++) { cur = cur.next; } cur.next = cur.next.next; size--; } }
- 看完讲解:
- singly linked list
- 以下所有的边界问题在于,head是dummy node
- get()里的while (index-- >= 0)
- addAtIndex里的index<0情况:if (index < 0) index = 0;
- addAtIndex里的for loop边界:for (int i=0; i<index; i++)
- deleteAtIndex里不需要特别考虑index==0的情况
- deleteAtIndex里for loop边界:for (int i=0; i<index; i++)
-
class ListNode { int val; ListNode next; ListNode() { } ListNode(int val) { this.val = val; } } class MyLinkedList { int size; ListNode head; public MyLinkedList() { head = new ListNode(0); size = 0; } public int get(int index) { if (index < 0 || index >= size) return -1; ListNode cur = head; while (index-- >= 0) { cur = cur.next; } return cur.val; } public void addAtHead(int val) { addAtIndex(0, val); } public void addAtTail(int val) { addAtIndex(size, val); } public void addAtIndex(int index, int val) { if (index > size) return; if (index < 0) index = 0; ListNode cur = head; for (int i=0; i<index; i++) { cur = cur.next; } ListNode temp = new ListNode(val); temp.next = cur.next; cur.next = temp; size++; } public void deleteAtIndex(int index) { if (index < 0 || index >= size) return; ListNode cur = head; for (int i=0; i<index; i++) { cur = cur.next; } cur.next = cur.next.next; size--; } }
- doubly linked list
- 不需要在addAtStart() / addAtTail()里单独更新head / tail, 只需要在addAtIndex()里更新prev, next逻辑
- get()里可以从前用next遍历,或者从后用prev遍历
-
class ListNode { int val; ListNode prev; ListNode next; ListNode() { } ListNode(int val) { this.val = val; } } class MyLinkedList { int size; ListNode head; ListNode tail; public MyLinkedList() { head = new ListNode(0); tail = new ListNode(0); head.next = tail; tail.prev = head; size = 0; } public int get(int index) { //判断index是否有效 if(index<0 || index>=size){ return -1; } ListNode cur = this.head; //判断是哪一边遍历时间更短 if(index >= size / 2){ //tail开始 cur = tail; for(int i=0; i< size-index; i++){ cur = cur.prev; } }else{ for(int i=0; i<= index; i++){ cur = cur.next; } } return cur.val; } public void addAtHead(int val) { addAtIndex(0, val); } public void addAtTail(int val) { addAtIndex(size, val); } public void addAtIndex(int index, int val) { if (index > size) return; if (index < 0) index = 0; ListNode cur = head; for (int i=0; i<index; i++) { cur = cur.next; } ListNode temp = new ListNode(val); temp.next = cur.next; temp.next.prev = temp; temp.prev = cur; cur.next = temp; size++; } public void deleteAtIndex(int index) { if (index < 0 || index >= size) return; ListNode cur = head; for (int i=0; i<index; i++) { cur = cur.next; } cur.next.next.prev = cur; cur.next = cur.next.next; size--; } }
- singly linked list
206.反转链表
题目链接/文章讲解/视频讲解:代码随想录
- 第一想法:
-
class Solution { public ListNode reverseList(ListNode head) { if (head == null) return head; ListNode prev = null; ListNode cur = head; ListNode next; while (cur!=null) { next = cur.next; cur.next = prev; prev = cur; cur = next; } return prev; } }
-
- 看完讲解:递归法,一样的逻辑
-
class Solution { public ListNode reverseList(ListNode head) { return reverse(null, head); } private ListNode reverse(ListNode prev, ListNode cur) { if (cur == null) { return prev; } ListNode temp = null; temp = cur.next;// 先保存下一个节点 cur.next = prev;// 反转 // 更新prev、cur位置 // prev = cur; // cur = temp; return reverse(cur, temp); } }
-