summaryrefslogtreecommitdiff
path: root/top-interview-questions
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-02-05 18:36:31 -0800
committer3gg <3gg@shellblade.net>2025-02-05 18:36:31 -0800
commit4689e4e80b479be25f7557d05818f5caa723aafa (patch)
tree4df25811fe2a9a15b401375178da6537f4b6063f /top-interview-questions
Initial commit.HEADmain
Diffstat (limited to 'top-interview-questions')
-rw-r--r--top-interview-questions/easy/array/01_remove_duplicates_from_sorted_array.cc13
-rw-r--r--top-interview-questions/easy/array/02_best_time_to_buy_and_sell_stock_2.cc24
-rw-r--r--top-interview-questions/easy/array/03_rotate_array.cc39
-rw-r--r--top-interview-questions/easy/array/04_contains_duplicate.cc14
-rw-r--r--top-interview-questions/easy/array/05_single_number.cc10
-rw-r--r--top-interview-questions/easy/array/06_intersection_of_two_arrays_II.cc27
-rw-r--r--top-interview-questions/easy/array/07_plus_one.cc25
-rw-r--r--top-interview-questions/easy/array/08_move_zeroes.cc23
-rw-r--r--top-interview-questions/easy/array/09_two_sum.cc24
-rw-r--r--top-interview-questions/easy/design/01_shuffle_an_array.cc41
-rw-r--r--top-interview-questions/easy/design/02_min_stack.cc56
-rw-r--r--top-interview-questions/easy/dynamic_programming/01_climbing_stairs.cc22
-rw-r--r--top-interview-questions/easy/linked_list/01_delete_node_in_a_linked_list.cc22
-rw-r--r--top-interview-questions/easy/linked_list/02_remove_nth_node_from_end_of_list.cc32
-rw-r--r--top-interview-questions/easy/linked_list/03_reverse_linked_list.cc26
-rw-r--r--top-interview-questions/easy/linked_list/04_merge_two_sorted_lists.cc52
-rw-r--r--top-interview-questions/easy/linked_list/05_palindrome_linked_list.cc48
-rw-r--r--top-interview-questions/easy/linked_list/05_palindrome_linked_list_2.cc63
-rw-r--r--top-interview-questions/easy/linked_list/06_linked_list_cycle.cc29
-rw-r--r--top-interview-questions/easy/others/05_valid_parentheses.cc41
-rw-r--r--top-interview-questions/easy/others/06_missing_number.cc13
-rw-r--r--top-interview-questions/easy/sorting_and_searching/01_merge_sorted_array.cc24
-rw-r--r--top-interview-questions/easy/sorting_and_searching/02_first_bad_version.cc21
-rw-r--r--top-interview-questions/easy/strings/03_first_unique_character.cc18
-rw-r--r--top-interview-questions/easy/strings/04_valid_anagram.cc29
-rw-r--r--top-interview-questions/easy/strings/05_valid_palindrome.cc30
-rw-r--r--top-interview-questions/easy/trees/01_maximum_depth_of_binary_tree.cc20
-rw-r--r--top-interview-questions/easy/trees/02_valid_binary_search_tree.cc54
-rw-r--r--top-interview-questions/easy/trees/03_symmetric_tree.cc52
-rw-r--r--top-interview-questions/easy/trees/04_binary_tree_level_order_traversal.cc44
-rw-r--r--top-interview-questions/easy/trees/05_convert_sorted_array_to_binary_search_tree.cc27
-rw-r--r--top-interview-questions/medium/trees_and_graphs/01_binary_tree_inorder_traversal.cc27
-rw-r--r--top-interview-questions/medium/trees_and_graphs/02_binary_tree_zigzag_level_order_traversal.cc53
-rw-r--r--top-interview-questions/medium/trees_and_graphs/03_construct_binary_tree_from_preorder_and_inorder_traversal.cc49
-rw-r--r--top-interview-questions/medium/trees_and_graphs/04_populating_next_right_pointers_in_each_node.cc47
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 @@
1class Solution {
2public:
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 @@
1class Solution {
2public:
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 @@
1class Solution {
2public:
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 @@
1class Solution {
2public:
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 @@
1class Solution {
2public:
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 @@
1class Solution {
2public:
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 @@
1class Solution {
2public:
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 @@
1class Solution {
2public:
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 @@
1class Solution {
2public:
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 @@
1class Solution {
2public:
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
19private:
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 @@
1class MinStack {
2public:
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
33private:
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 @@
1class Solution {
2public:
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 */
9class Solution {
10public:
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 */
11class Solution {
12public:
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 */
11class Solution {
12public:
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 */
11class Solution {
12public:
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 */
11class Solution {
12public:
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 */
11class Solution {
12public:
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 */
9class Solution {
10public:
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 @@
1class Solution {
2public:
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 @@
1class Solution {
2public:
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 @@
1class Solution {
2public:
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
4class Solution {
5public:
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 @@
1class Solution {
2public:
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 @@
1class Solution {
2public:
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 @@
1class Solution {
2public:
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 */
12class Solution {
13public:
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 */
12class Solution {
13public:
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 */
12class Solution {
13public:
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 */
12class Solution {
13public:
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 */
12class Solution {
13public:
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 */
12class Solution {
13public:
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 */
12class Solution {
13public:
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 */
12class Solution {
13public:
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.
3class Node {
4public:
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
19class Solution {
20public:
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};