(十二)連結串列(C++實現)
阿新 • • 發佈:2021-12-23
演算法與資料結構刷題系列之連結串列,僅記錄個人刷題總結記錄,方便複習。
反轉連結串列
leetcode 206:https://leetcode-cn.com/problems/reverse-linked-list/
nowcoder NC76:https://www.nowcoder.com/practice/75e878df47f24fdc9dc3e400ec6058ca?tpId=188&&tqId=38547
1.問題描述
給定單鏈表的頭節點head,反轉連結串列。
2.輸入輸出
- Input:head = [1, 2, 3, 4, 5]
- Output:[5, 4, 3, 2, 1]
3.演算法分析
- 迭代法:1)實現儲存前一個節點;2)通過當前指標遍歷連結串列;3)儲存後一個節點;4)將當前節點的next指標改為指向前一個節點。5)最後返回新的頭引用——前一個節點。
- 時間複雜度:O(n)
- 空間複雜度:O(1)
- 遞迴法:
- 遞迴終止條件:連結串列只剩最後一個節點或者已經為空(最後一個節點就是反轉後的頭節點)
- 處理:讓當前節點的下一格節點的next指標指向當前節點,且當前節點的next指向NULL,實現連結串列尾部開始的區域性反轉
- 時間複雜度:O(n)
- 空間複雜度:O(n)
4.程式設計實現
#include <iostream> using namespace std; struct ListNode { int val; ListNode *next; ListNode() : val(0), next(nullptr) {} ListNode(int x) : val(x), next(nullptr) {} ListNode(int x, ListNode *next) : val(x), next(next) {} }; class Solution { public: ListNode* reverseList1(ListNode* head) { // 迭代法 1->2->3->Ø變成Ø->3->2-1 ListNode* prev = nullptr; ListNode* curr = head; while (curr) { ListNode* nxt = curr->next; curr->next = prev; prev = curr; curr = nxt; } return prev; } ListNode* reverseList2(ListNode* head){ // 遞迴法 1->2->3->Ø變成Ø->3->2-1 if (!head || !head->next) return head; ListNode *newHead = reverseList2(head->next); head->next->next = head; head->next = nullptr; return newHead; } }; int main() { Solution sol; ListNode* head = new ListNode(), *now = head; int val; getchar(); while (cin >> val) { now->next = new ListNode(val); now = now->next; if (cin.get() == ']') break; } now = sol.reverseList1(head->next); cout << "["; while (now) { cout << now->val; if (now->next) { cout << ","; } else { cout << "]"; } now = now->next; } return 0; }
k個一組翻轉連結串列
Leetcode:https://leetcode-cn.com/problems/reverse-nodes-in-k-group/
1.問題描述
給定一個連結串列,每k個節點一組進行翻轉,返回翻轉後的連結串列。(k是一個正整數,它的值小於或等於連結串列的長度,如果節點總數不是k的整數倍,將最後剩餘的節點保持原有順序)
2.輸入輸出
- Input:head=[1, 2, 3, 4, 5],k=2
- Output:[2,1,4,3,5]
3.演算法分析
先計算以下長度,再根據需要翻轉的段數進行遍歷。
4.程式設計實現
// #include <bits/stdc++.h> #include <iostream> using namespace std; struct ListNode{ int val; ListNode *next; ListNode():val(0), next(nullptr){} ListNode(int x):val(x), next(nullptr){} ListNode(int x, ListNode *next):val(x), next(next){} }; class Solution{ public: ListNode* reverseKGroup(ListNode *head, int k) { ListNode *dummy = new ListNode(0), *prev = dummy, *curr = head, *nextNode; dummy->next = head; int length = 0; while (head) { length++; head = head->next; } for (int i = 0; i < length / k; i++) { for (int j = 0; j < k-1; j++) { nextNode = curr->next; curr->next = nextNode->next; nextNode->next = prev->next; prev->next = nextNode; } prev = curr; curr = prev->next; } return dummy->next; } }; int main(){ Solution sol; ListNode *head = new ListNode(0), *fake = head; int val, k; char ch; getchar(); while (cin >> val) { fake->next = new ListNode(val); fake = fake->next; if (cin.get() == ']') break; } cin >> k; ListNode *newNode = sol.reverseKGroup(head->next, k); while (newNode) { cout << newNode->val; if (newNode->next) { cout << ","; } else { cout << ""; } newNode = newNode->next; } return 0; }
合併兩個有序連結串列
Leetcode:https://leetcode-cn.com/problems/merge-two-sorted-lists/
1.問題描述
將兩個升序連結串列合併成一個新的升序連結串列並返回。新連結串列是通過拼接給定的兩個連結串列的所有節點組成的。
2.輸入輸出
- Input:l1=[1, 2, 4],l2=[1, 3, 4]
- Output:[1, 1, 2, 3, 4, 4]
3.演算法分析
迭代法:當l1和l2都不是空連結串列時,判斷l1和l2哪一個連結串列的頭節點的值更小,將較小值得節點新增到結果裡,當一個節點被新增到結果裡之後,將對應連結串列的節點後移一位。
- 時間複雜度:O(n+m)
- 空間複雜度:O(1)
4.程式設計實現
#include <iostream>
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
class Solution {
public:
// 1->2->3->Ø變成Ø->3->2-1
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* preHead = new ListNode(-1);
ListNode* prev = preHead;
while (l1 && l2 ) {
if (l1->val < l2->val) {
prev->next = l1;
l1 = l1->next;
} else {
prev->next = l2;
l2 = l2->next;
}
prev = prev->next;
}
// 合併後l1和l2最多還有一個還未被合併完,直接將連結串列末尾指向未合併完的連結串列即可。
prev->next = l1 == nullptr? l2 : l1;
return preHead->next;
}
};
int main() {
Solution sol;
ListNode* l1 = new ListNode(1);
l1->next = new ListNode(2);
l1->next->next = new ListNode(4);
ListNode* l2 = new ListNode(1);
l2->next = new ListNode(3);
l2->next->next = new ListNode(4);
ListNode* newHead = sol.mergeTwoLists(l1, l2);
while (newHead) {
cout << newHead->val << " ";
newHead = newHead->next;
}
return 0;
}
本文為博主原創文章,未經博主允許禁止轉載,需轉載請註明出處,歡迎指正!