演算法學習記錄十二(C++)--->連結串列題目集合
題目一
輸入一個連結串列,輸出該連結串列中倒數第k個結點。
分析
最普通的方法就是,先統計單連結串列中節點的個數,然後再找到n-k個節點,時間複雜度為O(n)
另一個思路就是雙指標,,先讓前面的指標走向正想第k個節點,這樣前後兩個節點的差距就是k-1,
之後前面兩個指標一起走,前面的指標走到最後一個節點的時候,後走的那個指標就是倒數第k個節點
程式碼
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(k==0 || pListHead == NULL){ // 這裡k的計數是從1開始的,若k為0或連結串列為空返回NULL
return NULL;
}
ListNode *pHead = pListHead;
ListNode *pBehind = pListHead;
while(k>1 && pHead != NULL){ // 前面的指標先走到正向第k個結點
pHead = pHead->next;
k--;
}
if(k>1||pHead==NULL){ // 結點個數小於k,返回NULL
return NULL;
}
while(pHead->next!=NULL){// 前後兩個指標一起向前走,直到前面的指標指向最後一個結點
pHead=pHead->next;
pBehind=pBehind->next;
}
return pBehind; // 後面那個指標所指節點就是倒數第k個
}
};
題目二
輸入一個連結串列,反轉連結串列後,輸出連結串列的所有元素
分析
1.非遞迴 三指標
pPrev -> pNode -> pNext;
我們先儲存原來的下一個指標位置,要不然翻轉後其next會指向pPrev,從而丟失指向pNext的指標
接著反轉指標,
然後下面指標同步後移,以便處理後面的指標
2.遞迴
核心程式碼,當前節點的兩次next取值指向自己,就是翻轉
pHead->next->next=pHead;
pHead->next=NULL;
程式碼 非遞迴
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
/*
next = head.next;//首先記錄當前節點的下一個節點,(儲存起來)
head.next = pre;//讓當前節點指向前一個節點,因為要反序嘛
pre = head;//讓前一個節點值,取代當前的節點值。因為要繼續向下走
head = next;//讓下一個節點,取代當前節點。同樣是向下走,為下一次迴圈做準備
*/
/*
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
ListNode *pNode = pHead;
ListNode *pPre = NULL;
ListNode *pNext = NULL;
while(pNode != NULL){
pNext = pNode->next;
pNode->next = pPre;
pPre = pNode;
pNode = pNext;
}
return pPre;
}
};
*/
程式碼 遞迴
class Solution {
public:
// 這個遞迴非常贊 舉個例子
// 例如 1->2->3-NULL 這個連結串列
// 當pHead為1的時候傳進去 內部會呼叫ReverseList(2)繼續傳遞,而且每次呼叫都會觸發一下兩行程式碼
// pHead->next->next=pHead;pHead->next=NULL;
// 當你呼叫ReverseList(3)的時候就直接返回3這個節點,不呼叫那兩行程式碼,然後進行迴歸
// pHead->next->next=pHead; 這句話的意思是,例如節點2呼叫的時候,pHead是2,遞迴最後一層ReverseList(3)返回3
// 然後->next就是對應的3節點,再next就是反序替換節點 兩個next指向當前節點,就是反轉一次了
// pHead->next=NULL;這句話的意思就是最後一個節點的next為Null結束
ListNode* ReverseList(ListNode* pHead) {
//如果連結串列為空或者連結串列中只有一個元素
if(pHead==NULL||pHead->next==NULL) return pHead;
//先反轉後面的連結串列,走到連結串列的末端結點
ListNode* pReverseNode=ReverseList(pHead->next);
//再將當前節點設定為後面節點的後續節點
pHead->next->next=pHead;
pHead->next=NULL;
return pReverseNode;
}
};
題目三
已知兩個單連結串列pHead1 和pHead2 各自有序,把它們合併成一個連結串列依然有序
分析
這個類似歸併排序。尤其注意兩個連結串列都為空,和其中一個為空時的情況。只需要O(1)的空間。時間複雜度為O(max(len1, len2))。分別用遞迴和常規指標進行操作
常規操作
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
/*
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1 == NULL){
return pHead2;
}
if(pHead2 == NULL){
return pHead1;
}
ListNode *orginalHeader = NULL;
ListNode *currentNode = NULL;
while(pHead1 && pHead2){
if(pHead1->val < pHead2->val){
if(orginalHeader == NULL){ // 該判斷為了找出對應的頭結點儲存到orginalHeader
orginalHeader = currentNode = pHead1;
}
else{
currentNode->next = pHead1; // 取下連結串列的當前節點放到臨時連結串列的next節點
currentNode = currentNode->next; // 臨時節點往後移動一位
}
pHead1 = pHead1->next; // 每次比較之後都要把比較小的連結串列往後移動一個
}
else{
if(orginalHeader == NULL){
orginalHeader = currentNode = pHead2;
}
else{
currentNode->next = pHead2;
currentNode = currentNode->next;
}
pHead2 = pHead2->next;
}
}
// 一個為空的時候結束遍歷而且直接拼接到後面
if(pHead1 == NULL){
currentNode->next = pHead2;
}
else{
currentNode->next = pHead1;
}
return orginalHeader;
}
};
*/
遞迴拼接
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(pHead1 == NULL){
return pHead2;
}
if(pHead2 == NULL){
return pHead1;
}
ListNode *tempNode = NULL;
if(pHead1->val < pHead2->val){
pHead1->next = Merge(pHead1->next,pHead2);
return pHead1; // 一開始的頭結點大小決定返回head1還是head2
}else{
pHead2->next = Merge(pHead1,pHead2->next);
return pHead2;
}
}
};
相關文章
- 【C++】“反轉連結串列”相關的題目C++
- 演算法學習記錄三(C++)--->從尾到頭列印連結串列每個節點的值演算法C++
- 連結串列學習(6)
- 單連結串列學習
- 資料結構學習(C++)——迴圈連結串列 (轉)資料結構C++
- 資料結構學習(C++)——雙向連結串列 (轉)資料結構C++
- 筆記--連結串列演算法筆記演算法
- 演算法學習之路|連結串列元素分類演算法
- C#集合----連結串列C#
- javascript 學習記錄 -- 程式設計題集合JavaScript程式設計
- 連結串列面試題(十二)---判斷兩個都不帶環的連結串列是否相交面試題
- 資料結構與演算法學習-連結串列上資料結構演算法
- 資料結構與演算法學習-連結串列下資料結構演算法
- LVGL雙向連結串列學習筆記筆記
- 單連結串列學習(一)
- [總結]學習目錄
- 【資料結構與演算法學習】線性表(順序表、單連結串列、雙向連結串列、迴圈連結串列)資料結構演算法
- leetcode題目解析(js)--連結串列LeetCodeJS
- 演算法學習記錄十三(C++)--->10年微軟面試題樹的子結構演算法C++微軟面試題
- 演算法題中的連結串列演算法
- Java集合學習記錄——IteratorJava
- 資料結構學習--連結串列資料結構
- C++建立連結串列C++
- c++學習記錄C++
- 連結串列面試題(二)---連結串列逆序(連結串列反轉)面試題
- 安卓學習筆記---開篇(目錄結構)安卓筆記
- (連結串列)連結串列的排序問題排序
- 《演算法筆記》6. 連結串列相關面試題總結演算法筆記面試題
- 資料結構練習題(順序表和單連結串列)C++資料結構C++
- 輕鬆搞定面試中的連結串列題目面試
- 【小白學演算法】5.連結串列(linked list)、連結串列的新增演算法
- 資料結構與演算法——連結串列 Linked List(單連結串列、雙向連結串列、單向環形連結串列-Josephu 問題)資料結構演算法
- 演算法問題總結-連結串列相關演算法
- 演算法-連結串列演算法
- Laravel8學習筆記01 - 目錄結構Laravel筆記
- Symfony2學習筆記之目錄結構筆記
- [演算法總結] 17 題搞定 BAT 面試——連結串列題演算法BAT面試
- C++ STL list連結串列C++