diff options
| author | 3gg <3gg@shellblade.net> | 2025-02-05 18:36:31 -0800 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2025-02-05 18:36:31 -0800 |
| commit | 4689e4e80b479be25f7557d05818f5caa723aafa (patch) | |
| tree | 4df25811fe2a9a15b401375178da6537f4b6063f | |
35 files changed, 1139 insertions, 0 deletions
diff --git a/top-interview-questions/easy/array/01_remove_duplicates_from_sorted_array.cc b/top-interview-questions/easy/array/01_remove_duplicates_from_sorted_array.cc new file mode 100644 index 0000000..8f5224b --- /dev/null +++ b/top-interview-questions/easy/array/01_remove_duplicates_from_sorted_array.cc | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | int removeDuplicates(vector<int>& nums) { | ||
| 4 | size_t i = nums.size() > 0 ? 1 : 0; | ||
| 5 | for (size_t j = 1; j < nums.size(); ++j) { | ||
| 6 | if (nums[j] != nums[i-1]) { | ||
| 7 | nums[i++] = nums[j]; | ||
| 8 | } | ||
| 9 | } | ||
| 10 | nums.resize(i); | ||
| 11 | return i; | ||
| 12 | } | ||
| 13 | }; | ||
diff --git a/top-interview-questions/easy/array/02_best_time_to_buy_and_sell_stock_2.cc b/top-interview-questions/easy/array/02_best_time_to_buy_and_sell_stock_2.cc new file mode 100644 index 0000000..abc4aa9 --- /dev/null +++ b/top-interview-questions/easy/array/02_best_time_to_buy_and_sell_stock_2.cc | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | int maxProfit(vector<int>& prices) { | ||
| 4 | int profit = 0; | ||
| 5 | int buy = -1; | ||
| 6 | int sell = -1; | ||
| 7 | for (size_t day = 0; day < prices.size(); ++day) { | ||
| 8 | if ((sell == -1) && | ||
| 9 | ((buy == -1) || (prices[day] < buy))) { | ||
| 10 | buy = prices[day]; | ||
| 11 | } else if ((sell == -1) || (prices[day] > sell)) { | ||
| 12 | sell = prices[day]; | ||
| 13 | } else { | ||
| 14 | profit += sell - buy; | ||
| 15 | buy = prices[day]; | ||
| 16 | sell = -1; | ||
| 17 | } | ||
| 18 | } | ||
| 19 | if (buy < sell) { | ||
| 20 | profit += sell - buy; | ||
| 21 | } | ||
| 22 | return profit; | ||
| 23 | } | ||
| 24 | }; | ||
diff --git a/top-interview-questions/easy/array/03_rotate_array.cc b/top-interview-questions/easy/array/03_rotate_array.cc new file mode 100644 index 0000000..19f66dd --- /dev/null +++ b/top-interview-questions/easy/array/03_rotate_array.cc | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | // Works, but it's slow. | ||
| 4 | /*int gcd(int a, int b) { | ||
| 5 | if (a == 0) return b; | ||
| 6 | if (b == 0) return a; | ||
| 7 | if (a == b) return a; | ||
| 8 | if (a > b) return gcd(a-b, b); | ||
| 9 | else return gcd(a, b-a); | ||
| 10 | }*/ | ||
| 11 | |||
| 12 | // Much faster than the above implementation. | ||
| 13 | int gcd(int a, int b) { | ||
| 14 | if (b == 0) return a; | ||
| 15 | else return gcd(b, a%b); | ||
| 16 | } | ||
| 17 | |||
| 18 | void rotate(vector<int>& nums, int k) { | ||
| 19 | const size_t N = nums.size(); | ||
| 20 | if ((N <= 1) || (k == 0)) { | ||
| 21 | return; | ||
| 22 | } | ||
| 23 | // Original algorithm only works for (N,k) coprime. | ||
| 24 | // Break the cycles when we complete a loop around the array. | ||
| 25 | const int gcdNk = gcd(N,k); | ||
| 26 | const int steps = (gcdNk != 1) ? (N / gcdNk) : N; | ||
| 27 | int start = -1; | ||
| 28 | for (size_t n = 0; n < N; n += steps) { | ||
| 29 | ++start; | ||
| 30 | int i = start; | ||
| 31 | int i_val = nums[i]; | ||
| 32 | for (size_t s = 0; s < steps; ++s) { | ||
| 33 | const int next = (i+k) % N; | ||
| 34 | std::swap(i_val, nums[next]); | ||
| 35 | i = next; | ||
| 36 | } | ||
| 37 | } | ||
| 38 | } | ||
| 39 | }; | ||
diff --git a/top-interview-questions/easy/array/04_contains_duplicate.cc b/top-interview-questions/easy/array/04_contains_duplicate.cc new file mode 100644 index 0000000..d40d1e4 --- /dev/null +++ b/top-interview-questions/easy/array/04_contains_duplicate.cc | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | bool containsDuplicate(vector<int>& nums) { | ||
| 4 | std::sort(nums.begin(), nums.end()); | ||
| 5 | |||
| 6 | for (size_t i = 1; i < nums.size(); ++i) { | ||
| 7 | if (nums[i-1] == nums[i]) { | ||
| 8 | return true; | ||
| 9 | } | ||
| 10 | } | ||
| 11 | |||
| 12 | return false; | ||
| 13 | } | ||
| 14 | }; | ||
diff --git a/top-interview-questions/easy/array/05_single_number.cc b/top-interview-questions/easy/array/05_single_number.cc new file mode 100644 index 0000000..ad55712 --- /dev/null +++ b/top-interview-questions/easy/array/05_single_number.cc | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | int singleNumber(vector<int>& nums) { | ||
| 4 | int x = 0; | ||
| 5 | for (int n : nums) { | ||
| 6 | x = x ^ n; | ||
| 7 | } | ||
| 8 | return x; | ||
| 9 | } | ||
| 10 | }; | ||
diff --git a/top-interview-questions/easy/array/06_intersection_of_two_arrays_II.cc b/top-interview-questions/easy/array/06_intersection_of_two_arrays_II.cc new file mode 100644 index 0000000..0921be8 --- /dev/null +++ b/top-interview-questions/easy/array/06_intersection_of_two_arrays_II.cc | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | vector<int> intersect(vector<int>& nums1, vector<int>& nums2) { | ||
| 4 | std::sort(nums1.begin(), nums1.end()); | ||
| 5 | std::sort(nums2.begin(), nums2.end()); | ||
| 6 | |||
| 7 | std::vector<int> result; | ||
| 8 | result.reserve(std::max(nums1.size(), nums2.size())); | ||
| 9 | |||
| 10 | size_t i = 0; | ||
| 11 | size_t j = 0; | ||
| 12 | |||
| 13 | while ((i < nums1.size()) && (j < nums2.size())) { | ||
| 14 | if (nums1[i] == nums2[j]) { | ||
| 15 | result.push_back(nums1[i]); | ||
| 16 | ++i; | ||
| 17 | ++j; | ||
| 18 | } else if (nums1[i] < nums2[j]) { | ||
| 19 | ++i; | ||
| 20 | } else { | ||
| 21 | ++j; | ||
| 22 | } | ||
| 23 | } | ||
| 24 | |||
| 25 | return result; | ||
| 26 | } | ||
| 27 | }; | ||
diff --git a/top-interview-questions/easy/array/07_plus_one.cc b/top-interview-questions/easy/array/07_plus_one.cc new file mode 100644 index 0000000..05c7b21 --- /dev/null +++ b/top-interview-questions/easy/array/07_plus_one.cc | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | vector<int> plusOne(vector<int>& digits) { | ||
| 4 | int carry = 1; | ||
| 5 | |||
| 6 | for (int i = digits.size()-1; (i >= 0) && (carry == 1); --i) { | ||
| 7 | const int sum = digits[i] + carry; | ||
| 8 | digits[i] = sum % 10; | ||
| 9 | carry = (sum >= 10) ? 1 : 0; | ||
| 10 | } | ||
| 11 | |||
| 12 | if (carry == 1) { // Overflow. | ||
| 13 | digits.resize(digits.size() + 1); | ||
| 14 | |||
| 15 | // Shift right. | ||
| 16 | for (size_t i = digits.size()-1; i > 0; --i) { | ||
| 17 | digits[i] = digits[i-1]; | ||
| 18 | } | ||
| 19 | |||
| 20 | digits[0] = 1; | ||
| 21 | } | ||
| 22 | |||
| 23 | return digits; | ||
| 24 | } | ||
| 25 | }; | ||
diff --git a/top-interview-questions/easy/array/08_move_zeroes.cc b/top-interview-questions/easy/array/08_move_zeroes.cc new file mode 100644 index 0000000..074944c --- /dev/null +++ b/top-interview-questions/easy/array/08_move_zeroes.cc | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | void moveZeroes(vector<int>& nums) { | ||
| 4 | // Invariant: left subset of array satisfies requirement. | ||
| 5 | bool sorted = false; | ||
| 6 | for (size_t i = 0; (i < nums.size()) && !sorted; ++i) { | ||
| 7 | if (nums[i] == 0) { | ||
| 8 | // Look for j>i with which to swap this 0. | ||
| 9 | // If not found, then we're done. | ||
| 10 | bool found = false; | ||
| 11 | for (size_t j = i+1; j < nums.size(); ++j) { | ||
| 12 | if (nums[j] != 0) { | ||
| 13 | nums[i] = nums[j]; | ||
| 14 | nums[j] = 0; | ||
| 15 | found = true; | ||
| 16 | break; | ||
| 17 | } | ||
| 18 | } | ||
| 19 | sorted = !found; | ||
| 20 | } | ||
| 21 | } | ||
| 22 | } | ||
| 23 | }; | ||
diff --git a/top-interview-questions/easy/array/09_two_sum.cc b/top-interview-questions/easy/array/09_two_sum.cc new file mode 100644 index 0000000..72d2014 --- /dev/null +++ b/top-interview-questions/easy/array/09_two_sum.cc | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | vector<int> twoSum(vector<int>& nums, int target) { | ||
| 4 | // When you find, e.g., 2, map (2 -> idx 0) for the event | ||
| 5 | // in which you find the 7. | ||
| 6 | std::vector<int> pair(2); | ||
| 7 | std::unordered_map<int, int> val_to_idx; | ||
| 8 | |||
| 9 | for (size_t i = 0; i < nums.size(); ++i) { | ||
| 10 | const int other = target - nums[i]; | ||
| 11 | const auto other_idx = val_to_idx.find(other); | ||
| 12 | |||
| 13 | if (other_idx != val_to_idx.end()) { | ||
| 14 | pair[0] = i; | ||
| 15 | pair[1] = other_idx->second; | ||
| 16 | break; | ||
| 17 | } | ||
| 18 | |||
| 19 | val_to_idx[nums[i]] = i; | ||
| 20 | } | ||
| 21 | |||
| 22 | return pair; | ||
| 23 | } | ||
| 24 | }; | ||
diff --git a/top-interview-questions/easy/design/01_shuffle_an_array.cc b/top-interview-questions/easy/design/01_shuffle_an_array.cc new file mode 100644 index 0000000..5c40d60 --- /dev/null +++ b/top-interview-questions/easy/design/01_shuffle_an_array.cc | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | Solution(vector<int>& nums) | ||
| 4 | : m_original(nums) {} | ||
| 5 | |||
| 6 | vector<int> reset() { | ||
| 7 | return m_original; | ||
| 8 | } | ||
| 9 | |||
| 10 | vector<int> shuffle() { | ||
| 11 | std::vector<int> shuffled = m_original; | ||
| 12 | for (size_t i = 0; i < shuffled.size(); ++i) { | ||
| 13 | const size_t j = random() % shuffled.size(); | ||
| 14 | std::swap(shuffled[i], shuffled[j]); | ||
| 15 | } | ||
| 16 | return shuffled; | ||
| 17 | } | ||
| 18 | |||
| 19 | private: | ||
| 20 | size_t random() { | ||
| 21 | uint64_t x = m_random; | ||
| 22 | |||
| 23 | // xorshift64 | ||
| 24 | x ^= x << 13; | ||
| 25 | x ^= x >> 7; | ||
| 26 | x ^= x << 17; | ||
| 27 | |||
| 28 | m_random = x; | ||
| 29 | return x; | ||
| 30 | } | ||
| 31 | |||
| 32 | std::vector<int> m_original; | ||
| 33 | std::uint64_t m_random = 16240738485554559101; | ||
| 34 | }; | ||
| 35 | |||
| 36 | /** | ||
| 37 | * Your Solution object will be instantiated and called as such: | ||
| 38 | * Solution* obj = new Solution(nums); | ||
| 39 | * vector<int> param_1 = obj->reset(); | ||
| 40 | * vector<int> param_2 = obj->shuffle(); | ||
| 41 | */ | ||
diff --git a/top-interview-questions/easy/design/02_min_stack.cc b/top-interview-questions/easy/design/02_min_stack.cc new file mode 100644 index 0000000..1bcb36a --- /dev/null +++ b/top-interview-questions/easy/design/02_min_stack.cc | |||
| @@ -0,0 +1,56 @@ | |||
| 1 | class MinStack { | ||
| 2 | public: | ||
| 3 | MinStack() {} | ||
| 4 | |||
| 5 | void push(int val) { | ||
| 6 | const int minVal = (m_minStack != nullptr) ? std::min(m_minStack->val, val) : val; | ||
| 7 | Node* top = new Node{m_stack, val}; | ||
| 8 | Node* minTop = new Node{m_minStack, minVal}; | ||
| 9 | m_stack = top; | ||
| 10 | m_minStack = minTop; | ||
| 11 | } | ||
| 12 | |||
| 13 | void pop() { | ||
| 14 | assertNonEmpty(); | ||
| 15 | Node* top = m_stack; | ||
| 16 | Node* minTop = m_minStack; | ||
| 17 | m_stack = m_stack->next; | ||
| 18 | m_minStack = m_minStack->next; | ||
| 19 | delete top; | ||
| 20 | delete minTop; | ||
| 21 | } | ||
| 22 | |||
| 23 | int top() { | ||
| 24 | assertNonEmpty(); | ||
| 25 | return m_stack->val; | ||
| 26 | } | ||
| 27 | |||
| 28 | int getMin() { | ||
| 29 | assertNonEmpty(); | ||
| 30 | return m_minStack->val; | ||
| 31 | } | ||
| 32 | |||
| 33 | private: | ||
| 34 | struct Node { | ||
| 35 | Node* next; | ||
| 36 | int val; | ||
| 37 | }; | ||
| 38 | |||
| 39 | void assertNonEmpty() const { | ||
| 40 | if (m_stack == nullptr) { | ||
| 41 | throw "empty stack"; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | Node* m_stack = nullptr; // The actual stack. | ||
| 46 | Node* m_minStack = nullptr; // Stack of mins. | ||
| 47 | }; | ||
| 48 | |||
| 49 | /** | ||
| 50 | * Your MinStack object will be instantiated and called as such: | ||
| 51 | * MinStack* obj = new MinStack(); | ||
| 52 | * obj->push(val); | ||
| 53 | * obj->pop(); | ||
| 54 | * int param_3 = obj->top(); | ||
| 55 | * int param_4 = obj->getMin(); | ||
| 56 | */ | ||
diff --git a/top-interview-questions/easy/dynamic_programming/01_climbing_stairs.cc b/top-interview-questions/easy/dynamic_programming/01_climbing_stairs.cc new file mode 100644 index 0000000..19aa6a1 --- /dev/null +++ b/top-interview-questions/easy/dynamic_programming/01_climbing_stairs.cc | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | int climbStairs(int n) { | ||
| 4 | /* | ||
| 5 | ways(n-1, n) = 1 -- one step to n | ||
| 6 | ways(n-2, n) = 1 + 1 -- 1x two-step + 2x one-step | ||
| 7 | ways( k, n) = ways(k-1, n) + ways(k-2, n) | ||
| 8 | */ | ||
| 9 | if (n == 1) return 1; | ||
| 10 | if (n == 2) return 2; | ||
| 11 | |||
| 12 | int ways_n_1 = 1; // ways(n-1, n) | ||
| 13 | int ways_n_2 = 2; // ways(n-2, n) | ||
| 14 | for (int i = n-3; i >= 0; --i) { | ||
| 15 | const int ways_n_3 = ways_n_1 + ways_n_2; | ||
| 16 | // Update | ||
| 17 | ways_n_1 = ways_n_2; | ||
| 18 | ways_n_2 = ways_n_3; | ||
| 19 | } | ||
| 20 | return ways_n_2; | ||
| 21 | } | ||
| 22 | }; | ||
diff --git a/top-interview-questions/easy/linked_list/01_delete_node_in_a_linked_list.cc b/top-interview-questions/easy/linked_list/01_delete_node_in_a_linked_list.cc new file mode 100644 index 0000000..47f9559 --- /dev/null +++ b/top-interview-questions/easy/linked_list/01_delete_node_in_a_linked_list.cc | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | /** | ||
| 2 | * Definition for singly-linked list. | ||
| 3 | * struct ListNode { | ||
| 4 | * int val; | ||
| 5 | * ListNode *next; | ||
| 6 | * ListNode(int x) : val(x), next(NULL) {} | ||
| 7 | * }; | ||
| 8 | */ | ||
| 9 | class Solution { | ||
| 10 | public: | ||
| 11 | void deleteNode(ListNode* node) { | ||
| 12 | while (node) { | ||
| 13 | if (node->next) { | ||
| 14 | node->val = node->next->val; | ||
| 15 | if (!node->next->next) { | ||
| 16 | node->next = NULL; | ||
| 17 | } | ||
| 18 | } | ||
| 19 | node = node->next; | ||
| 20 | } | ||
| 21 | } | ||
| 22 | }; | ||
diff --git a/top-interview-questions/easy/linked_list/02_remove_nth_node_from_end_of_list.cc b/top-interview-questions/easy/linked_list/02_remove_nth_node_from_end_of_list.cc new file mode 100644 index 0000000..6773f04 --- /dev/null +++ b/top-interview-questions/easy/linked_list/02_remove_nth_node_from_end_of_list.cc | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | /** | ||
| 2 | * Definition for singly-linked list. | ||
| 3 | * struct ListNode { | ||
| 4 | * int val; | ||
| 5 | * ListNode *next; | ||
| 6 | * ListNode() : val(0), next(nullptr) {} | ||
| 7 | * ListNode(int x) : val(x), next(nullptr) {} | ||
| 8 | * ListNode(int x, ListNode *next) : val(x), next(next) {} | ||
| 9 | * }; | ||
| 10 | */ | ||
| 11 | class Solution { | ||
| 12 | public: | ||
| 13 | // Return the number of elements in the list. | ||
| 14 | int removeNth(ListNode* node, int n) { | ||
| 15 | if (!node) { | ||
| 16 | return 0; | ||
| 17 | } | ||
| 18 | const int tailLength = removeNth(node->next, n); | ||
| 19 | if (tailLength == n) { | ||
| 20 | node->next = node->next->next; | ||
| 21 | } | ||
| 22 | return tailLength + 1; | ||
| 23 | } | ||
| 24 | |||
| 25 | ListNode* removeNthFromEnd(ListNode* head, int n) { | ||
| 26 | const int listLength = removeNth(head, n); | ||
| 27 | if (listLength == n) { | ||
| 28 | head = head->next; | ||
| 29 | } | ||
| 30 | return head; | ||
| 31 | } | ||
| 32 | }; | ||
diff --git a/top-interview-questions/easy/linked_list/03_reverse_linked_list.cc b/top-interview-questions/easy/linked_list/03_reverse_linked_list.cc new file mode 100644 index 0000000..d97bd33 --- /dev/null +++ b/top-interview-questions/easy/linked_list/03_reverse_linked_list.cc | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | /** | ||
| 2 | * Definition for singly-linked list. | ||
| 3 | * struct ListNode { | ||
| 4 | * int val; | ||
| 5 | * ListNode *next; | ||
| 6 | * ListNode() : val(0), next(nullptr) {} | ||
| 7 | * ListNode(int x) : val(x), next(nullptr) {} | ||
| 8 | * ListNode(int x, ListNode *next) : val(x), next(next) {} | ||
| 9 | * }; | ||
| 10 | */ | ||
| 11 | class Solution { | ||
| 12 | public: | ||
| 13 | // Reverse the list and return the head of the new list. | ||
| 14 | ListNode* reverse(ListNode* node) { | ||
| 15 | if (!node) { return nullptr; } | ||
| 16 | if (!node->next) { return node; } | ||
| 17 | ListNode* head = reverse(node->next); | ||
| 18 | node->next->next = node; | ||
| 19 | node->next = nullptr; | ||
| 20 | return head; | ||
| 21 | } | ||
| 22 | |||
| 23 | ListNode* reverseList(ListNode* head) { | ||
| 24 | return reverse(head); | ||
| 25 | } | ||
| 26 | }; | ||
diff --git a/top-interview-questions/easy/linked_list/04_merge_two_sorted_lists.cc b/top-interview-questions/easy/linked_list/04_merge_two_sorted_lists.cc new file mode 100644 index 0000000..9724ef0 --- /dev/null +++ b/top-interview-questions/easy/linked_list/04_merge_two_sorted_lists.cc | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | /** | ||
| 2 | * Definition for singly-linked list. | ||
| 3 | * struct ListNode { | ||
| 4 | * int val; | ||
| 5 | * ListNode *next; | ||
| 6 | * ListNode() : val(0), next(nullptr) {} | ||
| 7 | * ListNode(int x) : val(x), next(nullptr) {} | ||
| 8 | * ListNode(int x, ListNode *next) : val(x), next(next) {} | ||
| 9 | * }; | ||
| 10 | */ | ||
| 11 | class Solution { | ||
| 12 | public: | ||
| 13 | ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) { | ||
| 14 | ListNode* mergedHead = nullptr; | ||
| 15 | ListNode* merged = nullptr; | ||
| 16 | while (list1 && list2) { | ||
| 17 | if (list1->val <= list2->val) { | ||
| 18 | if (merged) { | ||
| 19 | merged->next = list1; | ||
| 20 | merged = merged->next; | ||
| 21 | } else { | ||
| 22 | merged = list1; | ||
| 23 | mergedHead = merged; | ||
| 24 | } | ||
| 25 | list1 = list1->next; | ||
| 26 | } else { | ||
| 27 | if (merged) { | ||
| 28 | merged->next = list2; | ||
| 29 | merged = merged->next; | ||
| 30 | } else { | ||
| 31 | merged = list2; | ||
| 32 | mergedHead = merged; | ||
| 33 | } | ||
| 34 | list2 = list2->next; | ||
| 35 | } | ||
| 36 | } | ||
| 37 | if (list1) { | ||
| 38 | if (merged) { | ||
| 39 | merged->next = list1; | ||
| 40 | } else { | ||
| 41 | mergedHead = list1; | ||
| 42 | } | ||
| 43 | } else if (list2) { | ||
| 44 | if (merged) { | ||
| 45 | merged->next = list2; | ||
| 46 | } else { | ||
| 47 | mergedHead = list2; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | return mergedHead; | ||
| 51 | } | ||
| 52 | }; | ||
diff --git a/top-interview-questions/easy/linked_list/05_palindrome_linked_list.cc b/top-interview-questions/easy/linked_list/05_palindrome_linked_list.cc new file mode 100644 index 0000000..3f42e4a --- /dev/null +++ b/top-interview-questions/easy/linked_list/05_palindrome_linked_list.cc | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /** | ||
| 2 | * Definition for singly-linked list. | ||
| 3 | * struct ListNode { | ||
| 4 | * int val; | ||
| 5 | * ListNode *next; | ||
| 6 | * ListNode() : val(0), next(nullptr) {} | ||
| 7 | * ListNode(int x) : val(x), next(nullptr) {} | ||
| 8 | * ListNode(int x, ListNode *next) : val(x), next(next) {} | ||
| 9 | * }; | ||
| 10 | */ | ||
| 11 | class Solution { | ||
| 12 | public: | ||
| 13 | // Copy the list. | ||
| 14 | ListNode* clone(const ListNode* node) { | ||
| 15 | if (!node) return nullptr; | ||
| 16 | ListNode* copy = new ListNode(); | ||
| 17 | copy->val = node->val; | ||
| 18 | if (node->next) { | ||
| 19 | copy->next = clone(node->next); | ||
| 20 | } else { | ||
| 21 | copy->next = nullptr; | ||
| 22 | } | ||
| 23 | return copy; | ||
| 24 | } | ||
| 25 | |||
| 26 | // Reverse a list and return the new of the reversed list. | ||
| 27 | ListNode* reverse(ListNode* node) { | ||
| 28 | if (!node) return nullptr; | ||
| 29 | if (!node->next) return node; | ||
| 30 | ListNode* head = reverse(node->next); | ||
| 31 | node->next->next = node; | ||
| 32 | node->next = nullptr; | ||
| 33 | return head; | ||
| 34 | } | ||
| 35 | |||
| 36 | // Compare two lists for equality. | ||
| 37 | bool eq(const ListNode* a, const LideNode* b) { | ||
| 38 | if (!a && !b) return true; | ||
| 39 | if (!a) return false; | ||
| 40 | if (!b) return false; | ||
| 41 | if (a->val != b->val) return false; | ||
| 42 | return eq(a->next, b->next); | ||
| 43 | } | ||
| 44 | |||
| 45 | bool isPalindrome(ListNode* head) { | ||
| 46 | return eq(head, reverse(clone(head))); | ||
| 47 | } | ||
| 48 | }; | ||
diff --git a/top-interview-questions/easy/linked_list/05_palindrome_linked_list_2.cc b/top-interview-questions/easy/linked_list/05_palindrome_linked_list_2.cc new file mode 100644 index 0000000..590c485 --- /dev/null +++ b/top-interview-questions/easy/linked_list/05_palindrome_linked_list_2.cc | |||
| @@ -0,0 +1,63 @@ | |||
| 1 | /** | ||
| 2 | * Definition for singly-linked list. | ||
| 3 | * struct ListNode { | ||
| 4 | * int val; | ||
| 5 | * ListNode *next; | ||
| 6 | * ListNode() : val(0), next(nullptr) {} | ||
| 7 | * ListNode(int x) : val(x), next(nullptr) {} | ||
| 8 | * ListNode(int x, ListNode *next) : val(x), next(next) {} | ||
| 9 | * }; | ||
| 10 | */ | ||
| 11 | class Solution { | ||
| 12 | public: | ||
| 13 | // Return the length of the list. | ||
| 14 | size_t length(const ListNode* node) { | ||
| 15 | if (!node) return 0; | ||
| 16 | return 1 + length(node->next); | ||
| 17 | } | ||
| 18 | |||
| 19 | // Return the nth element of the list. | ||
| 20 | const ListNode* nth(const ListNode* node, size_t n) { | ||
| 21 | if (!node) return nullptr; | ||
| 22 | if (n == 0) return node; | ||
| 23 | return nth(node->next, n-1); | ||
| 24 | } | ||
| 25 | |||
| 26 | // Reverse the list up to, and not including, the nth element. | ||
| 27 | // Return the head of the reversed list (nth-1 node). | ||
| 28 | ListNode* reverse(ListNode* node, size_t n) { | ||
| 29 | if (!node) return nullptr; | ||
| 30 | if (!node->next) return node; | ||
| 31 | if (n == 1) { | ||
| 32 | node->next = nullptr; | ||
| 33 | return node; | ||
| 34 | } | ||
| 35 | |||
| 36 | ListNode* head = reverse(node->next, n-1); | ||
| 37 | node->next->next = node; | ||
| 38 | node->next = nullptr; | ||
| 39 | return head; | ||
| 40 | } | ||
| 41 | |||
| 42 | // Compare two lists for equality. | ||
| 43 | bool eq(const ListNode* a, const ListNode* b) { | ||
| 44 | if (!a && !b) return true; | ||
| 45 | if (!a) return false; | ||
| 46 | if (!b) return false; | ||
| 47 | if (a->val != b->val) return false; | ||
| 48 | return eq(a->next, b->next); | ||
| 49 | } | ||
| 50 | |||
| 51 | bool isPalindrome(ListNode* head) { | ||
| 52 | if (!head) return true; | ||
| 53 | if (!head->next) return true; | ||
| 54 | |||
| 55 | // If odd, get the middle element. | ||
| 56 | // If even, get the first element of the second half. | ||
| 57 | const size_t len = length(head); | ||
| 58 | const size_t middle = len/2; | ||
| 59 | const ListNode* head1 = nth(head, middle + (len & 1)); | ||
| 60 | const ListNode* head2 = reverse(head, middle); | ||
| 61 | return eq(head1, head2); | ||
| 62 | } | ||
| 63 | }; | ||
diff --git a/top-interview-questions/easy/linked_list/06_linked_list_cycle.cc b/top-interview-questions/easy/linked_list/06_linked_list_cycle.cc new file mode 100644 index 0000000..e8b4d1d --- /dev/null +++ b/top-interview-questions/easy/linked_list/06_linked_list_cycle.cc | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | /** | ||
| 2 | * Definition for singly-linked list. | ||
| 3 | * struct ListNode { | ||
| 4 | * int val; | ||
| 5 | * ListNode *next; | ||
| 6 | * ListNode(int x) : val(x), next(NULL) {} | ||
| 7 | * }; | ||
| 8 | */ | ||
| 9 | class Solution { | ||
| 10 | public: | ||
| 11 | bool hasCycle(ListNode *head) { | ||
| 12 | if (!head) return false; | ||
| 13 | if (!head->next) return false; | ||
| 14 | |||
| 15 | const ListNode* next1 = head; | ||
| 16 | const ListNode* next2 = head; | ||
| 17 | |||
| 18 | do { | ||
| 19 | next1 = next1->next; | ||
| 20 | next2 = next2->next; | ||
| 21 | if (next2) { | ||
| 22 | next2 = next2->next; | ||
| 23 | } | ||
| 24 | } | ||
| 25 | while ((next1 != head) && next1 && next2 && (next1 != next2)); | ||
| 26 | |||
| 27 | return next1 && next2 && (next1 == next2); | ||
| 28 | } | ||
| 29 | }; | ||
diff --git a/top-interview-questions/easy/others/05_valid_parentheses.cc b/top-interview-questions/easy/others/05_valid_parentheses.cc new file mode 100644 index 0000000..3f6d020 --- /dev/null +++ b/top-interview-questions/easy/others/05_valid_parentheses.cc | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | char matchingChar(char c) { | ||
| 4 | switch (c) { | ||
| 5 | case ')': return '('; | ||
| 6 | case '}': return '{'; | ||
| 7 | case ']': return '['; | ||
| 8 | default: throw; | ||
| 9 | } | ||
| 10 | } | ||
| 11 | |||
| 12 | bool isValid(string s) { | ||
| 13 | // ([]) -- valid | ||
| 14 | // ([)] -- invalid | ||
| 15 | std::stack<char> st; | ||
| 16 | for (char c : s) { | ||
| 17 | switch (c) { | ||
| 18 | case '(': | ||
| 19 | case '{': | ||
| 20 | case '[': { | ||
| 21 | st.push(c); | ||
| 22 | break; | ||
| 23 | } | ||
| 24 | case ')': | ||
| 25 | case '}': | ||
| 26 | case ']': { | ||
| 27 | const char expected = matchingChar(c); | ||
| 28 | if (st.empty() || | ||
| 29 | (st.top() != expected)) { | ||
| 30 | return false; | ||
| 31 | } | ||
| 32 | st.pop(); | ||
| 33 | break; | ||
| 34 | } | ||
| 35 | default: | ||
| 36 | throw; | ||
| 37 | } | ||
| 38 | } | ||
| 39 | return st.empty(); | ||
| 40 | } | ||
| 41 | }; | ||
diff --git a/top-interview-questions/easy/others/06_missing_number.cc b/top-interview-questions/easy/others/06_missing_number.cc new file mode 100644 index 0000000..0487bcc --- /dev/null +++ b/top-interview-questions/easy/others/06_missing_number.cc | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | int missingNumber(vector<int>& nums) { | ||
| 4 | const size_t expectedSum = nums.size() * (nums.size()+1) / 2; | ||
| 5 | |||
| 6 | size_t sum = 0; | ||
| 7 | for (int x : nums) { | ||
| 8 | sum += x; | ||
| 9 | } | ||
| 10 | |||
| 11 | return expectedSum - sum; | ||
| 12 | } | ||
| 13 | }; | ||
diff --git a/top-interview-questions/easy/sorting_and_searching/01_merge_sorted_array.cc b/top-interview-questions/easy/sorting_and_searching/01_merge_sorted_array.cc new file mode 100644 index 0000000..9abb974 --- /dev/null +++ b/top-interview-questions/easy/sorting_and_searching/01_merge_sorted_array.cc | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) { | ||
| 4 | int i = m-1; | ||
| 5 | int j = n-1; | ||
| 6 | int k = n+m-1; | ||
| 7 | |||
| 8 | while ((i >= 0) && (j >= 0)) { | ||
| 9 | if (nums1[i] >= nums2[j]) { | ||
| 10 | nums1[k--] = nums1[i--]; | ||
| 11 | } else { | ||
| 12 | nums1[k--] = nums2[j--]; | ||
| 13 | } | ||
| 14 | } | ||
| 15 | |||
| 16 | while (i >= 0) { | ||
| 17 | nums1[k--] = nums1[i--]; | ||
| 18 | } | ||
| 19 | |||
| 20 | while (j >= 0) { | ||
| 21 | nums1[k--] = nums2[j--]; | ||
| 22 | } | ||
| 23 | } | ||
| 24 | }; | ||
diff --git a/top-interview-questions/easy/sorting_and_searching/02_first_bad_version.cc b/top-interview-questions/easy/sorting_and_searching/02_first_bad_version.cc new file mode 100644 index 0000000..15e2504 --- /dev/null +++ b/top-interview-questions/easy/sorting_and_searching/02_first_bad_version.cc | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // The API isBadVersion is defined for you. | ||
| 2 | // bool isBadVersion(int version); | ||
| 3 | |||
| 4 | class Solution { | ||
| 5 | public: | ||
| 6 | int FirstBad(int left, int right) { | ||
| 7 | if (left == right) { | ||
| 8 | return left; | ||
| 9 | } | ||
| 10 | const int mid = left + (right - left) / 2; | ||
| 11 | if (isBadVersion(mid)) { | ||
| 12 | return FirstBad(left, mid); | ||
| 13 | } else { | ||
| 14 | return FirstBad(mid+1, right); | ||
| 15 | } | ||
| 16 | } | ||
| 17 | |||
| 18 | int firstBadVersion(int n) { | ||
| 19 | return FirstBad(1, n); | ||
| 20 | } | ||
| 21 | }; | ||
diff --git a/top-interview-questions/easy/strings/03_first_unique_character.cc b/top-interview-questions/easy/strings/03_first_unique_character.cc new file mode 100644 index 0000000..871f761 --- /dev/null +++ b/top-interview-questions/easy/strings/03_first_unique_character.cc | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | int firstUniqChar(string s) { | ||
| 4 | int count[256] = {}; | ||
| 5 | |||
| 6 | for (char c : s) { | ||
| 7 | count[c]++; | ||
| 8 | } | ||
| 9 | |||
| 10 | for (size_t i = 0; i < s.size(); ++i) { | ||
| 11 | if (count[s[i]] == 1) { | ||
| 12 | return i; | ||
| 13 | } | ||
| 14 | } | ||
| 15 | |||
| 16 | return -1; | ||
| 17 | } | ||
| 18 | }; | ||
diff --git a/top-interview-questions/easy/strings/04_valid_anagram.cc b/top-interview-questions/easy/strings/04_valid_anagram.cc new file mode 100644 index 0000000..3ca6b7c --- /dev/null +++ b/top-interview-questions/easy/strings/04_valid_anagram.cc | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | static void count(const string& s, int* counts) { | ||
| 4 | for (char c : s) { | ||
| 5 | counts[c]++; | ||
| 6 | } | ||
| 7 | } | ||
| 8 | |||
| 9 | bool isAnagram(string s, string t) { | ||
| 10 | if (s.size() != t.size()) { | ||
| 11 | return false; | ||
| 12 | } | ||
| 13 | // strings are equal length | ||
| 14 | |||
| 15 | int sCount[256] = {}; | ||
| 16 | int tCount[256] = {}; | ||
| 17 | |||
| 18 | count(s, sCount); | ||
| 19 | count(t, tCount); | ||
| 20 | |||
| 21 | for (char c : s) { | ||
| 22 | if (sCount[c] != tCount[c]) { | ||
| 23 | return false; | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | return true; | ||
| 28 | } | ||
| 29 | }; | ||
diff --git a/top-interview-questions/easy/strings/05_valid_palindrome.cc b/top-interview-questions/easy/strings/05_valid_palindrome.cc new file mode 100644 index 0000000..1b4ca6f --- /dev/null +++ b/top-interview-questions/easy/strings/05_valid_palindrome.cc | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | class Solution { | ||
| 2 | public: | ||
| 3 | bool IsAlphaNum(char c) { | ||
| 4 | return | ||
| 5 | (('a' <= c) && (c <= 'z')) || | ||
| 6 | (('A' <= c) && (c <= 'Z')) || | ||
| 7 | (('0' <= c) && (c <= '9')); | ||
| 8 | } | ||
| 9 | |||
| 10 | void Transform(string& s) { | ||
| 11 | size_t j = 0; | ||
| 12 | for (size_t i = 0; i < s.size(); ++i) { | ||
| 13 | if (IsAlphaNum(s[i])) { | ||
| 14 | s[j] = std::tolower(s[i]); | ||
| 15 | j++; | ||
| 16 | } | ||
| 17 | } | ||
| 18 | s.resize(j); | ||
| 19 | } | ||
| 20 | |||
| 21 | bool isPalindrome(string s) { | ||
| 22 | Transform(s); | ||
| 23 | for (size_t i = 0; i < s.size()/2; ++i) { | ||
| 24 | if (s[i] != s[s.size()-i-1]) { | ||
| 25 | return false; | ||
| 26 | } | ||
| 27 | } | ||
| 28 | return true; | ||
| 29 | } | ||
| 30 | }; | ||
diff --git a/top-interview-questions/easy/trees/01_maximum_depth_of_binary_tree.cc b/top-interview-questions/easy/trees/01_maximum_depth_of_binary_tree.cc new file mode 100644 index 0000000..4d13af7 --- /dev/null +++ b/top-interview-questions/easy/trees/01_maximum_depth_of_binary_tree.cc | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | /** | ||
| 2 | * Definition for a binary tree node. | ||
| 3 | * struct TreeNode { | ||
| 4 | * int val; | ||
| 5 | * TreeNode *left; | ||
| 6 | * TreeNode *right; | ||
| 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| 10 | * }; | ||
| 11 | */ | ||
| 12 | class Solution { | ||
| 13 | public: | ||
| 14 | int max(int a, int b) { return a > b ? a : b; } | ||
| 15 | |||
| 16 | int maxDepth(TreeNode* root) { | ||
| 17 | if (!root) return 0; | ||
| 18 | return 1 + max(maxDepth(root->left), maxDepth(root->right)); | ||
| 19 | } | ||
| 20 | }; | ||
diff --git a/top-interview-questions/easy/trees/02_valid_binary_search_tree.cc b/top-interview-questions/easy/trees/02_valid_binary_search_tree.cc new file mode 100644 index 0000000..a071daf --- /dev/null +++ b/top-interview-questions/easy/trees/02_valid_binary_search_tree.cc | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | /** | ||
| 2 | * Definition for a binary tree node. | ||
| 3 | * struct TreeNode { | ||
| 4 | * int val; | ||
| 5 | * TreeNode *left; | ||
| 6 | * TreeNode *right; | ||
| 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| 10 | * }; | ||
| 11 | */ | ||
| 12 | class Solution { | ||
| 13 | public: | ||
| 14 | bool isValidBSTRec(TreeNode* root, int* min, int* max) { | ||
| 15 | if (root->left && root->right) { | ||
| 16 | int leftMin, leftMax, rightMin, rightMax; | ||
| 17 | if (!isValidBSTRec(root->left, &leftMin, &leftMax) || | ||
| 18 | !isValidBSTRec(root->right, &rightMin, &rightMax)) { | ||
| 19 | return false; | ||
| 20 | } | ||
| 21 | *min = std::min(std::min(leftMin, rightMin), root->val); | ||
| 22 | *max = std::max(std::max(leftMax, rightMax), root->val); | ||
| 23 | return (leftMax < root->val) && (root->val < rightMin); | ||
| 24 | } | ||
| 25 | else if (root->left) { | ||
| 26 | int leftMin, leftMax; | ||
| 27 | if (!isValidBSTRec(root->left, &leftMin, &leftMax)) { | ||
| 28 | return false; | ||
| 29 | } | ||
| 30 | *min = std::min(leftMin, root->val); | ||
| 31 | *max = std::max(leftMax, root->val); | ||
| 32 | return (leftMax < root->val); | ||
| 33 | } | ||
| 34 | else if (root->right) { | ||
| 35 | int rightMin, rightMax; | ||
| 36 | if (!isValidBSTRec(root->right, &rightMin, &rightMax)) { | ||
| 37 | return false; | ||
| 38 | } | ||
| 39 | *min = std::min(rightMin, root->val); | ||
| 40 | *max = std::max(rightMax, root->val); | ||
| 41 | return (root->val < rightMin); | ||
| 42 | } | ||
| 43 | else { | ||
| 44 | *min = *max = root->val; | ||
| 45 | return true; | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | bool isValidBST(TreeNode* root) { | ||
| 50 | if (!root) return true; | ||
| 51 | int minVal, maxVal; | ||
| 52 | return isValidBSTRec(root, &minVal, &maxVal); | ||
| 53 | } | ||
| 54 | }; | ||
diff --git a/top-interview-questions/easy/trees/03_symmetric_tree.cc b/top-interview-questions/easy/trees/03_symmetric_tree.cc new file mode 100644 index 0000000..bbdc52b --- /dev/null +++ b/top-interview-questions/easy/trees/03_symmetric_tree.cc | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | /** | ||
| 2 | * Definition for a binary tree node. | ||
| 3 | * struct TreeNode { | ||
| 4 | * int val; | ||
| 5 | * TreeNode *left; | ||
| 6 | * TreeNode *right; | ||
| 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| 10 | * }; | ||
| 11 | */ | ||
| 12 | class Solution { | ||
| 13 | public: | ||
| 14 | bool isSymmetricVector(const std::vector<const TreeNode*>& nodes) { | ||
| 15 | if (nodes.empty()) return true; | ||
| 16 | if (nodes.size() == 1) return true; | ||
| 17 | for (size_t i = 0; i < nodes.size()/2; ++i) { | ||
| 18 | const size_t j = nodes.size() - i - 1; | ||
| 19 | if ((nodes[i] && !nodes[j]) || | ||
| 20 | (!nodes[i] && nodes[j]) || | ||
| 21 | (nodes[i] && nodes[j] && (nodes[i]->val != nodes[j]->val))) { | ||
| 22 | return false; | ||
| 23 | } | ||
| 24 | } | ||
| 25 | return true; | ||
| 26 | } | ||
| 27 | |||
| 28 | bool isSymmetricBfs(std::vector<const TreeNode*>& current_level, | ||
| 29 | std::vector<const TreeNode*>& next_level) { | ||
| 30 | if (current_level.empty()) { | ||
| 31 | return true; | ||
| 32 | } | ||
| 33 | if (!isSymmetricVector(current_level)) { | ||
| 34 | return false; | ||
| 35 | } | ||
| 36 | for (const TreeNode* node : current_level) { | ||
| 37 | if (node) { | ||
| 38 | next_level.push_back(node->left); | ||
| 39 | next_level.push_back(node->right); | ||
| 40 | } | ||
| 41 | } | ||
| 42 | current_level.clear(); // New next level. | ||
| 43 | return isSymmetricBfs(next_level, current_level); | ||
| 44 | } | ||
| 45 | |||
| 46 | bool isSymmetric(TreeNode* root) { | ||
| 47 | if (!root) return true; | ||
| 48 | std::vector<const TreeNode*> current_level({root}); | ||
| 49 | std::vector<const TreeNode*> next_level; | ||
| 50 | return isSymmetricBfs(current_level, next_level); | ||
| 51 | } | ||
| 52 | }; | ||
diff --git a/top-interview-questions/easy/trees/04_binary_tree_level_order_traversal.cc b/top-interview-questions/easy/trees/04_binary_tree_level_order_traversal.cc new file mode 100644 index 0000000..9c506ab --- /dev/null +++ b/top-interview-questions/easy/trees/04_binary_tree_level_order_traversal.cc | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | /** | ||
| 2 | * Definition for a binary tree node. | ||
| 3 | * struct TreeNode { | ||
| 4 | * int val; | ||
| 5 | * TreeNode *left; | ||
| 6 | * TreeNode *right; | ||
| 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| 10 | * }; | ||
| 11 | */ | ||
| 12 | class Solution { | ||
| 13 | public: | ||
| 14 | void bfs(vector<vector<int>>& levels, | ||
| 15 | vector<const TreeNode*>& current_level, | ||
| 16 | vector<const TreeNode*>& next_level) { | ||
| 17 | if (current_level.empty()) { | ||
| 18 | return; | ||
| 19 | } | ||
| 20 | levels.push_back({}); | ||
| 21 | vector<int>& level = levels.back(); | ||
| 22 | level.reserve(current_level.size()); | ||
| 23 | for (const TreeNode* node : current_level) { | ||
| 24 | level.push_back(node->val); | ||
| 25 | if (node->left) { | ||
| 26 | next_level.push_back(node->left); | ||
| 27 | } | ||
| 28 | if (node->right) { | ||
| 29 | next_level.push_back(node->right); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | current_level.clear(); // New next level. | ||
| 33 | bfs(levels, next_level, current_level); | ||
| 34 | } | ||
| 35 | |||
| 36 | vector<vector<int>> levelOrder(TreeNode* root) { | ||
| 37 | if (!root) return {}; | ||
| 38 | vector<vector<int>> levels; | ||
| 39 | vector<const TreeNode*> current_level({root}); | ||
| 40 | vector<const TreeNode*> next_level; | ||
| 41 | bfs(levels, current_level, next_level); | ||
| 42 | return levels; | ||
| 43 | } | ||
| 44 | }; | ||
diff --git a/top-interview-questions/easy/trees/05_convert_sorted_array_to_binary_search_tree.cc b/top-interview-questions/easy/trees/05_convert_sorted_array_to_binary_search_tree.cc new file mode 100644 index 0000000..4882a2a --- /dev/null +++ b/top-interview-questions/easy/trees/05_convert_sorted_array_to_binary_search_tree.cc | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | /** | ||
| 2 | * Definition for a binary tree node. | ||
| 3 | * struct TreeNode { | ||
| 4 | * int val; | ||
| 5 | * TreeNode *left; | ||
| 6 | * TreeNode *right; | ||
| 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| 10 | * }; | ||
| 11 | */ | ||
| 12 | class Solution { | ||
| 13 | public: | ||
| 14 | // 'end' is one past the end. | ||
| 15 | TreeNode* makeTree(const vector<int>& nums, size_t start, size_t end) { | ||
| 16 | if (start >= end) return nullptr; | ||
| 17 | const size_t middle = start + (end - start) / 2; | ||
| 18 | TreeNode* root = new TreeNode(nums[middle]); | ||
| 19 | root->left = makeTree(nums, start, middle); | ||
| 20 | root->right = makeTree(nums, middle+1, end); | ||
| 21 | return root; | ||
| 22 | } | ||
| 23 | |||
| 24 | TreeNode* sortedArrayToBST(vector<int>& nums) { | ||
| 25 | return makeTree(nums, 0, nums.size()); | ||
| 26 | } | ||
| 27 | }; | ||
diff --git a/top-interview-questions/medium/trees_and_graphs/01_binary_tree_inorder_traversal.cc b/top-interview-questions/medium/trees_and_graphs/01_binary_tree_inorder_traversal.cc new file mode 100644 index 0000000..6a2762b --- /dev/null +++ b/top-interview-questions/medium/trees_and_graphs/01_binary_tree_inorder_traversal.cc | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | /** | ||
| 2 | * Definition for a binary tree node. | ||
| 3 | * struct TreeNode { | ||
| 4 | * int val; | ||
| 5 | * TreeNode *left; | ||
| 6 | * TreeNode *right; | ||
| 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| 10 | * }; | ||
| 11 | */ | ||
| 12 | class Solution { | ||
| 13 | public: | ||
| 14 | void inorder(TreeNode* node, vector<int>& vals) { | ||
| 15 | if (node == nullptr) return; | ||
| 16 | |||
| 17 | inorder(node->left, vals); | ||
| 18 | vals.push_back(node->val); | ||
| 19 | inorder(node->right, vals); | ||
| 20 | } | ||
| 21 | |||
| 22 | vector<int> inorderTraversal(TreeNode* root) { | ||
| 23 | vector<int> vals; | ||
| 24 | inorder(root, vals); | ||
| 25 | return vals; | ||
| 26 | } | ||
| 27 | }; | ||
diff --git a/top-interview-questions/medium/trees_and_graphs/02_binary_tree_zigzag_level_order_traversal.cc b/top-interview-questions/medium/trees_and_graphs/02_binary_tree_zigzag_level_order_traversal.cc new file mode 100644 index 0000000..2abb093 --- /dev/null +++ b/top-interview-questions/medium/trees_and_graphs/02_binary_tree_zigzag_level_order_traversal.cc | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | /** | ||
| 2 | * Definition for a binary tree node. | ||
| 3 | * struct TreeNode { | ||
| 4 | * int val; | ||
| 5 | * TreeNode *left; | ||
| 6 | * TreeNode *right; | ||
| 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| 10 | * }; | ||
| 11 | */ | ||
| 12 | class Solution { | ||
| 13 | public: | ||
| 14 | void push(vector<const TreeNode*>& level, vector<int>& values, const TreeNode* node) { | ||
| 15 | level.push_back(node); | ||
| 16 | values.push_back(node->val); | ||
| 17 | } | ||
| 18 | |||
| 19 | void zigZag(bool leftRight, const vector<const TreeNode*>& level, vector<vector<int>>& values) { | ||
| 20 | vector<const TreeNode*> next_level; | ||
| 21 | vector<int> next_values; | ||
| 22 | |||
| 23 | if (leftRight) { | ||
| 24 | for (int i = level.size()-1; i >= 0; --i) { | ||
| 25 | const TreeNode* node = level[i]; | ||
| 26 | if (node->left) push(next_level, next_values, node->left); | ||
| 27 | if (node->right) push(next_level, next_values, node->right); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | else { | ||
| 31 | for (int i = level.size()-1; i >= 0; --i) { | ||
| 32 | const TreeNode* node = level[i]; | ||
| 33 | if (node->right) push(next_level, next_values, node->right); | ||
| 34 | if (node->left) push(next_level, next_values, node->left); | ||
| 35 | } | ||
| 36 | } | ||
| 37 | |||
| 38 | if (!next_level.empty()) { | ||
| 39 | values.push_back(next_values); | ||
| 40 | zigZag(!leftRight, next_level, values); | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | vector<vector<int>> zigzagLevelOrder(TreeNode* root) { | ||
| 45 | if (root == nullptr) return {}; | ||
| 46 | |||
| 47 | vector<const TreeNode*> level = {root}; | ||
| 48 | vector<vector<int>> values = {{root->val}}; | ||
| 49 | |||
| 50 | zigZag(false, level, values); | ||
| 51 | return values; | ||
| 52 | } | ||
| 53 | }; | ||
diff --git a/top-interview-questions/medium/trees_and_graphs/03_construct_binary_tree_from_preorder_and_inorder_traversal.cc b/top-interview-questions/medium/trees_and_graphs/03_construct_binary_tree_from_preorder_and_inorder_traversal.cc new file mode 100644 index 0000000..95e3655 --- /dev/null +++ b/top-interview-questions/medium/trees_and_graphs/03_construct_binary_tree_from_preorder_and_inorder_traversal.cc | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | /** | ||
| 2 | * Definition for a binary tree node. | ||
| 3 | * struct TreeNode { | ||
| 4 | * int val; | ||
| 5 | * TreeNode *left; | ||
| 6 | * TreeNode *right; | ||
| 7 | * TreeNode() : val(0), left(nullptr), right(nullptr) {} | ||
| 8 | * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} | ||
| 9 | * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {} | ||
| 10 | * }; | ||
| 11 | */ | ||
| 12 | class Solution { | ||
| 13 | public: | ||
| 14 | TreeNode* build(const vector<int>& preorder, const vector<int>& inorder, | ||
| 15 | int& preIdx, int leftIdx, int rightIdx) { | ||
| 16 | // Base case. | ||
| 17 | if (leftIdx > rightIdx) { | ||
| 18 | return nullptr; | ||
| 19 | } | ||
| 20 | |||
| 21 | // Root value. | ||
| 22 | const int root = preorder[preIdx++]; | ||
| 23 | |||
| 24 | // Base case. | ||
| 25 | if (leftIdx == rightIdx) { | ||
| 26 | return new TreeNode{root, nullptr, nullptr}; | ||
| 27 | } | ||
| 28 | // Recursive case. | ||
| 29 | else { | ||
| 30 | // Find the root in the inorder array. | ||
| 31 | int inorderRootIdx = -1; | ||
| 32 | for (int i = 0; i < inorder.size(); ++i) { | ||
| 33 | if (inorder[i] == root) { | ||
| 34 | inorderRootIdx = i; | ||
| 35 | break; | ||
| 36 | } | ||
| 37 | } | ||
| 38 | // Build recursively. | ||
| 39 | TreeNode* left = build(preorder, inorder, preIdx, leftIdx, inorderRootIdx-1); | ||
| 40 | TreeNode* right = build(preorder, inorder, preIdx, inorderRootIdx+1, rightIdx); | ||
| 41 | return new TreeNode{root, left, right}; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { | ||
| 46 | int preIdx = 0; | ||
| 47 | return build(preorder, inorder, preIdx, 0, preorder.size()-1); | ||
| 48 | } | ||
| 49 | }; | ||
diff --git a/top-interview-questions/medium/trees_and_graphs/04_populating_next_right_pointers_in_each_node.cc b/top-interview-questions/medium/trees_and_graphs/04_populating_next_right_pointers_in_each_node.cc new file mode 100644 index 0000000..17a5874 --- /dev/null +++ b/top-interview-questions/medium/trees_and_graphs/04_populating_next_right_pointers_in_each_node.cc | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | /* | ||
| 2 | // Definition for a Node. | ||
| 3 | class Node { | ||
| 4 | public: | ||
| 5 | int val; | ||
| 6 | Node* left; | ||
| 7 | Node* right; | ||
| 8 | Node* next; | ||
| 9 | |||
| 10 | Node() : val(0), left(NULL), right(NULL), next(NULL) {} | ||
| 11 | |||
| 12 | Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {} | ||
| 13 | |||
| 14 | Node(int _val, Node* _left, Node* _right, Node* _next) | ||
| 15 | : val(_val), left(_left), right(_right), next(_next) {} | ||
| 16 | }; | ||
| 17 | */ | ||
| 18 | |||
| 19 | class Solution { | ||
| 20 | public: | ||
| 21 | // The obvious solution is to do a BFS and connect the nodes in each level. | ||
| 22 | // However, the problem asks us to use "constant space" (depth of tree). | ||
| 23 | |||
| 24 | void connectLeftRight(Node* leftTree, Node* rightTree) { | ||
| 25 | while (leftTree && rightTree) { | ||
| 26 | leftTree->next = rightTree; | ||
| 27 | |||
| 28 | leftTree = leftTree->right; | ||
| 29 | rightTree = rightTree->left; | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | Node* connect(Node* root) { | ||
| 34 | if (root == nullptr) { | ||
| 35 | return root; | ||
| 36 | } | ||
| 37 | |||
| 38 | connect(root->left); | ||
| 39 | connect(root->right); | ||
| 40 | |||
| 41 | if (root->left) { // Non-leaf node. | ||
| 42 | connectLeftRight(root->left, root->right); | ||
| 43 | } | ||
| 44 | |||
| 45 | return root; | ||
| 46 | } | ||
| 47 | }; | ||
