一、203. 移除鏈表元素
題目連接:https://leetcode.cn/problems/remove-linked-list-elements/
思路:單鏈表要移除元素,需要知道刪除元素的前一個(gè)節(jié)點(diǎn),改變前一個(gè)元素的pre.next等于cur.next
思路一:通過添加虛擬頭節(jié)點(diǎn),遍歷如果下一個(gè)節(jié)點(diǎn)=val,即pre.next == val, 則刪除next節(jié)點(diǎn),即pre.next=pre.next.next;
/**
* Definition for singly-linked list.
* 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 Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummyHead = new ListNode();
dummyHead.next = head;
ListNode pre = dummyHead;
while (pre.next != null) {
if (pre.next.val == val) {
pre.next = pre.next.next;
} else {
pre = pre.next;
}
}
return dummyHead.next;
}
}
思路二:不使用虛擬節(jié)點(diǎn),先看head是否等于val,等于修改head為head.next,在通過pre.next.val 是否等于val 來是否移除元素
/**
* Definition for singly-linked list.
* 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 Solution {
public ListNode removeElements(ListNode head, int val) {
while (head != null && head.val == val){
head = head.next;
}
ListNode pre = head;
while (pre != null && pre.next != null) {
if (pre.next.val == val) {
pre.next = pre.next.next;
} else {
pre = pre.next;
}
}
return head;
}
}
二、 206. 反轉(zhuǎn)鏈表
題目連接:https://leetcode.cn/problems/reverse-linked-list/
思路一、迭代法,記錄前一個(gè)指針pre、讓當(dāng)前的cur.next=pre,在這之前要下記錄下next,cur = next;
/**
* Definition for singly-linked list.
* 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 Solution {
public ListNode reverseList(ListNode head) {
ListNode cur = head;
ListNode pre = null;
while (cur != null) {
ListNode next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
}
}
思路二、使用遞歸、遞歸到最后一個(gè)元素時(shí),即head.next == null,遞歸回溯,修改當(dāng)前節(jié)點(diǎn)的next.next = 當(dāng)前節(jié)點(diǎn),并且head.next = null;
/**
* Definition for singly-linked list.
* 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 Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode listNode = reverseList(head.next);
head.next.next = head;
head.next = null;
return listNode;
}
}
思路三、使用棧模擬遞歸的過程
/**
* Definition for singly-linked list.
* 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 Solution {
public ListNode reverseList(ListNode head) {
Stack<ListNode> stack = new Stack<>();
ListNode cur = head;
while (cur != null && cur.next != null){
stack.push(cur);
cur = cur.next;
}
ListNode newHead = cur;
while (!stack.isEmpty()){
ListNode listNode = stack.pop();
listNode.next = null;
cur.next = listNode;
cur = listNode;
}
return newHead;
}
}
三、707. 設(shè)計(jì)鏈表
題目連接:https://leetcode.cn/problems/design-linked-list/
1、使用單鏈表,設(shè)計(jì)一個(gè)虛擬頭結(jié)點(diǎn)、查找的時(shí)候要 <= index, 添加和刪除要找到前一個(gè)節(jié)點(diǎn)即 < index
添加節(jié)點(diǎn):newListNode.next = pre.next;
? ? ? ?pre.next = newListNode;
? ? ? ?size++;
刪除節(jié)點(diǎn):pre.next = pre.next.next;
? ? ? ?size--;
class MyLinkedList {
public static class ListNode {
public int val;
public ListNode next;
public ListNode(){}
public ListNode(int val) {
this.val = val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
private ListNode dummy;
int size = 0;
public MyLinkedList() {
dummy = new ListNode();
}
public int get(int index) {
if (index < 0 || index >= size) return -1;
ListNode cur = dummy;
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 pre = dummy;
for (int i = 0; i < index; i++){
pre = pre.next;
}
ListNode newListNode = new ListNode(val);
newListNode.next = pre.next;
pre.next = newListNode;
size++;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) return;
ListNode pre = dummy;
for (int i = 0; i < index; i++){
pre = pre.next;
}
pre.next = pre.next.next;
size--;
}
}
2、使用雙鏈表,注意查找的時(shí)候當(dāng) index >= size / 2 從后面向前搜索;同理刪除和添加也是,獲取到index的前一個(gè)節(jié)點(diǎn)pre.
查找操作:
if (index > size / 2) {
ListNode cur = tail;
for (int i = 0; i < size - index; i++) {
cur = cur.prev;
}
return cur.val;
} else {
ListNode cur = head;
for (int i = 0; i <= index; i++) {
cur = cur.next;
}
return cur.val;
}
添加操作:ListNode newListNode = new ListNode(val);
? ? ? ?newListNode.next = pre.next;
? ? ? ?pre.next.prev = newListNode;
? ? ? ?pre.next = newListNode;
? ? ? ?newListNode.prev = pre;
刪除操作:pre.next.next.prev = pre;
? ? ? ?pre.next = pre.next.next;
class MyLinkedList {
public static class ListNode {
public int val;
public ListNode next;
public ListNode prev;
public ListNode(){}
public ListNode(int val) {
this(val, null);
}
public ListNode(int val, ListNode next){
this(val, next, null);
}
public ListNode(int val, ListNode next, ListNode prev) {
this.val = val;
this.next = next;
this.prev = prev;
}
}
private ListNode head;
private ListNode tail;
int size = 0;
public MyLinkedList() {
head = new ListNode();
tail = new ListNode();
head.next = tail;
tail.prev = head;
size = 0;
}
public int get(int index) {
if (index < 0 || index >= size) return -1;
if (index > size / 2) {
ListNode cur = tail;
for (int i = 0; i < size - index; i++){
cur = cur.prev;
}
return cur.val;
} else {
ListNode cur = head;
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);
ListNode newListNode = new ListNode(val);
tail.prev.next = newListNode;
newListNode.prev = tail.prev;
newListNode.next = tail;
tail.prev = newListNode;
size++;
}
public void addAtIndex(int index, int val) {
if (index > size) return;
if (index < 0) index = 0;
// ListNode pre = head;
// for (int i = 0; i < index; i++){
// pre = pre.next;
// }
if (index == size) {
addAtTail(val);
return;
}
ListNode pre = getListPreNode(index);
ListNode newListNode = new ListNode(val);
newListNode.next = pre.next;
pre.next.prev = newListNode;
pre.next = newListNode;
newListNode.prev = pre;
size++;
}
private ListNode getListPreNode(int index) {
if (index < 0 || index >= size) return null;
if (index >= size / 2) {
ListNode pre = tail;
for (int i = 0; i <= size - index; i++){
pre = pre.prev;
}
return pre;
} else {
ListNode pre = head;
for (int i = 0; i < index; i++) {
pre = pre.next;
}
return pre;
}
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) return;
// ListNode pre = head;
// for (int i = 0; i < index; i++){
// pre = pre.next;
// }
// pre.next.next.prev = pre;
// pre.next = pre.next.next;
ListNode pre = getListPreNode(index);
pre.next.next.prev = pre;
pre.next = pre.next.next;
size--;
}
}