LeetCode 單鏈表專題 (一)
阿新 • • 發佈:2019-02-23
listnode ptr 時間 lis class toc ref nod link
目錄
- LeetCode 單鏈表專題 <c++>
- \([2]\) Add Two Numbers
- \([92]\) Reverse Linked List II
- \([86]\) Partition List
- \([82]\) Remove Duplicates from Sorted List II
- \([61]\) Rotate List
- \([19]\) Remove Nth Node From End of List
LeetCode 單鏈表專題 <c++>
\([2]\) Add Two Numbers
模擬,註意最後判斷進位是否為1。
時間復雜度 \(O(n)\)
class Solution { public: ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) { ListNode ans(-1); int carry = 0; auto p1 = l1, p2 = l2; auto p = &ans; while (p1 != nullptr || p2 != nullptr) { int val1, val2; if (p1 == nullptr) { val1 = 0; } else { val1 = p1->val; p1 = p1->next; } if (p2 == nullptr) { val2 = 0; } else { val2 = p2->val; p2 = p2->next; } int sum = (val1 + val2 + carry) % 10; carry = (val1 + val2 + carry) / 10; p = p->next = new ListNode(sum); } if(carry) p->next = new ListNode(carry); return ans.next; } };
\([92]\) Reverse Linked List II
給定鏈表,翻轉第m個結點到第n個結點。
從第m+1個結點開始,在第m-1個結點之後的位置用頭插法插入新結點,可以避免使用棧。
時間復雜度 \(O(n)\)
class Solution { public: ListNode* reverseBetween(ListNode* head, int m, int n) { ListNode res(-1); auto p = head, p_res = &res; for(int i = 1; i <= m-1; i++){ p_res = p_res->next = new ListNode(p->val); // new list next node p = p->next; // origin list next node } auto prev = p_res; p_res = p_res->next = new ListNode(p->val); auto last = p_res; p = p->next; for(int i = m+1; i <= n; i++){ prev->next = new ListNode(p->val); prev->next->next = p_res; p_res = prev->next; p = p->next; } last->next = p; return res.next; } };
\([86]\) Partition List
鏈表拼接。
時間復雜度 \(O(n)\)
(c++)搞清楚了實體用.
,指針用->
調用屬性和方法。
(c++)new 構造方法(參數)
返回的是同類型指針。
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
ListNode dummy_l(-1);
ListNode dummy_r(-1);
auto dummy_l_p = &dummy_l, dummy_r_p = &dummy_r;
for(auto p = head; p; p = p->next){
if(p->val<x){
dummy_l_p = dummy_l_p->next = p;
}
else {
dummy_r_p = dummy_r_p->next = p;
}
}
dummy_l_p->next = dummy_r.next;
dummy_r_p->next = nullptr;
return dummy_l.next;
}
};
\([82]\) Remove Duplicates from Sorted List II
如果有元素重復出現,刪掉該元素及其復制。
時間復雜度 \(O(n)\)
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode dummy(-1);
auto prev = &dummy;
bool flag = false;
for(auto p = head; p; p = p->next){
while(p->next!=nullptr && p->next->val == p->val){
p->next = p->next->next;
flag = true;
}
if(flag){
flag = false;
prev->next = p->next;
}
else prev = prev->next = p;
}
return dummy.next;
}
};
\([61]\) Rotate List
先遍歷求出長度length
。k可能大於等於length
,所以對length
取模。從length-k
處斷開原鏈表,斷開處為新鏈表頭結點,原頭結點接到原尾結點後面。
時間復雜度 \(O(n)\)
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if(head == nullptr) return head;
int length = 1;
auto cur = head;
for(; cur->next; cur = cur->next) length++;
k = k % length;
if(k == 0) return head;
ListNode dummy(-1);
dummy.next = head;
auto cut = &dummy;
for(int i = 0; i<length - k; i++) cut = cut->next;
dummy.next = cut->next;
cur->next = head;
cut->next = nullptr; // 記得斷開,避免形成環,會TLE。
return dummy.next;
}
};
\([19]\) Remove Nth Node From End of List
刪掉鏈表倒數第n個結點,要求只遍歷一遍。
兩個指針p,q。一個先走n步,然後兩個一起走。
時間復雜度 \(O(n)\)
/**
* Status: Accepted
* Runtime: 12 ms
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode dummy(-1);
dummy.next = head;
auto p = &dummy, q = &dummy;
int cnt = 0;
while(p!=nullptr) {
if(cnt>n) q = q->next;
p = p->next;
cnt++;
}
q->next = q->next->next;
return dummy.next;
}
};
這份代碼跑了12ms。因為循環中有判斷語句。
下面是優化後的代碼
/**
* Status: Accepted
* Runtime: 8 ms
*/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode dummy(-1);
dummy.next = head;
auto p = &dummy, q = &dummy;
for(int i = 0; i<=n; i++) p = p->next;
while(p!=nullptr) {
q = q->next;
p = p->next;
}
auto tmp = q->next;
q->next = q->next->next;
delete tmp;
return dummy.next;
}
};
LeetCode 單鏈表專題 (一)