LeetCode 1 : Linked List
阿新 • • 發佈:2018-03-15
val add AC help tails 是否 rand 右移 題解
分組
328. Odd Even Linked List
序號為奇數的在前,偶數的在後,每一半相對順序不變。
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
if(!head) return NULL;
int index = 1;
ListNode pseudoHeadOfNewList = ListNode(0);
ListNode pseudoHeadOfOldList = ListNode(0);
pseudoHeadOfOldList.next = head;
ListNode *pn = &pseudoHeadOfNewList;
ListNode *prePo = &pseudoHeadOfOldList;
ListNode *po = pseudoHeadOfOldList.next;
ListNode *next = NULL;
while (po) {
next = po->next;
if(index & 1) {
pn = pn->next = po;
prePo->next = po->next;
} else {
prePo = po;
}
po = next;
++index;
}
pn->next = pseudoHeadOfOldList.next;
return pseudoHeadOfNewList.next;
}
};
725. Split Linked List in Parts
將鏈表分為大小差不超1的k組。
class Solution {
public:
int listLength(ListNode *head) {
int cnt = 0;
for(ListNode *p = head; p; p = p->next) {
++cnt;
}
return cnt;
}
vector<ListNode*> splitListToParts(ListNode* root, int k) {
vector<ListNode*> ans;
if(k <= 0) return ans;
int length = listLength(root);
int lengthOfPart = length / k;
int mod = length % k;
ListNode *p = root;
for(; k && p; --k) {
ans.push_back(p);
for(int i = lengthOfPart-(mod <= 0); i > 0; --i)
p = p->next;
ListNode *next = p->next;
p->next = NULL;
p = next;
--mod;
}
for(; k; --k)
ans.push_back(NULL);
return ans;
}
};
86. Partition List
將鏈表分為小於x的部分和大於等於x的部分,
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
if(!head || !head->next) return head;
ListNode pseudoHeadOfNewList = ListNode(0);
ListNode *pNew = &pseudoHeadOfNewList;
ListNode pseudoHeadOfOldList = ListNode(0);
pseudoHeadOfOldList.next = head;
ListNode *preOld = &pseudoHeadOfOldList;
for(ListNode *pOld = head, *next = NULL; pOld; pOld = next) {
next = pOld->next;
if(pOld->val < x) {
preOld->next = pOld->next;
pNew = pNew->next = pOld;
} else {
preOld = pOld;
}
}
pNew->next = pseudoHeadOfOldList.next;
return pseudoHeadOfNewList.next;
}
};
刪除
237. Delete Node in a Linked List
給指向一個鏈表節點的指針,刪除該節點。將後序的元素向前復制一位解決。
class Solution {
public:
void deleteNode(ListNode* node) {
if(!node) return;
ListNode *pre = NULL;
ListNode *p = node;
while(p->next) {
p->val = p->next->val;
pre = p;
p = p->next;
}
delete p;
pre->next = NULL;
}
};
83. Remove Duplicates from Sorted List
刪除重復元素,每個元素僅保留一份。
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
for(ListNode *p = head; p; p = p->next) {
while (p->next && p->val == p->next->val) {
ListNode *toDeleteNode = p->next;
p->next = p->next->next;
delete toDeleteNode;
}
}
return head;
}
};
82. Remove Duplicates from Sorted List II
刪除重復元素,僅保留沒有重復的元素。
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(!head || !head->next)
return head;
ListNode pseudoHead = ListNode(0);
pseudoHead.next = head;
ListNode *pre = &pseudoHead;
ListNode *p = head;
while(p && p->next) {
if(p->val != p->next->val) {
pre = p;
p = p->next;
} else {
int val = p->val;
while(p && p->val == val) {
pre->next = p->next;
delete p;
p = pre->next;
}
}
}
return pseudoHead.next;
}
};
203. Remove Linked List Elements
刪除指定值的元素。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
if(!head) return NULL;
ListNode pseudoHead = ListNode(0);
pseudoHead.next = head;
ListNode *pre = &pseudoHead;
ListNode *p = pseudoHead.next;
ListNode *next = NULL;
while(p) {
next = p->next;
if(p->val == val) {
pre->next = p->next;
delete p;
} else {
pre = p;
}
p = next;
}
return pseudoHead.next;
}
};
雙指針
19. Remove Nth Node From End of List
刪除倒數第n個節點,快指針先走n個節點,慢指針再開始走,當p2指向NULL時,慢指針指向需要刪的元素。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(!head) return NULL;
ListNode pseudoHead = ListNode(0);
pseudoHead.next = head;
ListNode *preP1 = &pseudoHead;
ListNode *p1 = head, *p2 = head;
for(int i = 0; i < n; ++i)
p2 = p2->next;
while(p2) {
preP1 = p1;
p1 = p1->next;
p2 = p2->next;
}
preP1->next = p1->next;
delete p1;
return pseudoHead.next;
}
};
141. Linked List Cycle
判斷一個鏈表是否有環。
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode *p1 = head, *p2 = head;
while(p2 && p2->next) {
p1 = p1->next;
p2 = p2->next->next;
if(p1 == p2) return true;
}
return false;
}
};
142. Linked List Cycle II
判斷一個鏈表是否有環,若有返回環的起點,否則返回NULL。
leetcode題解 problem 142 Linked List Cycle II
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *p1 = head;
ListNode *p2 = head;
while(p2 && p2->next) {
p1 = p1->next;
p2 = p2->next->next;
if(p1 == p2) {
ListNode *p = head;
while(p != p1) {
p = p->next;
p1 = p1->next;
}
return p;
}
}
return NULL;
}
};
逆序
206. Reverse Linked List
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(!head) return NULL;
ListNode *p = head;
ListNode *pre = NULL;
ListNode *next = NULL;
while(p) {
next = p->next;
p->next = pre;
pre = p;
p = next;
}
return pre;
}
};
92. Reverse Linked List II
將鏈表的第m個到第n個節點倒序。
class Solution {
public:
// 倒序從head開始的n個節點,返回新的頭節點
ListNode* reverseNodes(ListNode *head, int n) {
if(!head) return head;
ListNode *p = head;
ListNode *pre = NULL;
ListNode *next = NULL;
for(int i = 0; i < n; ++i) {
next = p->next;
p->next = pre;
pre = p;
p = next;
}
head->next = p; // 只是多加這一行,和參數n
return pre;
}
ListNode* reverseBetween(ListNode* head, int m, int n) {
if(!head || !head->next || m >= n)
return head;
ListNode pseudoHead = ListNode(0);
pseudoHead.next = head;
ListNode *pre = &pseudoHead;
for(int i = 1; i < m; ++i)
pre = pre->next;
pre->next = reverseNodes(pre->next, n-m+1);
return pseudoHead.next;
}
};
25. Reverse Nodes in k-Group
將鏈表中的元素每k個一組倒序。
class Solution {
public:
int listLength(ListNode *head) {
int cnt = 0;
for(ListNode *p = head; p; p = p->next)
++cnt;
return cnt;
}
ListNode* reverseNodes(ListNode *head, int n) {
if(!head) return head;
ListNode *p = head;
ListNode *pre = NULL;
ListNode *next = NULL;
for(int i = 0; i < n; ++i) {
next = p->next;
p->next = pre;
pre = p;
p = next;
}
head->next = p;
return pre;
}
ListNode* reverseKGroup(ListNode* head, int k) {
int length = listLength(head);
if(length < k) return head;
ListNode dummy(0);
dummy.next = head;
ListNode *pre = &dummy;
for(int i = 0; i + k <= length; i += k) {
pre->next = reverseNodes(pre->next, k);
for(int j = k; j > 0 && pre; --j)
pre = pre->next;
}
return dummy.next;
}
};
234. Palindrome Linked List
判斷鏈表是否是回文的,將後一半逆序後,和前一半比較。
class Solution {
public:
ListNode* reverse(ListNode *head) {
if(!head) return NULL;
ListNode *p = head;
ListNode *pre = NULL;
ListNode *next = NULL;
while(p) {
next = p->next;
p->next = pre;
pre = p;
p = next;
}
return pre;
}
bool isPalindrome(ListNode* head) {
if (!head || !head->next)
return true;
int cnt = 0;
bool ret = true;
ListNode *prep1, *p1, *p2, *beforeRightHalf, *afterReverse;
p1 = p2 = head;
beforeRightHalf = afterReverse = prep1 = NULL;
while(p2 && p2->next) {
prep1= p1;
p1 = p1->next;
p2 = p2->next->next;
cnt += 2;
}
if(p2) ++cnt;
beforeRightHalf = (cnt & 1) ? p1 : prep1;
afterReverse = reverse(beforeRightHalf->next);
p1 = head, p2 = afterReverse;
while(p2) {
if(p1->val != p2->val) {
ret = false;
break;
}
p1 = p1->next;
p2 = p2->next;
}
beforeRightHalf->next = reverse(afterReverse);
return ret;
}
};
143. Reorder List
給鏈表 L: L0→L1→…→Ln-1→Ln,
返回形式 : L0→Ln→L1→Ln-1→L2→Ln-2→…
比如:{1,2,3,4} 返回 {1,4,2,3}
將後一半逆序後,和前一半組合。
class Solution {
public:
ListNode* reverse(ListNode *head) {
if(!head) return head;
ListNode *p = head;
ListNode *pre = NULL;
ListNode *next = NULL;
while(p) {
next = p->next;
p->next = pre;
pre = p;
p = next;
}
return pre;
}
ListNode *beforeCenter(ListNode *head) {
ListNode *pre = NULL, *p1 = head, *p2 = head;
while(p2 && p2->next) {
pre = p1;
p1 = p1->next;
p2 = p2->next->next;
}
return pre;
}
void reorderList(ListNode* head) {
if(!head || !head->next) return;
ListNode *beforeMid = beforeCenter(head);
beforeMid->next = reverse(beforeMid->next);
ListNode *left = head;
ListNode *right = beforeMid->next;
beforeMid->next = NULL;
ListNode dummy(0);
dummy.next = head;
ListNode *p = &dummy;
ListNode *p1 = left;
ListNode *p2 = right;
while(p1 && p2) {
ListNode *next1 = p1->next;
ListNode *next2 = p2->next;
p = p->next = p1;
p = p->next = p2;
p1 = next1;
p2 = next2;
}
p->next = p2;
}
};
排序
147. Insertion Sort List
插入排序。
class Solution {
public:
ListNode* insertionSortList(ListNode* head) {
if(!head || !head->next) return head;
ListNode pseudoHead = ListNode(0);
pseudoHead.next = head;
ListNode *pre = &pseudoHead;
for(ListNode *p = head, *next = NULL; p; p = next) {
next = p->next;
if(pre != &pseudoHead && p->val < pre->val) {
pre->next = p->next;
ListNode *q = &pseudoHead;
while(q->next && q->next->val <= p->val)
q = q->next;
p->next = q->next;
q->next = p;
} else {
pre = p;
}
}
return pseudoHead.next;
}
};
21. Merge Two Sorted Lists
合並兩個有序的鏈表。
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode pseudoHead(0);
ListNode *p = &pseudoHead;
ListNode *p1 = l1;
ListNode *p2 = l2;
while(p1 && p2) {
if(p1->val < p2->val) {
p = p->next = p1;
p1 = p1->next;
} else {
p = p->next = p2;
p2 = p2->next;
}
}
p->next = p1 ? p1 : p2;
return pseudoHead.next;
}
};
23. Merge k Sorted Lists
合並k個有序鏈表,分治解決。
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
return mergeKListsHelper(lists.begin(), lists.size());
}
ListNode* mergeKListsHelper(vector<ListNode*>::iterator it, int k) {
if(k <= 0) {
return NULL;
} else if(k == 1) {
return *it;
} else if(k == 2) {
return merge(it[0], it[1]);
} else {
int h = k >> 1;
ListNode *leftHalf = mergeKListsHelper(it, h);
ListNode *rightHalf = mergeKListsHelper(it+h, k-h);
return merge(leftHalf, rightHalf);
}
}
ListNode* merge(ListNode *la, ListNode *lb) {
ListNode dummyHead(0);
ListNode *p = &dummyHead;
ListNode *pa = la;
ListNode *pb = lb;
while(pa && pb) {
if(pa->val <= pb->val) {
p = p->next = pa;
pa = pa->next;
} else {
p = p->next = pb;
pb = pb->next;
}
}
p->next = pa ? pa : pb;
return dummyHead.next;
}
};
148. Sort List
以O(nlgn)排序鏈表,這裏使用歸並排序,快速排序見:單鏈表的快速排序
class Solution {
public:
ListNode* beforeCenter(ListNode *head) {
ListNode *preP1 = NULL, *p1 = head, *p2 = head;
while(p2 && p2->next) {
preP1 = p1;
p1 = p1->next;
p2 = p2->next->next;
}
return preP1;
}
ListNode* merge(ListNode *left, ListNode *right) {
ListNode dummy = ListNode(0);
ListNode *p = &dummy;
ListNode *p1 = left;
ListNode *p2 = right;
while(p1 && p2) {
if(p1->val <= p2->val) {
p = p->next = p1;
p1 = p1->next;
} else {
p = p->next = p2;
p2 = p2->next;
}
}
p->next = p1 ? p1 : p2;
return dummy.next;
}
ListNode* sortList(ListNode* head) {
if(!head || !head->next)
return head;
ListNode *mid = beforeCenter(head);
ListNode *right = mid->next;
mid->next = NULL;
ListNode *left = sortList(head);
right = sortList(right);
return merge(left, right);
}
};
其他
24. Swap Nodes in Pairs
交換相鄰元素。
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(!head || !head->next) return head;
ListNode pseudoHead = ListNode(0);
pseudoHead.next = head;
ListNode *pre = &pseudoHead;
ListNode *p = pseudoHead.next;
ListNode *next1 = NULL;
ListNode *next2 = NULL;
while(p && p->next) {
next1 = p->next;
next2 = p->next->next;
pre->next = next1;
next1->next = p;
p->next = next2;
pre = p;
p = next2;
}
return pseudoHead.next;
}
};
109. Convert Sorted List to Binary Search Tree
將一個鏈表轉換成二叉樹。
class Solution {
public:
TreeNode* sortedListToBST(ListNode* head) {
return sortedListToBSTHelper(head, NULL);
}
private:
ListNode* listCenter(ListNode *head, ListNode *tail) {
if(!head || !head->next) return head;
ListNode *p1 = head, *p2 = head;
while(p2 != tail && p2->next != tail) {
p1 = p1->next;
p2 = p2->next->next;
}
return p1;
}
TreeNode* sortedListToBSTHelper(ListNode* head, ListNode *tail) {
if(head == tail) return NULL;
ListNode *mid = listCenter(head, tail);
TreeNode *p = new TreeNode(mid->val);
p->left = sortedListToBSTHelper(head, mid);
p->right = sortedListToBSTHelper(mid->next, tail);
return p;
}
};
138. Copy List with Random Pointer
復制帶有隨機指針的鏈表
class Solution {
public:
RandomListNode *copyRandomList(RandomListNode *head) {
if(!head) return head;
RandomListNode *p = head;
RandomListNode *next = NULL;
while(p) {
next = p->next;
RandomListNode *newNode = new RandomListNode(p->label);
newNode->next = p->next;
p->next = newNode;
p = next;
}
for(p = head; p; p = p->next->next) {
if(p->random)
p->next->random = p->random->next;
}
RandomListNode dummyHeadOfNewList(0);
RandomListNode *pNew = &dummyHeadOfNewList;
for(p = head; p; p = next) {
next = p->next->next;
pNew = pNew->next = p->next;
p->next = next;
}
return dummyHeadOfNewList.next;
}
};
61. Rotate List
循環右移鏈表k位。
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if(!head || !head->next)
return head;
int len = 1;
ListNode *oldLast = head;
while(oldLast && oldLast->next) {
++len;
oldLast = oldLast->next;
}
k %= len;
if(!k) return head;
ListNode *newHead = head;
ListNode *newLast = NULL; // pre new head
for(int i = len - k; i > 0; --i) {
newLast = newHead;
newHead = newHead->next;
}
oldLast->next = head;
newLast->next = NULL;
return newHead;
}
};
2. Add Two Numbers
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
char up = 0;
ListNode head(0), *p = &head;
ListNode *p1 = l1, *p2 = l2;
for(; p1 && p2; p1=p1->next, p2=p2->next) {
p = p->next = new ListNode(p1->val + p2->val + up);
up = p->val / 10;
p->val %= 10;
}
for(ListNode *p3 = p1 ? p1 : p2; p3; p3 = p3->next) {
p = p->next = new ListNode(p3->val + up);
up = p->val / 10;
p->val %= 10;
}
if(up) {
p = p->next = new ListNode(up);
}
return head.next;
}
};
445. Add Two Numbers II
class Solution {
public:
ListNode *reverse(ListNode *head) {
if(!head) return NULL;
ListNode *pre = NULL;
for(ListNode *p = head, *next = NULL; p; p = next) {
next = p->next;
p->next = pre;
pre = p;
}
return pre;
}
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *newHead1 = reverse(l1);
ListNode *newHead2 = reverse(l2);
ListNode pseudoHead = ListNode(0);
int up = 0;
ListNode *p1 = newHead1, *p2 = newHead2, *p = &pseudoHead;
while(p1 && p2) {
p = p->next = new ListNode(up + p1->val + p2->val);
up = p->val / 10;
p->val %= 10;
p1 = p1->next;
p2 = p2->next;
}
p1 = p1 ? p1 : p2;
while(p1) {
p = p->next = new ListNode(up + p1->val);
up = p->val / 10;
p->val %= 10;
p1 = p1->next;
}
if(up) {
p->next = new ListNode(up);
}
reverse(newHead1);
reverse(newHead2);
return reverse(pseudoHead.next);
}
};
LeetCode 1 : Linked List