|
19 | 19 | 17. [Subarray Sum Equals K](#Subarray-Sum-Equals-K) Medium |
20 | 20 | 18. [Find the Kth largest item](#Find-the-Kth-largest-item) Medium |
21 | 21 | 19. [Count Duplicates](#Count-Duplicates) Medium |
22 | | -20. [3 Sum](#3-Ssum) |
23 | | -21. [Majority Item](Majority Item) Medium |
| 22 | +20. [3 Sum](#3-Ssum) Medium |
| 23 | +21. [Majority Item](#Majority-Item) Medium |
24 | 24 |
|
25 | 25 | ## Matrix |
26 | 26 | 1. [Diagnose Tranverse](#Diagnose-Tranverse) Medium |
|
56 | 56 | 1. [Valid Anagram](#Valid-Anagram) Easy |
57 | 57 | 2. [Integer to English Words](#Integer-to-English-Words) Hard |
58 | 58 | 3. [Insert five](#Insert-five) Easy |
| 59 | +4. [Partition Labels](#Partition-Labels) Medium |
| 60 | +5. [Longest Palindromic Substring](#Longest-Palindromic-Substring) Medium |
| 61 | +6. [Word Break](#Word-Break) Medium |
59 | 62 |
|
60 | 63 | ## Bits Manipulation |
61 | 64 | 1. [Is Power of Four](#Is-Power-of-Four) Easy |
|
66 | 69 | ## Data Structure |
67 | 70 | 1. [LRU cache](#LRU-cache) Hard |
68 | 71 | 2. [LFU cache](#LFU-cache) Hard |
| 72 | +3. [Min Stack](#Min-Stack) Easy |
69 | 73 |
|
70 | 74 | ## OS flavor |
71 | 75 | 1. [Task Scheduler](#task-scheduler) Medium |
|
89 | 93 | 13. [Container With Most Water](#Container-With-Most-Water) Medium |
90 | 94 | 14. [Move Zeroes](#Move-Zeroes) Medium |
91 | 95 | 15. [Symmetric Tree](#Symmetric-Tree) Easy |
| 96 | +16. [Subtree of Another Tree](#Subtree-of-Another-Tree) Medium |
92 | 97 |
|
93 | 98 | ## Implementation |
94 | 99 |
|
@@ -1363,7 +1368,7 @@ private: |
1363 | 1368 |
|
1364 | 1369 | string tens[10] = {"", "Ten ", "Twenty ", "Thirty ", "Forty ", "Fifty ", "Sixty ", "Seventy ", "Eighty ", "Ninety "}; |
1365 | 1370 |
|
1366 | | - pair<int, string> units[4] = {{1000*1000*1000, "Billion "}, {1000*1000, "Million "}, {1000, "Thousand "}, {100, "Hundred "}}; |
| 1371 | + pair<int, string> units[4] = { {1000*1000*1000, "Billion "}, {1000*1000, "Million "}, {1000, "Thousand "}, {100, "Hundred "}}; |
1367 | 1372 | }; |
1368 | 1373 | ``` |
1369 | 1374 | ### **Reorder list** |
@@ -3138,4 +3143,263 @@ public: |
3138 | 3143 | return ans; |
3139 | 3144 | } |
3140 | 3145 | }; |
| 3146 | +``` |
| 3147 | + |
| 3148 | +### Partition Labels |
| 3149 | +***Big O:*** O(N) speed, O(1) space |
| 3150 | +``` |
| 3151 | +Tips: |
| 3152 | +
|
| 3153 | +First record all the last occurance indexes of each letter. Than go through the array again and partition. |
| 3154 | +``` |
| 3155 | +```c++ |
| 3156 | +class Solution { |
| 3157 | +public: |
| 3158 | + vector<int> partitionLabels(string S) { |
| 3159 | + int letters[26] = {0}; |
| 3160 | + int n = S.size(); |
| 3161 | + vector<int> ans; |
| 3162 | + |
| 3163 | + if (n == 0) |
| 3164 | + return ans; |
| 3165 | + |
| 3166 | + for (int i = 0; i < n; i++) { |
| 3167 | + // record the last occurance index of the letter |
| 3168 | + letters[S[i]-'a'] = i; |
| 3169 | + } |
| 3170 | + |
| 3171 | + int p_size = letters[S[0]-'a']; |
| 3172 | + for (int i = 0; i < n; i++) { |
| 3173 | + // record the last occurance index of the letter |
| 3174 | + if (i <= p_size) { |
| 3175 | + p_size = max(letters[S[i]-'a'], p_size); |
| 3176 | + } else { |
| 3177 | + ans.push_back(p_size); |
| 3178 | + p_size = letters[S[i]-'a']; |
| 3179 | + } |
| 3180 | + } |
| 3181 | + ans.push_back(p_size); |
| 3182 | + |
| 3183 | + for (int i = ans.size()-1; i >= 1; i--) { |
| 3184 | + ans[i] = ans[i] - ans[i-1]; |
| 3185 | + } |
| 3186 | + ans[0] += 1; |
| 3187 | + |
| 3188 | + return ans; |
| 3189 | + } |
| 3190 | +}; |
| 3191 | +``` |
| 3192 | +
|
| 3193 | +### Longest Palindromic Substring |
| 3194 | +***Big O:*** O(N^2 or N^3) speed, O(1) space |
| 3195 | +``` |
| 3196 | +Tips: |
| 3197 | + |
| 3198 | +DP method: |
| 3199 | + |
| 3200 | +To improve over the brute force solution, we first observe how we can avoid unnecessary re-computation while validating palindromes. Consider the case "ababa". If we already knew that "bab" is a palindrome, it is obvious that "ababa" must be a palindrome since the two left and right end letters are the same. |
| 3201 | + |
| 3202 | +p(i, j) if substring Si...Sj is panlidrome. |
| 3203 | + |
| 3204 | +Therefore: |
| 3205 | + |
| 3206 | +p(i, j) = (p(i+1, j-1) && Si == Sj) |
| 3207 | + |
| 3208 | +Base cases: |
| 3209 | + |
| 3210 | +p(i, i) = true |
| 3211 | +p(i, i+1) = (Si == S_(i+1)) |
| 3212 | +``` |
| 3213 | +```c++ |
| 3214 | +//Brutal Force |
| 3215 | +class Solution { |
| 3216 | +public: |
| 3217 | + bool isPanlidrome(string &s, int st, int end) { |
| 3218 | + while (st < end) { |
| 3219 | + if (s[st++] != s[end--]) |
| 3220 | + return false; |
| 3221 | + } |
| 3222 | + |
| 3223 | + return true; |
| 3224 | + } |
| 3225 | + |
| 3226 | + string longestPalindrome(string s) { |
| 3227 | + int n = s.size(); |
| 3228 | + string ans = ""; |
| 3229 | + |
| 3230 | + for (int i = 0; i < n; i++) { |
| 3231 | + int st = i, end = n-1; |
| 3232 | + while (st <= end) { |
| 3233 | + // if it is guanranteed that ans has bigger size, go to the next index |
| 3234 | + if ((end - st + 1) <= ans.size()) { |
| 3235 | + break; |
| 3236 | + } else if (s[st] == s[end]){ |
| 3237 | + if (isPanlidrome(s, st, end)) { |
| 3238 | + ans = s.substr(st, end-st+1); |
| 3239 | + } |
| 3240 | + } else { |
| 3241 | + end --; |
| 3242 | + } |
| 3243 | + } |
| 3244 | + } |
| 3245 | + |
| 3246 | + return ans; |
| 3247 | + } |
| 3248 | +}; |
| 3249 | +
|
| 3250 | +// DP solution |
| 3251 | +string longestPalindrome(string s) { |
| 3252 | + const int n = s.size(); |
| 3253 | + if(n==0) return ""; |
| 3254 | + int dp[n][n], maxlen =1 , left=0;// maxlen = 1 when only one word |
| 3255 | + memset(dp,0,n*n*sizeof(int)); |
| 3256 | + for(int i=0;i<n;++i){ |
| 3257 | + dp[i][i] = 1; |
| 3258 | + for(int j=0;j<i;++j){ |
| 3259 | + dp[j][i] = (s[j]==s[i] && (i-j< 2 || dp[j+1][i-1])); |
| 3260 | + if(dp[j][i] && maxlen < i-j+1){ |
| 3261 | + left = j; |
| 3262 | + maxlen = i-j+1; |
| 3263 | + } |
| 3264 | + } |
| 3265 | + } |
| 3266 | + return s.substr(left,maxlen); |
| 3267 | +} |
| 3268 | +``` |
| 3269 | + |
| 3270 | +### Subtree of Another Tree |
| 3271 | +***Big O:*** O(M*N) speed, O(1) space |
| 3272 | +``` |
| 3273 | +Tips: |
| 3274 | +
|
| 3275 | +Recursion |
| 3276 | +``` |
| 3277 | +```c++ |
| 3278 | +class Solution { |
| 3279 | +public: |
| 3280 | + bool helper(TreeNode* s, TreeNode* t) { |
| 3281 | + if (s == nullptr && t == nullptr) |
| 3282 | + return true; |
| 3283 | + |
| 3284 | + if ((s == nullptr && t != nullptr) || (s != nullptr && t == nullptr)) |
| 3285 | + return false; |
| 3286 | + |
| 3287 | + return s->val == t->val && helper(s->left, t->left) && helper(s->right, t->right); |
| 3288 | + } |
| 3289 | + |
| 3290 | + bool isSubtree(TreeNode* s, TreeNode* t) { |
| 3291 | + if ((s == nullptr && t != nullptr) || (s != nullptr && t == nullptr)) |
| 3292 | + return false; |
| 3293 | + |
| 3294 | + if (helper(s, t)) |
| 3295 | + return true; |
| 3296 | + |
| 3297 | + return isSubtree(s->left, t) || isSubtree(s->right, t); |
| 3298 | + } |
| 3299 | +}; |
| 3300 | +``` |
| 3301 | +
|
| 3302 | +### Min Stack |
| 3303 | +***Big O:*** O(M*N) speed, O(1) space |
| 3304 | +``` |
| 3305 | +Tips: |
| 3306 | + |
| 3307 | +In the stack, store the pair of <new_val, current_min>. |
| 3308 | +``` |
| 3309 | +```c++ |
| 3310 | +class MinStack { |
| 3311 | + stack<pair<int, int>> data; |
| 3312 | + |
| 3313 | +public: |
| 3314 | + /** initialize your data structure here. */ |
| 3315 | + MinStack() { |
| 3316 | + |
| 3317 | + } |
| 3318 | + |
| 3319 | + void push(int val) { |
| 3320 | + int min_val = (val < getMin()) ? val : getMin(); |
| 3321 | + data.push(make_pair(val, min_val)); |
| 3322 | + } |
| 3323 | + |
| 3324 | + void pop() { |
| 3325 | + if (!data.empty()) |
| 3326 | + data.pop(); |
| 3327 | + } |
| 3328 | + |
| 3329 | + int top() { |
| 3330 | + pair<int, int> item = data.top(); |
| 3331 | + return item.first; |
| 3332 | + } |
| 3333 | + |
| 3334 | + int getMin() { |
| 3335 | + if (data.empty()) |
| 3336 | + return INT_MAX; |
| 3337 | + |
| 3338 | + pair<int, int> item = data.top(); |
| 3339 | + return item.second; |
| 3340 | + } |
| 3341 | +}; |
| 3342 | +``` |
| 3343 | + |
| 3344 | +### Word Break |
| 3345 | +***Big O:*** O(2^n or n^3) speed, O(1) space |
| 3346 | +``` |
| 3347 | +Tips: |
| 3348 | +
|
| 3349 | +To optimize the brutal force method, we add memorizations: |
| 3350 | +
|
| 3351 | +In the previous approach we can see that many subproblems were redundant, i.e we were calling the recursive function multiple times for a particular string. To avoid this we can use memoization method, where an array memomemo is used to store the result of the subproblems. Now, when the function is called again for a particular string, value will be fetched and returned using the memomemo array, if its value has been already evaluated. |
| 3352 | +
|
| 3353 | +With memoization many redundant subproblems are avoided and recursion tree is pruned and thus it reduces the time complexity by a large factor. |
| 3354 | +``` |
| 3355 | +```c++ |
| 3356 | +// Brutal Force |
| 3357 | +class Solution { |
| 3358 | +public: |
| 3359 | + bool wordBreak(string s, vector<string>& wordDict) { |
| 3360 | + set<string> word_set(wordDict.begin(), wordDict.end()); |
| 3361 | + return wordBreakRecur(s, word_set, 0); |
| 3362 | + } |
| 3363 | + |
| 3364 | + bool wordBreakRecur(string& s, set<string>& word_set, int start) { |
| 3365 | + if (start == s.length()) { |
| 3366 | + return true; |
| 3367 | + } |
| 3368 | + for (int end = start + 1; end <= s.length(); end++) { |
| 3369 | + if (word_set.find(s.substr(start, end - start)) != word_set.end() and |
| 3370 | + wordBreakRecur(s, word_set, end)) { |
| 3371 | + return true; |
| 3372 | + } |
| 3373 | + } |
| 3374 | + return false; |
| 3375 | + } |
| 3376 | +}; |
| 3377 | + |
| 3378 | +// Recursion with memo |
| 3379 | +class Solution { |
| 3380 | +public: |
| 3381 | + bool wordBreak(string s, vector<string>& wordDict) { |
| 3382 | + set<string> word_set(wordDict.begin(), wordDict.end()); |
| 3383 | + // In the memo table, -1 stands for the state not yet reached, |
| 3384 | + // 0 for false and 1 for true |
| 3385 | + vector<int> memo(s.length(), -1); |
| 3386 | + return wordBreakMemo(s, word_set, 0, memo); |
| 3387 | + } |
| 3388 | + |
| 3389 | + bool wordBreakMemo(string& s, set<string>& word_set, int start, vector<int>& memo) { |
| 3390 | + if (start == s.length()) { |
| 3391 | + return true; |
| 3392 | + } |
| 3393 | + if (memo[start] != -1) { |
| 3394 | + return memo[start]; |
| 3395 | + } |
| 3396 | + for (int end = start + 1; end <= s.length(); end++) { |
| 3397 | + if (word_set.find(s.substr(start, end - start)) != word_set.end() and |
| 3398 | + wordBreakMemo(s, word_set, end, memo)) { |
| 3399 | + return memo[start] = true; |
| 3400 | + } |
| 3401 | + } |
| 3402 | + return memo[start] = false; |
| 3403 | + } |
| 3404 | +}; |
3141 | 3405 | ``` |
0 commit comments