These ten problems are difficult—there is a lot to remember.
21 Merge Two Sorted Lists
Merge two linked lists; handle empty lists carefully.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 class Solution { public : ListNode* mergeTwoLists (ListNode* l1, ListNode* l2) { ListNode node (INT_MIN) ; ListNode *head = &node; while (l1&&l2) { if (l1->val < l2->val) { head->next = l1; l1 = l1->next; } else { head->next = l2; l2 = l2->next; } head = head->next; } head->next = l1 ? l1 : l2; return node.next; } };
22 Generate Parentheses
Generate valid parentheses strings of length $2 * n$.
Recursion makes this problem easy to understand, but it can also be written iteratively; here is a dynamic-programming solution . Let $dp[x]$ represent every valid string with $x$ pairs of parentheses; derive $x+1$ by combining earlier strings whose pair counts add up to $x$.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 void gen (vector<string>&res, int le, int ri, string cur) { if (le == 0 && ri == 0 ) { res.push_back (cur); return ; } if (le > 0 ) { gen (res, le - 1 , ri, cur + '(' ); } if (ri > le) { gen (res, le, ri - 1 , cur + ')' ); } } class Solution { public : vector<string> generateParenthesis (int n) { vector<string>res; gen (res, n, n, "" ); return res; } };
23 Merge k Sorted Lists
Merge $k$ linked lists.
Use the merge-sort idea.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 ListNode* mergeTwoLists (ListNode* l1, ListNode* l2) { ListNode node (INT_MIN) ; ListNode *head = &node; while (l1&&l2) { if (l1->val < l2->val) { head->next = l1; l1 = l1->next; } else { head->next = l2; l2 = l2->next; } head = head->next; } head->next = l1 ? l1 : l2; return node.next; } class Solution { public : ListNode* mergeKLists (vector<ListNode*>& lists) { int sz = lists.size (); if (sz == 0 ) { return NULL ; } else if (sz == 1 ) { return lists[0 ]; } vector<ListNode*>left (lists.begin (), lists.begin () + sz / 2 ); vector<ListNode*>right (lists.begin () + sz / 2 , lists.end ()); return mergeTwoLists (mergeKLists (left), mergeKLists (right)); } };
24 Swap Nodes in Pairs
Swap adjacent nodes in a linked list.
This is a simpler version of reversing each following group of $k$ nodes. (There can never be too many linked-list problems.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Solution { public : ListNode* swapPairs (ListNode* head) { ListNode no = ListNode (0 ); no.next = head; ListNode *pre=&no; while (head&&head->next) { ListNode *tmp=head->next->next; pre->next=head->next; head->next->next=head; head->next=tmp; pre = head; head = tmp; } return no.next; } };
********25 Reverse Nodes in k-Group
Rotate each adjacent group of $k$ nodes in a linked list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class Solution {public : ListNode* reverseKGroup (ListNode* head, int k) { if (head == NULL || k == 1 )return head; ListNode *res = new ListNode (-1 ); res->next = head; ListNode *pre = res; ListNode *cur = res; ListNode *nxt = res; int num = 0 ; while (cur->next) { cur = cur->next; num++; } while (num >= k) { cur = pre->next; nxt = cur->next; for (int i = 1 ; i < k; i++) { cur->next = nxt->next; nxt->next = pre->next; pre->next = nxt; nxt = cur->next; } num -= k; pre = cur; } return res->next; } };
27 Remove Element
Remove elements equal to val from an array without allocating extra space.
My approach was still much more complicated; this solution runs in 0 ms.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Solution { public : int removeElement (vector<int >& nums, int val) { int sz = nums.size (); if (sz == 0 ) { return 0 ; } int idx = sz - 1 ; for (int i = sz - 1 ; i >= 0 ; i--) { if (nums[i] == val) { swap (nums[i], nums[idx]); idx--; sz--; } } nums.resize (sz); return sz; } };
28 Implement strStr()
Return the index at which a substring occurs in the original string.
Plain KMP.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 void getnext (string x, vector<int >&nxt) { int k = -1 ; int len = x.length (); nxt[0 ] = -1 ; for (int i = 0 ; i < len; ) { if (k == -1 || x[k] == x[i]) { k++; i++; nxt[i] = k; } else { k = nxt[k]; } } } class Solution { public : int strStr (string haystack, string needle) { int len1 = haystack.length (); int len2 = needle.length (); vector<int >nxt (needle.length () + 1 , 0 ); getnext (needle, nxt); int i = 0 , j = 0 ; while (i < len1 && j < len2) { if (j == -1 || haystack[i] == needle[j]) { i++; j++; } else { j = nxt[j]; } } if (j == len2) { return i - len2; } else { return -1 ; } } };
29 Divide Two Integers
Divide two integers without using multiplication, division, or modulo.
Use bit shifts and reduce the problem to binary operations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 long long cal (long long dividend, long long divisor) { long long res = 0 ; long long d = abs (dividend); long long t = abs (divisor); while (d >= t) { long long cnt = 0 ; while ((t << cnt) <= d) { cnt++; } cnt--; d -= (t << cnt); res += (1LL << cnt); } int s1 = dividend < 0 ; int s2 = divisor < 0 ; if (s1^s2) { return -res; } else { return res; } } class Solution { public : int divide (int dividend, int divisor) { int s1 = dividend < 0 ; int s2 = divisor < 0 ; if (s1^s2) { if (abs (dividend) == INT_MIN&&abs (divisor) == 1 ) return INT_MIN; } else { if (abs (dividend) == INT_MIN&&abs (divisor) == 1 ) return INT_MAX; } long long res = cal (dividend, divisor); if (res > INT_MAX || res < INT_MIN) { return INT_MAX; } else { return res; } } };
30 Substring with Concatenation of All Words
Given a set of strings and a source string, return every position where all set strings occur exactly once.
Keep a map of string counts, then inspect every position for missing or excessive occurrences.
This took far too long. This post uses a trie; I will improve this after reading it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 class Solution { public : vector<int > findSubstring (string s, vector<string>& words) { map<string, int >num; int sz = words.size (); int len = 0 ; vector<int >res; if (sz == 0 )return res; int one = words[0 ].length (); for (int i = 0 ; i < sz; i++) { num[words[i]]++; len += words[i].length (); } int lens = s.length (); for (int i = 0 ; i + len <= lens; i++) { map<string, int >tmp; int f = 0 ; for (int k = 0 ; k < sz; k++) { string t = s.substr (i + k*one, one); if (num.find (t) != num.end ()) { tmp[t]++; if (tmp[t] > num[t]) { f = 1 ; break ; } } else { f = 1 ; break ; } } if (f == 0 ) { res.push_back (i); } } return res; } };