【LeetCode】連結串列問題:虛擬頭節點
阿新 • • 發佈:2021-02-11
虛擬頭節點
- 對於有刪除問題,一定要設定虛擬頭節點
203. 移除連結串列元素
難度簡單521收藏分享切換為英文接收動態反饋
刪除連結串列中等於給定值 *val* 的所有節點。
示例:
輸入: 1->2->6->3->4->5->6, val = 6
輸出: 1->2->3->4->5
題解
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode firstNode = new ListNode();
firstNode.next = head;
ListNode pre = firstNode;
ListNode node = firstNode.next;
while(node != null){
if(node .val == val){
pre.next = node = node.next;
}else {
pre = node ;
node = node.next;
}
}
return firstNode.next;
}
}
82. 刪除排序連結串列中的重複元素 II
難度中等442收藏分享切換為英文接收動態反饋
給定一個排序連結串列,刪除所有含有重複數字的節點,只保留原始連結串列中 沒有重複出現 的數字。
示例 1:
輸入: 1->2->3->3->4->4->5
輸出: 1->2->5
示例 2:
輸入: 1->1->1->2->3
輸出: 2->3
題解
class Solution {
public ListNode deleteDuplicates(ListNode head) {
ListNode resHead = null;
ListNode resTail = null;
ListNode node = head;
int beforeData = Integer.MAX_VALUE;
boolean canUseBeforeData = true;
while(node != null){
if(node == head){
beforeData = node.val;
node = node.next;
continue;
}
if(beforeData == node.val){
canUseBeforeData = false;
node = node.next;
continue;
}
if(canUseBeforeData){
if(resHead == null){
resHead = resTail = new ListNode(beforeData);
}else {
resTail.next = new ListNode(beforeData);
resTail = resTail.next;
}
}
beforeData = node.val;
canUseBeforeData = true;
node = node.next;
}
if(canUseBeforeData && head != null){
if(resHead == null){
resHead = new ListNode(beforeData);
}else {
resTail.next = new ListNode(beforeData);
}
}
return resHead;
}
}
24. 兩兩交換連結串列中的節點
難度中等799收藏分享切換為英文接收動態反饋
給定一個連結串列,兩兩交換其中相鄰的節點,並返回交換後的連結串列。
你不能只是單純的改變節點內部的值,而是需要實際的進行節點交換。
示例 1:
輸入:head = [1,2,3,4]
輸出:[2,1,4,3]
示例 2:
輸入:head = []
輸出:[]
示例 3:
輸入:head = [1]
輸出:[1]
題解
- 對於迴圈中(即遞推中)操作較複雜或者冗餘,考慮換成遞迴
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode firstNode = new ListNode();
firstNode.next = head;
func(firstNode);
return firstNode.next;
}
void func(ListNode head){
ListNode next = head.next;
ListNode next2 = null;
if(next != null){
next2 = next.next;
}
if(next == null || next2 == null){
return;
}
ListNode append = next2.next;
head.next = next2;
next2.next = next;
next.next = append;
func(next);
}
}
25. K 個一組翻轉連結串列
難度困難881收藏分享切換為英文接收動態反饋
給你一個連結串列,每 k 個節點一組進行翻轉,請你返回翻轉後的連結串列。
k 是一個正整數,它的值小於或等於連結串列的長度。
如果節點總數不是 k 的整數倍,那麼請將最後剩餘的節點保持原有順序。
示例:
給你這個連結串列:1->2->3->4->5
當 k = 2 時,應當返回: 2->1->4->3->5
當 k = 3 時,應當返回: 3->2->1->4->5
說明:
- 你的演算法只能使用常數的額外空間。
- 你不能只是單純的改變節點內部的值,而是需要實際進行節點交換
題解
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode firstNode = new ListNode();
firstNode.next = head;
func(firstNode ,k);
return firstNode.next;
}
void func(ListNode head , int k){
ListNode node = head.next;
int sum = 0;
while(node != null && sum != k){
sum ++;
node = node.next;
}
if(sum != k){
return;
}
ListNode pre = null;
ListNode cur = head.next;
ListNode after = null;
for(int i = 0 ; i < k ; i ++){
after = cur.next;
cur.next = pre;
pre = cur;
cur = after;
}
ListNode kLast = head.next ;
kLast.next = cur;
head.next = pre;
func(kLast , k);
}
}
147. 對連結串列進行插入排序
難度中等346收藏分享切換為英文接收動態反饋
對連結串列進行插入排序。
插入排序的動畫演示如上。從第一個元素開始,該連結串列可以被認為已經部分排序(用黑色表示)。
每次迭代時,從輸入資料中移除一個元素(用紅色表示),並原地將其插入到已排好序的連結串列中。
插入排序演算法:
- 插入排序是迭代的,每次只移動一個元素,直到所有元素可以形成一個有序的輸出列表。
- 每次迭代中,插入排序只從輸入資料中移除一個待排序的元素,找到它在序列中適當的位置,並將其插入。
- 重複直到所有輸入資料插入完為止。
示例 1:
輸入: 4->2->1->3
輸出: 1->2->3->4
示例 2:
輸入: -1->5->3->4->0
輸出: -1->0->3->4->5
題解
class Solution {
public ListNode insertionSortList(ListNode head) {
if(head == null){
return null;
}
ListNode sortArea = head;
while(sortArea.next != null){
sortArea = sortArea.next;
}
ListNode sortHead = new ListNode();
sortHead.next = sortArea;
ListNode node = head;
while(node != sortArea){
ListNode preI = sortHead;
ListNode i = sortHead.next;
while(i != null && node.val > i.val){
preI = i;
i = i.next;
}
ListNode next = node.next;
preI.next = node;
node.next = i;
node = next;
}
return sortHead.next;
}
}
19. 刪除連結串列的倒數第 N 個結點
難度中等1199收藏分享切換為英文接收動態反饋
給你一個連結串列,刪除連結串列的倒數第 n
個結點,並且返回連結串列的頭結點。
**進階:**你能嘗試使用一趟掃描實現嗎?
示例 1:
輸入:head = [1,2,3,4,5], n = 2
輸出:[1,2,3,5]
示例 2:
輸入:head = [1], n = 1
輸出:[]
示例 3:
輸入:head = [1,2], n = 1
輸出:[1]
題解
遍歷
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
int sum = 0;
ListNode node = head;
while(node != null){
node = node.next;
sum ++;
}
int idx = sum - n + 1;
int i = 1;
ListNode firstNode = new ListNode();
firstNode.next = head;
ListNode pre = firstNode;
node = firstNode.next;
while(idx != i){
i ++;
pre = node;
node = node.next;
}
pre.next = node.next;
return firstNode.next;
}
}
回溯
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode firstNode = new ListNode();
firstNode.next = head;
func(firstNode ,n);
return firstNode.next;
}
int func(ListNode head , int n){
if(head.next == null){
return 1;
}
int res = func(head.next ,n);
if(res == n ){
head.next = head.next.next;
}
return res + 1;
}
}