25-k個一組翻轉連結串列 203-移除連結串列元素 206-反轉一個連結串列
阿新 • • 發佈:2020-11-18
題目:
給你一個連結串列,每k個節點一組進行翻轉,請你返回翻轉後的連結串列。
k是一個正整數,它的值小於或等於連結串列的長度。
如果節點總數不是k的整數倍,那麼請將最後剩餘的節點保持原有順序。
示例:
給你這個連結串列:1->2->3->4->5
當k= 2 時,應當返回: 2->1->4->3->5
當k= 3 時,應當返回: 3->2->1->4->5
說明:
你的演算法只能使用常數的額外空間。
你不能只是單純的改變節點內部的值,而是需要實際進行節點交換。
解答:看懂了,但是自己寫有問題,自己寫的太多的判斷了,直接看解答
//指定head,然後在k段內翻轉,k段內都不為nullptr //head-開始的頭結點 //tail-要翻轉的最後一個節點 //返回:翻轉後的頭-尾節點 pair<ListNode*, ListNode*> reverseK(ListNode* head, ListNode* tail) { ListNode* pre = tail->next;//使用尾部的下一個元素作為頭 ListNode* cur = head; ListNode* next = nullptr; while (pre != tail) { next = cur->next; cur->next = pre; pre = cur; cur = next; } return{ tail, head }; } ListNode* reverseKGroup(ListNode* head, int k) { ListNode* dummy = new ListNode(0); dummy->next = head; ListNode* pre = dummy; while (head != nullptr) { ListNode* tail = pre;for (int i = 0; i < k; i++) { tail = tail->next; if (tail == nullptr)//如果連結串列長度小於k,則直接返回該連結串列 return dummy->next; } ListNode* next = tail->next;//k段連結串列的下一個節點 pair<ListNode*, ListNode*> result = reverseK(head, tail); head = result.first; tail = result.second; //把k段的連結串列重新接回原連結串列 pre->next = head; tail->next = next; //更新pre head,用於下一段k的反轉; pre = tail; head = tail->next; } return dummy->next; }
相關題目:
203-移除連結串列元素
206-反轉一個連結串列
題目-206
反轉一個單鏈表。
示例:
輸入: 1->2->3->4->5->NULL
輸出: 5->4->3->2->1->NULL
進階:
你可以迭代或遞迴地反轉連結串列。你能否用兩種方法解決這道題?
解答:
程式碼一:迭代方法:
if (head == nullptr) return head; if (head->next == nullptr)//如果連結串列就一個節點,則直接返回 return head; ListNode* pre = nullptr; ListNode* cur = head; ListNode* next = nullptr; while (cur != nullptr) { next = cur->next; cur->next = pre; pre = cur; cur = next; } return pre;
}
方法二:遞迴:https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-by-leetcode/
題目-203
刪除連結串列中等於給定值val的所有節點。
示例:
輸入: 1->2->6->3->4->5->6, val = 6 輸出: 1->2->3->4->5
解答:
自己寫的程式碼:
//連結串列中可能有多個符合的元素 ListNode* removeElements(ListNode* head, int val) { if (head == nullptr) return head; while (head!= nullptr && head->val == val) head = head->next; ListNode dummy; dummy.next = head; ListNode* tmp = &dummy; ListNode* pre = &dummy; while (tmp != nullptr) { tmp = tmp->next; while (tmp != nullptr && tmp->val == val) { tmp = tmp->next; } pre->next = tmp; pre = tmp; } return head; }
問題:上面的程式碼沒有釋放移除節點,需要delete,修改如下:
//上面的函式沒有刪除移除的節點, ListNode* removeElements2(ListNode* head, int val) { if (head == nullptr) return head; ListNode* toBeDelete = nullptr; while (head != nullptr && head->val == val) { toBeDelete = head; head = head->next; if (toBeDelete != nullptr) delete toBeDelete; } ListNode dummy; dummy.next = head; ListNode* tmp = &dummy; ListNode* pre = &dummy; while (tmp != nullptr) { tmp = tmp->next; while (tmp != nullptr && tmp->val == val) { toBeDelete = tmp; tmp = tmp->next; if (toBeDelete != nullptr) delete toBeDelete; } pre->next = tmp; pre = tmp; } return head; }
解答中的程式碼很簡潔,如下,使用了一個哨兵sentinel,而且根據當前的cur的val是否為目標值對pre進行不同的處理,邏輯比自己寫的簡單:
ListNode* removeElements3(ListNode* head, int val) { ListNode* sentinel = new ListNode(0); sentinel->next = head; ListNode* pre = sentinel; ListNode* cur = head; ListNode* toBeDelete = nullptr; while (cur != nullptr) { if (cur->val == val) { pre->next = cur->next; toBeDelete = cur; } else pre = cur; cur = cur->next; if (toBeDelete != nullptr) { delete toBeDelete; toBeDelete = nullptr; } } ListNode* ret = sentinel->next; delete sentinel; return ret; }