diff options
author | jack <[email protected]> | 2024-06-14 13:13:15 -0600 |
---|---|---|
committer | jack <[email protected]> | 2024-06-14 13:13:15 -0600 |
commit | d343a3b18dbaca9297d4f7b2280c4a16f0a5c8aa (patch) | |
tree | 96df922dae2a5073d9a50ea70c7aae6aa37e3ebe | |
download | leetcode-d343a3b18dbaca9297d4f7b2280c4a16f0a5c8aa.tar.gz leetcode-d343a3b18dbaca9297d4f7b2280c4a16f0a5c8aa.zip |
initial
1668 files changed, 69483 insertions, 0 deletions
diff --git a/.gdb_history b/.gdb_history new file mode 100644 index 0000000..0d69d40 --- /dev/null +++ b/.gdb_history @@ -0,0 +1,29 @@ +b minimumMoney +r +disas +ni +r +r +k +b main +r +k +i b +d +b capitalizeTitle +i b +r +ni +k +b capitali +b capitalizeTitle +i b +disas +i b +r +ni +r +k +d +r +quit diff --git a/01_matrix.cpp b/01_matrix.cpp new file mode 100644 index 0000000..f6d9c2d --- /dev/null +++ b/01_matrix.cpp @@ -0,0 +1,34 @@ +#include "leetcode.h" + +class Solution { +public: + vector<vector<int>> updateMatrix(vector<vector<int>> &mat) { + int m = mat.size(), n = mat[0].size(); + vector<vector<int>> ans(m, vector<int>(n, INT_MAX)); + queue<pair<int, int>> qp; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (mat[i][j] == 0) { + ans[i][j] = 0; + qp.push({i, j}); + } + } + } + vector<pair<int, int>> vp{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; + while (!qp.empty()) { + auto curr = qp.front(); + qp.pop(); + int currX = curr.first, currY = curr.second; + for (auto dirr : vp) { + int x = currX + dirr.first, y = currY + dirr.second; + if (x >= 0 && x < m && y >= 0 && y < n) { + if (ans[x][y] > ans[currX][currY] + 1) { + ans[x][y] = ans[currX][currY] + 1; + qp.push({x, y}); + } + } + } + } + return ans; + } +}; diff --git a/132_pattern.c b/132_pattern.c new file mode 100644 index 0000000..67e57de --- /dev/null +++ b/132_pattern.c @@ -0,0 +1,39 @@ +// 456. 132 Pattern +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array of 'n' integers 'nums', a 132 pattern is a subsequence of + * three integers 'nums[i], nums[j], nums[k]' such that 'i < j < k' and 'nums[i] + * < nums[k] < nums[j]'. return true if there is a 132 pattern in 'nums', and + * false otherwise + */ + +bool find132pattern(int *nums, int nums_size) { + int n = nums_size, third = INT_MIN, s_idx = 0; + int *stk = malloc(n * sizeof(int)); + bool ans = false; + for (int i = n - 1; i >= 0; i--) { + if (nums[i] < third) { + ans = true; + break; + } + while (s_idx && nums[i] > stk[s_idx - 1]) { + third = stk[s_idx - 1]; + s_idx--; + } + stk[s_idx] = nums[i]; + s_idx++; + } + free(stk); + return ans; +} + +int main() { + int n1[] = {1, 2, 3, 4}, n2[] = {3, 1, 4, 2}, n3[] = {-1, 3, 2, 0}; + printf("%d\n", find132pattern(n1, 4)); // expect: 0 + printf("%d\n", find132pattern(n2, 4)); // expect: 1 + printf("%d\n", find132pattern(n3, 4)); // expect: 1 +} diff --git a/132_pattern.cpp b/132_pattern.cpp new file mode 100644 index 0000000..a9f0c43 --- /dev/null +++ b/132_pattern.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class Solution { +public: + bool find132pattern(vector<int> &nums) { + int n = nums.size(), minI[n]; + stack<int> s; + minI[0] = nums[0]; + for (int i = 1; i < nums.size(); i++) + minI[i] = min(minI[i - 1], nums[i]); + for (int i = nums.size() - 1; i >= 0; i--) { + while (!s.empty() && s.top() <= minI[i]) + s.pop(); + if (!s.empty() && s.top() < nums[i]) + return true; + s.push(nums[i]); + } + return false; + } +}; + +int main() { + vector<int> nums = {1, 3, 2, 4}; + Solution obj; + for (int i = 0; i < nums.size(); i++) + cout << nums[i] << ' '; + cout << endl << "searching for '132'...\n"; + if (obj.find132pattern(nums)) + cout << "found"; + else + cout << "not found"; +} diff --git a/132_pattern.py b/132_pattern.py new file mode 100644 index 0000000..8a9f0c5 --- /dev/null +++ b/132_pattern.py @@ -0,0 +1,29 @@ +# 456. 132 Pattern +import sys + +""" +given an array of 'n' integers 'nums', a 132 pattern is a subsequence of +three integers 'nums[i], nums[j], nums[k]' such that 'i < j < k' and 'nums[i] +< nums[k] < nums[j]'. return true if there is a 132 pattern in 'nums', and +false otherwise +""" + + +class Solution(object): + def find132pattern(self, nums): + stack = [] + s3 = -sys.maxint + for n in nums[::-1]: + if n < s3: + return True + while stack and stack[-1] < n: + s3 = stack.pop() + stack.append(n) + return False + + +if __name__ == "__main__": + obj = Solution() + print(obj.find132pattern([1, 2, 3, 4])) # expect: False + print(obj.find132pattern([3, 1, 4, 2])) # expect: True + print(obj.find132pattern([-1, 3, 2, 0])) # expect: True diff --git a/24_game.c b/24_game.c new file mode 100644 index 0000000..9d38dc5 --- /dev/null +++ b/24_game.c @@ -0,0 +1,116 @@ +// 679. 24 Game +#include "leetcode.h" + +/* + * given an integer array 'cards' of length 4. you have four cards, each + * containing a number in the range '[1,9]'. you should arrange the numbers on + * these cards in a mathematical expression using the operators '[+,-,*,/]' and + * the parenthesis '(' and ')' to get value 24. you are restricted to the + * following rules: + * - the division operation represents real division, not integer division + * - every operation done is between two numbers. in particular, we cannot use + * '-' as a unary operator + * - you cannot concatenate numbers together + * return true if you can get such expression that evaluates to 24 and false + * otherwise. + */ + +float calculate(float n1, float n2, char operand) { + switch (operand) { + case '+': + return n1 + n2; + case '-': + return n1 - n2; + case '*': + return n1 * n2; + case '/': + if (!n2) + return -1; + return n1 / n2; + } + return 0; +} + +bool judgePoint24(int *cards, int cardsSize) { + int i, j, k, l; + int x, y, z; + int t; + int opersSize = 4; + int sum = 6; + float cal[3]; + int sign[3]; + float ans; + char oper[4] = {'+', '-', '*', '/'}; + for (i = 0; i < cardsSize; i++) + for (j = 0; j < cardsSize; j++) { + if (j == i) + continue; + for (k = 0; k < cardsSize; k++) { + if (k == i || k == j) + continue; + l = sum - (i + j + k); + for (x = 0; x < opersSize; x++) { + sign[0] = 0; + if (x <= 1) + sign[0] = 1; + for (y = 0; y < opersSize; y++) { + sign[1] = 0; + if (y <= 1) + sign[1] = 1; + for (z = 0; z < opersSize; z++) { + sign[2] = 0; + if (z <= 1) + sign[2] = 1; + if ((sign[0] ^ sign[1]) || (sign[0] ^ sign[2]) || + (sign[1] ^ sign[2])) { + cal[0] = calculate(cards[i], cards[j], oper[x]); + cal[1] = calculate(cal[0], cards[k], oper[y]); + cal[2] = calculate(cal[1], cards[l], oper[z]); + ans = cal[2] > 24 ? cal[2] - 24 : 24 - cal[2]; + if (ans < 0.0001) + return true; + cal[0] = calculate(cards[i], cards[j], oper[x]); + cal[2] = calculate(cards[k], cards[l], oper[z]); + cal[1] = calculate(cal[0], cal[2], oper[y]); + ans = cal[1] > 24 ? cal[1] - 24 : 24 - cal[1]; + if (ans < 0.0001) + return true; + cal[1] = calculate(cards[j], cards[k], oper[y]); + cal[0] = calculate(cards[i], cal[1], oper[x]); + cal[2] = calculate(cal[0], cards[l], oper[z]); + ans = cal[2] > 24 ? cal[2] - 24 : 24 - cal[2]; + if (ans < 0.0001) + return true; + cal[1] = calculate(cards[j], cards[k], oper[y]); + cal[2] = calculate(cal[1], cards[l], oper[z]); + cal[0] = calculate(cards[i], cal[2], oper[x]); + ans = cal[0] > 24 ? cal[0] - 24 : 24 - cal[0]; + if (ans < 0.0001) + return true; + cal[2] = calculate(cards[k], cards[l], oper[z]); + cal[1] = calculate(cards[j], cal[2], oper[y]); + cal[0] = calculate(cards[i], cal[1], oper[x]); + ans = cal[0] > 24 ? cal[0] - 24 : 24 - cal[0]; + if (ans < 0.0001) + return true; + } else { + cal[0] = calculate(cards[i], cards[j], oper[x]); + cal[1] = calculate(cal[0], cards[k], oper[y]); + cal[2] = calculate(cal[1], cards[l], oper[z]); + ans = cal[2] > 24 ? cal[2] - 24 : 24 - cal[2]; + if (ans < 0.0001) + return true; + } + } + } + } + } + } + return false; +} + +int main() { + int c1[] = {4, 1, 8, 7}, c2[] = {1, 2, 1, 2}; + printf("%d\n", judgePoint24(c1, ARRAY_SIZE(c1))); // expect: 1 + printf("%d\n", judgePoint24(c2, ARRAY_SIZE(c2))); // expect: 0 +} diff --git a/24_game.py b/24_game.py new file mode 100644 index 0000000..cd65e9b --- /dev/null +++ b/24_game.py @@ -0,0 +1,38 @@ +# 679. 24 Game +from itertools import permutations +from math import isclose + +""" +given an integer array 'cards' of length 4. you have four cards, each +containing a number in the range '[1,9]'. you should arrange the numbers on +these cards in a mathematical expression using the operators '[+,-,*,/]' and +the parenthesis '(' and ')' to get value 24. you are restricted to the +following rules: +- the division operation represents real division, not integer division +- every operation done is between two numbers. in particular, we cannot use +'-' as a unary operator +- you cannot concatenate numbers together +return true if you can get such expression that evaluates to 24 and false +otherwise. +""" + + +class Solution(object): + def judgePoint24(self, cards): + """ + :type cards: List[int] + :rtype: bool + """ + if len(cards) == 1: + return isclose(cards[0], 24) + return any( + self.judgePoint24([x] + rest) + for a, b, *rest in permutations(cards) + for x in {a + b, a - b, a * b, b and a / b} + ) + + +if __name__ == "__main__": + obj = Solution() + print(obj.judgePoint24([4, 1, 8, 7])) + print(obj.judgePoint24([1, 2, 1, 2])) diff --git a/3_consec_int_sum.c b/3_consec_int_sum.c new file mode 100644 index 0000000..8cc4d40 --- /dev/null +++ b/3_consec_int_sum.c @@ -0,0 +1,29 @@ +// 2177. Find Three Consecutive Integers That Sum to a Given Number +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer 'num', return 3 consecutive integers (as a sorted array) + * that sum to 'num'. if 'num' cannot be expressed as the sum of 3 consecutive + * integers, return an empty array. + */ + +long long *sumOfThree(long long num, int *returnSize) { + if ((num - 3) % 3 != 0) { + *returnSize = 0; + return NULL; + } + *returnSize = 3; + long long *ans = malloc(3 * sizeof(long long)); + ans[0] = (num - 3) / 3; + ans[1] = ans[0] + 1; + ans[2] = ans[1] + 1; + return ans; +} + +int main() { + long long num1 = 33, num2 = 4; + int rs1[] = {}, rs2[] = {}; + printf("%p\n", sumOfThree(num1, rs1)); // expect: 10, 11, 12 + printf("%p\n", sumOfThree(num2, rs2)); // expect: nil +} diff --git a/3sum_closest.cpp b/3sum_closest.cpp new file mode 100644 index 0000000..3050ee0 --- /dev/null +++ b/3sum_closest.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + int threeSumClosest(vector<int> &nums, int target) { + sort(nums.begin(), nums.end()); + int n = nums.size(), ans = nums[0] + nums[1] + nums[2]; + for (int i = 0; i < n - 2; ++i) { + int left = i + 1, right = n - 1; + while (left < right) { + int sum3 = nums[i] + nums[left] + nums[right]; + if (abs(ans - target) > abs(sum3 - target)) + ans = sum3; + if (sum3 == target) + break; + if (sum3 > target) + --right; + else + ++left; + } + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums = {-1, 2, 1, -4}; + int target = 1; + cout << obj.threeSumClosest(nums, target); +} diff --git a/3sum_multiplicity.cpp b/3sum_multiplicity.cpp new file mode 100644 index 0000000..66f1f2c --- /dev/null +++ b/3sum_multiplicity.cpp @@ -0,0 +1,18 @@ +#include <bits/stdc++.h> +using namespace std; + +class Solution { +public: + int threeSumMulti(vector<int> &arr, int target) { + int n = arr.size(), mod = 1e9 + 7, ans = 0; + unordered_map<int, int> m; + for (int i = 0; i < n; i++) { + ans = (ans + m[target - arr[i]]) % mod; + for (int j = 0; j < i; j++) + m[arr[i] + arr[j]]++; + } + return ans; + } +}; + +int main() {} @@ -0,0 +1,64 @@ +// 18. 4Sum +#include <stdio.h> +#include <stdlib.h> + +/* + * given array 'nums' of 'n' integers, return an array of all + * unique qudruplets 'nums[a], nums[b], nums[c], nums[d]' + * - such that 0 <= a, b, c, d < n + * - a, b, c, d are distinct + * - 'nums[a] + nums[b] + nums[c] + nums[d]' == 'target' + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int **fourSum(int *nums, int numsSize, int target, int *returnSize, + int **returnColumnsSizes) { + int i, j, left, right; + qsort(nums, numsSize, sizeof(int), cmp); + int **ans = (int **)malloc(1000000 * sizeof(int *)); + int idx = 0; + for (i = 0; i < numsSize - 3; i++) { + if (i > 0 && nums[i] == nums[i - 1]) + continue; + for (j = i + 1; j < numsSize - 2; j++) { + if (j > i + 1 && nums[j] == nums[j - 1]) + continue; + left = j + 1; + right = numsSize - 1; + while (left < right) { + long long sum = (long long)nums[i] + nums[j] + nums[left] + nums[right]; + if (sum == target) { + ans[idx] = (int *)malloc(4 * sizeof(int)); + ans[idx][0] = nums[i]; + ans[idx][1] = nums[j]; + ans[idx][2] = nums[left]; + ans[idx][3] = nums[right]; + idx++; + left++; + right--; + while (left < right && nums[left] == nums[left - 1]) + left++; + while (right > left && nums[right] == nums[right + 1]) + right--; + } else if (sum > target) + right--; + else + left++; + } + } + } + ans = (int **)realloc(ans, idx * sizeof(int *)); + *returnSize = idx; + returnColumnsSizes[0] = (int *)malloc(idx * sizeof(int)); + for (i = 0; i < idx; i++) + returnColumnsSizes[0][i] = 4; + return ans; +} + +int main() { + int nums1[] = {1, 0, -1, 0, -2, 2}, nums2[] = {2, 2, 2, 2, 2}; + int retSz1[] = {3}, retSz2[] = {1}; + int retColSz1[][3] = {}, retColSz2[][1] = {}; + printf("%d\n", fourSum(nums1, 6, 0, retSz1, retColSz1)); +} diff --git a/4sum.cpp b/4sum.cpp new file mode 100644 index 0000000..8ab5fa4 --- /dev/null +++ b/4sum.cpp @@ -0,0 +1,48 @@ +#include "leetcode.h" + +class Solution { +public: + vector<vector<int>> fourSum(vector<int> &nums, int target) { + sort(begin(nums), end(nums)); + return kSum(nums, target, 0, 4); + } + + vector<vector<int>> kSum(vector<int> &nums, int target, int start, int k) { + vector<vector<int>> result; + if (start == nums.size()) + return result; + int avgVal = target / k; + if (nums[start] > avgVal || avgVal > nums.back()) + return result; + if (k == 2) + return twoSum(nums, target, start); + for (int i = start; i < nums.size(); ++i) { + if (i == start || nums[i - 1] != nums[i]) { + for (vector<int> &subset : + kSum(nums, static_cast<long>(target) - nums[i], i + 1, k - 1)) { + result.push_back({nums[i]}); + result.back().insert(end(result.back()), begin(subset), end(subset)); + } + } + } + return result; + } + + vector<vector<int>> twoSum(vector<int> &nums, int target, int start) { + vector<vector<int>> result; + int low = start, high = nums.size() - 1; + while (low < high) { + int currSum = nums[low] + nums[high]; + if (currSum < target || (low > start && nums[low] == nums[low - 1])) + ++low; + else if (currSum > target || + (high < nums.size() - 1 && nums[high] == nums[high + 1])) + --high; + else + result.push_back({nums[low++], nums[high--]}); + } + return result; + } +}; + +int main() {} diff --git a/BST_iterator.cpp b/BST_iterator.cpp new file mode 100644 index 0000000..e50c74a --- /dev/null +++ b/BST_iterator.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class BSTIterator { +public: + stack<TreeNode *> s; + BSTIterator(TreeNode *root) { partialOrder(root); } + int next() { + TreeNode *top = s.top(); + s.pop(); + partialOrder(top->right); + return top->val; + } + bool hasNext() { return !s.empty(); } + void partialOrder(TreeNode *root) { + while (root != NULL) { + s.push(root); + root = root->left; + } + } +}; + +int main() {} Binary files differdiff --git a/add_arr_form_int.c b/add_arr_form_int.c new file mode 100644 index 0000000..2cadd67 --- /dev/null +++ b/add_arr_form_int.c @@ -0,0 +1,42 @@ +// 989. Add to Array-Form of Integer +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * the array-form of an integer 'num' is an array representing its digits in + * left to right order. eg 'num = 1231', the array form is 1,3,2,1. given 'num', + * the array form of an integer, and an integer 'k', return the array-form of + * 'num + k' + */ + +int *addToArrayForm(int *num, int numSize, int k, int *returnSize) { + int *k_arr, *ans, k_size, r_size, p; + for (int i = k, k_size = 0; i > 0; i /= 10) + k_size++; + k_arr = malloc(sizeof(int) * k_size); + for (int i = k_size - 1, p = k; i >= 0; p /= 10) + k_arr[i--] = p % 10; + r_size = k_size > numSize ? k_size : numSize; + ans = malloc(sizeof(int) * (++r_size)); + for (int i = numSize, j = k_size, c = 0, p = r_size - 1; p >= 0; p--) { + c += i > 0 ? num[--i] : 0; + c += j > 0 ? k_arr[--j] : 0; + ans[p] = c % 10; + c /= 10; + } + if (ans[0] == 0) + memmove(ans, ans + 1, sizeof(int) * (--r_size)); + *returnSize = r_size; + free(k_arr); + return ans; +} + +int main() { + int num1[] = {1, 2, 0, 0}, ns1 = 4, k1 = 34, rs1[] = {4}; + int num2[] = {2, 7, 4}, ns2 = 3, k2 = 181, rs2[] = {3}; + int num3[] = {2, 1, 4}, ns3 = 3, k3 = 806, rs3[] = {4}; + printf("%d\n" * addToArrayForm(num1, ns1, k1, rs1)); + printf("%d\n" * addToArrayForm(num2, ns2, k2, rs2)); + printf("%d\n" * addToArrayForm(num3, ns3, k3, rs3)); +} diff --git a/add_arr_form_int.cpp b/add_arr_form_int.cpp new file mode 100644 index 0000000..1cb8f7a --- /dev/null +++ b/add_arr_form_int.cpp @@ -0,0 +1,44 @@ +// 989. Add to Array-Form of Integer +#include "leetcode.h" + +/* + * the array-form of an integer 'num' is an array representing its digits in + * left to right order. eg 'num = 1231', the array form is 1,3,2,1. given 'num', + * the array form of an integer, and an integer 'k', return the array-form of + * 'num + k' + */ + +class Solution { +public: + vector<int> addToArrayForm(vector<int> &num, int k) { + int carry = 0, j = num.size() - 1; + while (j >= 0) { + int sum = num[j] + (k % 10) + carry; + k /= 10; + num[j--] = sum % 10; + carry = sum / 10; + } + while (k > 0) { + int sum = (k % 10) + carry; + k /= 10; + num.insert(num.begin(), sum % 10); + carry = sum / 10; + } + if (carry > 0) + num.insert(num.begin(), carry); + return num; + } +}; + +int main() { + Solution obj; + vector<int> num1 = {1, 2, 0, 0}, num2 = {2, 7, 4}, num3 = {2, 1, 5}; + for (auto i : obj.addToArrayForm(num1, 34)) + cout << i << ','; // expect: 1,2,3,4 + cout << endl; + for (auto i : obj.addToArrayForm(num2, 181)) + cout << i << ','; // expect: 4,5,5 + cout << endl; + for (auto i : obj.addToArrayForm(num3, 806)) + cout << i << ','; // expect: 1,0,2,1 +} diff --git a/add_binary.c b/add_binary.c new file mode 100644 index 0000000..772864e --- /dev/null +++ b/add_binary.c @@ -0,0 +1,28 @@ +// 67. Add Binary +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +char *addBinary(char *a, char *b) { + int i = strlen(a), j = strlen(b), carry = 0; + int k = i > j ? i : j; + char *ans = malloc(k + 2); + ans[k + 1] = '\0'; + while (i || j) { + if (i) + carry += (a[--i] - '0'); + if (j) + carry += (b[--j] - '0'); + ans[k--] = (carry & 1) + '0'; + carry >>= 1; + } + ans[0] = carry + '0'; + return ans + (carry ^ 1); +} + +int main() { + char a1[] = "11", b1[] = "1"; + char a2[] = "1010", b2[] = "1011"; + printf("%c\n" * addBinary(a1, b1)); // expect: 100 + printf("%c\n" * addBinary(a2, b2)); // expect: 100 +} diff --git a/add_binary.cpp b/add_binary.cpp new file mode 100644 index 0000000..9afc1dc --- /dev/null +++ b/add_binary.cpp @@ -0,0 +1,30 @@ +// 67. Add Binary +#include "leetcode.h" + +class Solution { +public: + string addBinary(string a, string b) { + int i = a.size() - 1, j = b.size() - 1, carry = 0; + string ans; + while (i >= 0 || j >= 0 || carry) { + if (i >= 0) { + carry += a[i] - '0'; + i--; + } + if (j >= 0) { + carry += b[j] - '0'; + j--; + } + ans += (carry % 2 + '0'); + carry /= 2; + } + reverse(ans.begin(), ans.end()); + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.addBinary("11", "1") << endl; // expect: 100 + cout << obj.addBinary("1010", "1011") << endl; // expect: 10101 +} diff --git a/add_digits.c b/add_digits.c new file mode 100644 index 0000000..c887a06 --- /dev/null +++ b/add_digits.c @@ -0,0 +1,22 @@ +// 258. Add Digits +#include <stdio.h> + +// given an integer 'num', repeatedly add all its digits until +// the result has onlye one digit and return it + +int addDigits(int num) { + int sum = 0; + while (num) { + sum += num % 10; + num /= 10; + } + if (sum < 10) + return sum; + else + return addDigits(sum); +} + +int main() { + printf("%d\n", addDigits(38)); // expect: 2 + printf("%d\n", addDigits(0)); // expect: 0 +} diff --git a/add_digits.cpp b/add_digits.cpp new file mode 100644 index 0000000..ec8abfa --- /dev/null +++ b/add_digits.cpp @@ -0,0 +1,26 @@ +// 258. Add Digits +#include "leetcode.h" + +// given an integer 'num', repeatedly add all its digits until +// the result has onlye one digit and return it + +class Solution { +public: + int addDigits(int num) { + int sum = 0; + while (num) { + sum += num % 10; + num /= 10; + } + if (sum < 10) + return sum; + else + return addDigits(sum); + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.addDigits(38)); // expect: 2 + printf("%d\n", obj.addDigits(0)); // expect: 0 +} diff --git a/add_one_row_tree.c b/add_one_row_tree.c new file mode 100644 index 0000000..c466e13 --- /dev/null +++ b/add_one_row_tree.c @@ -0,0 +1,49 @@ +// 623. Add One Row to Tree +#include "leetcode.h" + +/* + * given the 'root' of a binary tree and two integers 'val' and 'depth', add a + * row of nodes with value 'val' at the given depth 'depth'. note that 'root' + * node is at depth 1. the adding rule is given the integer 'depth' for each + * non-null tree node 'curr' at the depth 'depth - 1' create two tree nodes with + * value 'val' as 'curr's left subtree root and right subtree root. 'curr's + * original left subtree should be the left subtree of the new left subtree + * root. if 'depth == 1' that means that there is no depth 'depth - 1' at all, + * then create a tree node with value 'val' as the new root of the whole + * original tree, and the original tree is the new left subtree. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +struct TreeNode *addOneRow(struct TreeNode *root, int val, int depth) { + if (depth == 1) { + struct TreeNode *new = malloc(sizeof(struct TreeNode)); + new->val = val; + new->left = root; + new->right = NULL; + root = new; + return root; + } + if (depth == 2) { + struct TreeNode *left = malloc(sizeof(struct TreeNode)); + struct TreeNode *right = malloc(sizeof(struct TreeNode)); + left->val = val; + right->val = val; + left->left = root->left; + left->right = NULL; + right->right = root->right; + right->left = NULL; + root->left = left; + root->right = right; + return root; + } + if (root->left) + addOneRow(root->left, val, depth - 1); + if (root->right) + addOneRow(root->right, val, depth - 1); + return root; +} diff --git a/add_one_row_tree.py b/add_one_row_tree.py new file mode 100644 index 0000000..a790935 --- /dev/null +++ b/add_one_row_tree.py @@ -0,0 +1,48 @@ +# 623. Add One Row to Tree + +""" +given the 'root' of a binary tree and two integers 'val' and 'depth', add a +row of nodes with value 'val' at the given depth 'depth'. note that 'root' +node is at depth 1. the adding rule is given the integer 'depth' for each +non-null tree node 'curr' at the depth 'depth - 1' create two tree nodes with +value 'val' as 'curr's left subtree root and right subtree root. 'curr's +original left subtree should be the left subtree of the new left subtree +root. if 'depth == 1' that means that there is no depth 'depth - 1' at all, +then create a tree node with value 'val' as the new root of the whole +original tree, and the original tree is the new left subtree. +""" + + +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def addOneRow(self, root, val, depth): + """ + :type root: TreeNode + :type val: int + :type depth: int + :rtype: TreeNode + """ + + def dfs(root, val, depth): + if root == None: + return + if depth > 2: + dfs(root.left, val, depth - 1) + dfs(root.right, val, depth - 1) + else: + ptr = root.left + root.left = TreeNode(val, ptr, None) + ptr = root.right + root.right = TreeNode(val, None, ptr) + + if depth == 1: + ptr = TreeNode(val, root, None) + return ptr + dfs(root, val, depth) + return root diff --git a/add_row_tree.cpp b/add_row_tree.cpp new file mode 100644 index 0000000..54ebfb4 --- /dev/null +++ b/add_row_tree.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +class Solution { +public: + TreeNode *addOneRow(TreeNode *root, int val, int depth) { + if (depth-- == 1) + return new TreeNode(val, root, nullptr); + queue<TreeNode *> q; + q.push(root); + while (!q.empty()) { + bool addLevel = depth-- == 1; + size_t sz = q.size(); + for (size_t _ = 0; _ < sz; _++) { + TreeNode *curr = q.front(); + q.pop(); + if (addLevel) { + curr->left = new TreeNode(val, curr->left, nullptr); + curr->right = new TreeNode(val, nullptr, curr->right); + continue; + } + if (curr->left) + q.push(curr->left); + if (curr->right) + q.push(curr->right); + } + } + return root; + } +}; diff --git a/add_search_words_data.c b/add_search_words_data.c new file mode 100644 index 0000000..1661cfb --- /dev/null +++ b/add_search_words_data.c @@ -0,0 +1,69 @@ +// 211. Design Add and Search Words Data Structure +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * design data structure that supports adding new words and finding if a string + * matches any previously added string. implement WordDictionary class (rather + * self explanatory) + */ + +typedef struct trieNode { + struct trieNode *sub_char[26]; + bool eow; +} WordDictionary; + +WordDictionary *wordDictionaryCreate() { + WordDictionary *obj = (WordDictionary *)calloc(1, sizeof(WordDictionary)); + return obj; +} + +void wordDictionaryAddWord(WordDictionary *obj, char *word) { + while (*word) { + if (obj->sub_char[*word - 'a'] == NULL) + obj->sub_char[*word - 'a'] = + (WordDictionary *)calloc(1, sizeof(WordDictionary)); + obj = obj->sub_char[*word - 'a']; + word++; + } + obj->eow = true; +} + +bool wordDictionarySearch(WordDictionary *obj, char *word) { + while (*word) { + if (*word == '.') { + for (uint8_t i = 0; i < 26; i++) { + if (!obj->sub_char[i]) + continue; + bool a = wordDictionarySearch(obj->sub_char[i], word + 1); + if (a) + return true; + } + return false; + } else if (!obj->sub_char[*word] - 'a') + return false; + obj = obj->sub_char[*word - 'a']; + word++; + } + if (obj->eow) + return true; + else + return false; +} + +void wordDictionaryFree(WordDictionary *obj) { + for (uint8_t i = 0; i < 26; i++) + if (!obj->sub_char[i]) + continue; + free(obj); +} + +int main() { + WordDictionary *obj = wordDictionaryCreate(); + wordDictionaryAddWord(obj, "foo"); + bool param_2 = wordDictionarySearch(obj, "bar"); + wordDictionaryFree(obj); +} diff --git a/add_search_words_data.cpp b/add_search_words_data.cpp new file mode 100644 index 0000000..5c5e0f4 --- /dev/null +++ b/add_search_words_data.cpp @@ -0,0 +1,35 @@ +#include "leetcode.h" + +class WordDictionary { +public: + WordDictionary() {} + void addWord(string word) { words[word.size()].push_back(word); } + bool search(string word) { + for (auto s : words[word.size()]) + if (isEqual(s, word)) + return true; + return false; + } + +private: + unordered_map<int, vector<string>> words; + bool isEqual(string a, string b) { + for (int i = 0; i < a.size(); i++) { + if (b[i] == '.') + continue; + if (a[i] != b[i]) + return false; + } + return true; + } +}; + +int main() { + WordDictionary *obj = new WordDictionary(); + obj->addWord("WordDictionary"); + bool param_2 = obj->search("WordDictionary"); + if (param_2) + cout << "found"; + else + cout << "not found"; +} diff --git a/add_space_string.c b/add_space_string.c new file mode 100644 index 0000000..3d6bf04 --- /dev/null +++ b/add_space_string.c @@ -0,0 +1,39 @@ +// 2109. Adding Spaces to a String +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a 0-indexed string 's' and a 0-indexed integer array 'spaces' that + * describes the indices in the original string where spaces will be added. each + * space should be inserted before the character at the given index. return the + * modified string after the spaces have been added + */ + +char *addSpaces(char *s, int *spaces, int spaces_size) { + int n = strlen(s), m = n + 1 + spaces_size; + char *ans = malloc(m * sizeof(char)); + ans[m - 1] = '\0'; + int aidx = 0, bidx = 0; + int *num = malloc(spaces_size * sizeof(int)); + num[0] = spaces[0]; + for (int i = 1; i < spaces_size; i++) + num[i] = spaces[i] - spaces[i - 1]; + for (int i = 0; i < spaces_size; i++) { + strncpy(&ans[aidx], &s[bidx], num[i]); + aidx += num[i]; + bidx += num[i]; + ans[aidx] = ' '; + aidx++; + } + strncpy(&ans[aidx], &s[bidx], m - aidx); + free(num); + return ans; +} + +int main() { + char s1[] = {"LeetcodeHelpsMeLearn"}, s2[] = {"icodeinpython"}; + int n1[] = {8, 13, 15}, n2[] = {1, 5, 7, 9}; + printf("%s\n", addSpaces(s1, n1, 3)); // expect: Leetcode Helps Me Learn + printf("%s\n", addSpaces(s2, n2, 4)); // expect: i code in py thon +} diff --git a/add_space_string.cpp b/add_space_string.cpp new file mode 100644 index 0000000..2906d7a --- /dev/null +++ b/add_space_string.cpp @@ -0,0 +1,35 @@ +// 2109. Adding Spaces to a String +#include "leetcode.h" + +/* + * given a 0-indexed string 's' and a 0-indexed integer array 'spaces' that + * describes the indices in the original string where spaces will be added. each + * space should be inserted before the character at the given index. return the + * modified string after the spaces have been added + */ + +class Solution { +public: + string addSpaces(string s, vector<int> &spaces) { + int n = spaces.size(), m = s.size(), i = 0, j = 0; + string ans = ""; + while (i < m) { + if (j < n && i == spaces[j]) { + ans += ' '; + j++; + } + ans += s[i]; + i++; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> s1 = {8, 13, 15}, s2 = {1, 5, 7, 9}; + cout << obj.addSpaces("LeetcodeHelpsMeLearn", s1) + << endl; // expect: Leetcode Helps Me Learn + cout << obj.addSpaces("icodeinpython", s2) + << endl; // expect: i code in py thon +} diff --git a/add_two_num2.c b/add_two_num2.c new file mode 100644 index 0000000..cdce998 --- /dev/null +++ b/add_two_num2.c @@ -0,0 +1,63 @@ +// 445. Add Two Numbers II +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given two non-empty linked lists representing two non-negative integers. the + * most significant digit comes first and each of their nodes contains a single + * digit. add the two numbers and return the same as a linked list. you may + * assume the two numbers do not contain any leading zero, except the number 0 + * itself. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +static int append(struct ListNode *l1, struct ListNode *l2, int missing) { + int carry, val; + if (!l1) + return 0; + if (!missing) { + carry = append(l1->next, l2->next, 0); + val = l1->val + l2->val + carry; + } else { + carry = append(l1->next, l2->next, -1); + val = l1->val + carry; + } + l1->val = val % 10; + return val / 10; +} + +static int length(struct ListNode *n) { + int len; + for (len = 0; n; n = n->next) + len++; + return len; +} + +static void swap(struct ListNode **p1, struct ListNode **p2) { + struct ListNode *tmp; + tmp = *p1; + *p1 = *p2; + *p2 = tmp; +} + +struct ListNode *addTwoNumbers(struct ListNode *l1, struct ListNode *l2) { + int len1, len2, carry; + struct ListNode *head; + len1 = length(l1); + len2 = length(l2); + if (len1 < len2) + swap(&l1, &l2); + carry = append(l1, l2, abs(len1 - len2)); + if (carry) { + if (!(head = malloc(sizeof(struct ListNode)))) + return head; + head->val = 1; + head->next = l1; + } + return l1; +} diff --git a/add_two_num2.cpp b/add_two_num2.cpp new file mode 100644 index 0000000..8cc7121 --- /dev/null +++ b/add_two_num2.cpp @@ -0,0 +1,56 @@ +// 445. Add Two Numbers II +#include "leetcode.h" + +/* + * given two non-empty linked lists representing two non-negative integers. the + * most significant digit comes first and each of their nodes contains a single + * digit. add the two numbers and return the same as a linked list. you may + * assume the two numbers do not contain any leading zero, except the number 0 + * itself. + */ + +class Solution { + ListNode *append(int val, ListNode *head) { + ListNode *tmp = new ListNode(val); + tmp->next = head; + return tmp; + } + +public: + ListNode *addTwoNumbers(ListNode *l1, ListNode *l2) { + int n1 = 0, n2 = 0, carry = 0; + ListNode *curr1 = l1, *curr2 = l2, *ans = NULL; + while (curr1) + curr1 = curr1->next, n1++; + while (curr2) + curr2 = curr2->next, n2++; + curr1 = l1, curr2 = l2; + while (n1 && n2) { + int sum = 0; + if (n1 >= n2) { + sum += curr1->val; + curr1 = curr1->next; + n1--; + } + if (n2 > n1) { + sum += curr2->val; + curr2 = curr2->next; + n2--; + } + ans = append(sum, ans); + } + curr1 = ans; + ans = NULL; + while (curr1) { + curr1->val += carry; + carry = curr1->val / 10; + ans = append(curr1->val % 10, ans); + curr2 = curr1; + curr1 = curr1->next; + delete curr2; + } + if (carry) + ans = append(1, ans); + return ans; + } +}; diff --git a/additive_number.cpp b/additive_number.cpp new file mode 100644 index 0000000..d62c2e5 --- /dev/null +++ b/additive_number.cpp @@ -0,0 +1,54 @@ +// 306. Additive Number +#include "leetcode.h" + +/* + * an additive number is a string whose digits can form an additive sequence. a + * valid additive seuqnece should contain at least three numbers. except for the + * firs ttwo numbers each subsequent number in the sequence must be the sum of + * the preceding two. given a string containing only digits, return 'true' if it + * is an additive number, or 'false' otherwise. note, numbers in the additive + * sequence cannot have leading zeros, so sequence, 1,2,03, or 1,02,3 is invalid + */ + +class Solution { + string add(string n, string m) { + string res; + int i = n.size() - 1, j = m.size() - 1, carry = 0; + while (i >= 0 || j >= 0) { + int sum = + carry + (i >= 0 ? (n[i--] - '0') : 0) + (j >= 0 ? (m[j--] - '0') : 0); + res.push_back(sum % 10 + '0'); + carry = sum / 10; + } + if (carry) + res.push_back(carry + '0'); + reverse(res.begin(), res.end()); + return res; + } + bool check(string n1, string n2, string n) { + if (n1.size() > 1 && n1[0] == '0' || n2.size() > 1 && n2[0] == '0') + return false; + string sum = add(n1, n2); + if (n == sum) + return true; + if (n.size() <= sum.size() || !sum.compare(n.substr(0, sum.size()))) + return false; + else + return check(n1, sum, n.substr(sum.size())); + } + +public: + bool isAdditiveNumber(string num) { + for (int i = 1; i <= num.size() / 2; i++) + for (int j = 1; j <= (num.size() - i) / 2; j++) + if (check(num.substr(0, i), num.substr(i, j), num.substr(i + j))) + return true; + return false; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.isAdditiveNumber("112358")); // expect: 1 + printf("%d\n", obj.isAdditiveNumber("199100199")); // expect: 1 +}; diff --git a/all_nodes_binary_tree.c b/all_nodes_binary_tree.c new file mode 100644 index 0000000..05e1115 --- /dev/null +++ b/all_nodes_binary_tree.c @@ -0,0 +1,79 @@ +// 863. All Nodes Distance K in Binary Tree +#include <math.h> +#include <stdlib.h> + +/* + * given the 'root' of a binary tree, the value of a target node 'target', and + * an integer 'k', return an array of the values of all nodes that have a + * distance 'k' from the target node. you can return the answer in any order. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int depth(struct TreeNode *root) { + if (!root) + return -1; + return fmax(depth(root->left), depth(root->right)) + 1; +} + +void find_path(struct TreeNode *root, struct TreeNode *target, + struct TreeNode **data, int data_idx, struct TreeNode **path, + int *path_idx) { + if (!root) + return; + data[data_idx] = root; + if (root == target) { + *path_idx = data_idx + 1; + for (int i = 0; i < data_idx + 1; i++) + path[i] = data[i]; + return; + } + find_path(root->left, target, data, data_idx + 1, path, path_idx); + find_path(root->right, target, data, data_idx + 1, path, path_idx); +} + +void k_level_data(struct TreeNode *root, int *data, int *idx, int k) { + if (!root) + return; + if (!k) { + data[*idx] = root->val; + (*idx)++; + return; + } + k_level_data(root->left, data, idx, k - 1); + k_level_data(root->right, data, idx, k - 1); +} + +int *distanceK(struct TreeNode *root, struct TreeNode *target, int k, + int *return_size) { + int *ans = malloc(100 * sizeof(int)), idx = 0; + if (root == target) { + k_level_data(root, ans, &idx, k); + *return_size = idx; + return ans; + } + int dep = depth(root); + struct TreeNode **data = malloc((dep + 1) * sizeof(struct TreeNode *)); + struct TreeNode **path = malloc((dep + 1) * sizeof(struct TreeNode *)); + int data_idx = 0, path_idx = 0, a = 1; + find_path(root, target, data, data_idx, path, &path_idx); + k_level_data(target, ans, &idx, k); + for (int i = path_idx - 2; i >= 0; i--) { + if (!(k - a)) { + ans[idx] = path[i]->val; + idx++; + break; + } + if (path[i]->left == path[i + 1]) + k_level_data(path[i]->right, ans, &idx, k - a - 1); + else + k_level_data(path[i]->left, ans, &idx, k - a - 1); + a++; + } + *return_size = idx; + return ans; +} diff --git a/all_nodes_binary_tree.cpp b/all_nodes_binary_tree.cpp new file mode 100644 index 0000000..909352b --- /dev/null +++ b/all_nodes_binary_tree.cpp @@ -0,0 +1,53 @@ +// 863. All Nodes Distance K in Binary Tree +#include "leetcode.h" + +/* + * given the 'root' of a binary tree, the value of a target node 'target', and + * an integer 'k', return an array of the values of all nodes that have a + * distance 'k' from the target node. you can return the answer in any order. + */ + +class Solution { + void dfs(TreeNode *root, unordered_map<TreeNode *, TreeNode *> &back_edge, + TreeNode *target) { + if (!root || root == target) + return; + if (root->left) { + back_edge[root->left] = root; + dfs(root->left, back_edge, target); + } + if (root->right) { + back_edge[root->right] = root; + dfs(root->right, back_edge, target); + } + } + +public: + vector<int> distanceK(TreeNode *root, TreeNode *target, int k) { + unordered_map<TreeNode *, TreeNode *> back_edge; + unordered_set<TreeNode *> visited; + vector<int> ans; + dfs(root, back_edge, target); + queue<TreeNode *> q; + q.push(target); + while (!q.empty() && k >= 0) { + int s = q.size(); + while (s--) { + TreeNode *curr = q.front(); + int val = curr->val; + q.pop(); + visited.insert(curr); + if (!k) + ans.push_back(val); + if (!visited.count(back_edge[curr]) && back_edge[curr]) + q.push(back_edge[curr]); + if (!visited.count(curr->left) && curr->left) + q.push(curr->left); + if (!visited.count(curr->right) && curr->right) + q.push(curr->right); + } + k--; + } + return ans; + } +}; diff --git a/all_path_src_target.cpp b/all_path_src_target.cpp new file mode 100644 index 0000000..ae261aa --- /dev/null +++ b/all_path_src_target.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + vvd(int) allPathsSourceTarget(vvd(int) & graph) { + vvd(int) ans; + vector<int> path; + dfs(graph, ans, path, 0); + return ans; + } + +private: + void dfs(vvd(int) & graph, vvd(int) & ans, vector<int> &path, int curr) { + path.push_back(curr); + if (curr == graph.size() - 1) + ans.push_back(path); + else + for (auto it : graph[curr]) + dfs(graph, ans, path, it); + path.pop_back(); + } +}; + +int main() { + Solution obj; + vvd(int) graph = {{1, 2}, {3}, {3}, {}}; + for (auto i : obj.allPathsSourceTarget(graph)) + for (auto j : i) + cout << j << ' '; +} diff --git a/all_path_src_target.rs b/all_path_src_target.rs new file mode 100644 index 0000000..c406cd8 --- /dev/null +++ b/all_path_src_target.rs @@ -0,0 +1,54 @@ +use std::collections::VecDeque; +struct Solution; + +impl Solution { + pub fn all_paths_source_target(graph: Vec<Vec<i32>>) -> Vec<Vec<i32>> { + let (src, dst, mut rev) = (0, (graph.len() - 1) as i32, vec![0; graph.len()]); + for (u, adj) in graph.iter().enumerate() { + for &v in adj { + rev[v as usize] += 1; + } + } + let mut top_sort_q = VecDeque::new(); + for v in 0..graph.len() { + if rev[v] == 0 { + top_sort_q.push_back(v as i32); + } + } + let mut ans = vec![vec![]; graph.len()]; + while let Some(v) = top_sort_q.pop_front() { + if v == src { + ans[src as usize].push(vec![src]) + } + if v == dst { + break; + } + for &next in graph[v as usize].iter() { + let (ans_v, ans_next) = { + if v < next { + let (ans_left, ans_right) = ans.split_at_mut(v as usize + 1); + (&ans_left[v as usize], &mut ans_right[(next - v - 1) as usize]) + } else { + let (ans_left, ans_right) = ans.split_at_mut(next as usize + 1); + (&ans_right[(v - next - 1) as usize], &mut ans_left[next as usize]) + } + }; + for path in ans_v { + let mut new_path = path.clone(); + new_path.push(next); + ans_next.push(new_path); + } + rev[next as usize] -= 1; + if rev[next as usize] == 0 { + top_sort_q.push_back(next); + } + } + } + std::mem::take(&mut ans[dst as usize]) + } +} + +fn main() { + let graph = vec![vec![1,2],vec![3],vec![3],vec![]]; + print!("{:?}", Solution::all_paths_source_target(graph)); +} diff --git a/all_possible_full_tree.c b/all_possible_full_tree.c new file mode 100644 index 0000000..6c64c94 --- /dev/null +++ b/all_possible_full_tree.c @@ -0,0 +1,74 @@ +// 894. All Possible Full Binary Trees +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer 'n', return a list of all possible full binary trees with + * 'n' nodes. each node of each tree in the answer must have 'node.val == 0'. + * each element of the answer is the root node of one possible tree. you may + * return the final list of trees in any order. a full binary tree is a binary + * tree where each node has exactly zero or two children + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +struct TreeNode **allPossibleFBT(int n, int *return_size) { + if (!n % 2) { + *return_size = 0; + return NULL; + } + if (n == 1) { + struct TreeNode *root = malloc(sizeof(struct TreeNode)); + root->val = 0; + root->left = NULL; + root->right = NULL; + struct TreeNode **ans = malloc(sizeof(struct TreeNode *)); + *return_size = 1; + ans[0] = root; + return ans; + } + if (n == 3) { + struct TreeNode *root = malloc(sizeof(struct TreeNode)); + struct TreeNode *left = malloc(sizeof(struct TreeNode)); + struct TreeNode *right = malloc(sizeof(struct TreeNode)); + root->val = 0; + left->val = 0; + right->val = 0; + left->left = NULL; + left->right = NULL; + right->left = NULL; + right->right = NULL; + root->left = left; + root->right = right; + struct TreeNode **ans = malloc(sizeof(struct TreeNode)); + *return_size = 1; + ans[0] = root; + return ans; + } + struct TreeNode **ans = malloc(5000 * sizeof(struct TreeNode)); + int idx = 0; + for (int i = 1; i <= (n - 1); i += 2) { + int *cnt_l = calloc(1, sizeof(int)); + int *cnt_r = calloc(1, sizeof(int)); + struct TreeNode **l_tree = allPossibleFBT(i, cnt_l); + struct TreeNode **r_tree = allPossibleFBT(n - 1 - i, cnt_r); + for (int j = 0; j < (*cnt_l); j++) { + for (int k = 0; k < (*cnt_r); k++) { + struct TreeNode *new = malloc(sizeof(struct TreeNode)); + new->val = 0; + new->left = l_tree[j]; + new->right = r_tree[k]; + ans[idx] = new; + idx++; + } + } + free(cnt_l), free(cnt_r); + } + ans = realloc(ans, idx * sizeof(struct TreeNode *)); + *return_size = idx; + return ans; +} diff --git a/all_possible_full_tree.cpp b/all_possible_full_tree.cpp new file mode 100644 index 0000000..ca54570 --- /dev/null +++ b/all_possible_full_tree.cpp @@ -0,0 +1,40 @@ +// 894. All Possible Full Binary Trees +#include "leetcode.h" + +/* + * given an integer 'n', return a list of all possible full binary trees with + * 'n' nodes. each node of each tree in the answer must have 'node.val == 0'. + * each element of the answer is the root node of one possible tree. you may + * return the final list of trees in any order. a full binary tree is a binary + * tree where each node has exactly zero or two children + */ + +class Solution { +public: + vector<TreeNode *> allPossibleFBT(int n) { + unordered_map<int, vector<TreeNode *>> memo; + vector<TreeNode *> ans; + if (n < 1 || !n % 2) + return ans; + if (memo.find(n) != memo.end()) + return memo[n]; + if (n == 1) { + ans.push_back(new TreeNode(0)); + memo[1] = ans; + return ans; + } + for (int i = 1; i < n; i += 2) { + vector<TreeNode *> left = allPossibleFBT(i); + vector<TreeNode *> right = allPossibleFBT(n - 1 - i); + for (int j = 0; j < left.size(); j++) + for (int k = 0; k < right.size(); k++) { + TreeNode *root = new TreeNode(0); + root->left = left[j]; + root->right = right[k]; + ans.push_back(root); + } + } + memo[n] = ans; + return ans; + } +}; diff --git a/alphabet_board_path.c b/alphabet_board_path.c new file mode 100644 index 0000000..16fa77f --- /dev/null +++ b/alphabet_board_path.c @@ -0,0 +1,70 @@ +// 1138. Alphabet Board Path +#include <stdio.h> +#include <stdlib.h> + +/* + * on an alphabet board, we start position [0,0], corresponding to character + * 'board[0][0]'. here, 'board = ["abcde", "fghij", "klmno", "pqrst", "uvwxy", + * "z"]' as show in the diagram (see page). return a sequence of moves that + * makes our answer equal to 'target' in the minimum numbe of moves. (in any + * order/path) + */ + +char *alphabetBoardPath(char *target) { + char map[26][2] = {0}; + int i; + for (i = 0; i < 26; i++) { + map[i][0] = i % 5; + map[i][1] = i / 5; + } + char *curr, *prev; + curr = "a"; + prev = target; + char *ans = (char *)malloc(100 * sizeof(char)); + int ans_size = 100; + i = 0; + while (*prev) { + if (ans_size - i < 11) { + ans_size += 11; + char *new_ans = (char *)realloc(ans, ans_size * sizeof(char)); + if (new_ans) + ans = new_ans; + } + int j = (int)(*prev) - (int)('a'); + int k = (int)(*curr) - (int)('a'); + int dx = map[j][0] - map[k][0]; + int dy = map[j][1] - map[k][1]; + if (dx < 0) + while (dx) { + ans[i++] = 'L'; + dx++; + } + if (dy > 0) + while (dy) { + ans[i++] = 'D'; + dy--; + } + if (dy < 0) + while (dy) { + ans[i++] = 'U'; + dy++; + } + if (dx > 0) + while (dx) { + ans[i++] = 'R'; + dx--; + } + ans[i++] = '!'; + curr = prev; + prev++; + } + ans[i] = '\0'; + return ans; +} + +int main() { + char *t1 = "leet"; + char *t2 = "code"; + printf("%s\n", alphabetBoardPath(t1)); // expect: DDR!UURRR!!DDD! + printf("%s\n", alphabetBoardPath(t2)); // expect: RR!DDRR!UUL!R! +} diff --git a/alphabet_board_path.cpp b/alphabet_board_path.cpp new file mode 100644 index 0000000..874e201 --- /dev/null +++ b/alphabet_board_path.cpp @@ -0,0 +1,44 @@ +// 1138. Alphabet Board Path +#include "leetcode.h" + +/* + * on an alphabet board, we start position [0,0], corresponding to character + * 'board[0][0]'. here, 'board = ["abcde", "fghij", "klmno", "pqrst", "uvwxy", + * "z"]' as show in the diagram (see page). return a sequence of moves that + * makes our answer equal to 'target' in the minimum numbe of moves. (in any + * order/path) + */ + +class Solution { +public: + string alphabetBoardPath(string target) { + unordered_map<char, pair<int, int>> mp; + for (int i = 0; i < 26; ++i) + mp[i + 'a'] = {i / 5, i % 5}; + target = 'a' + target; + string path; + int dx = 0, dy = 0; + for (int i = 1; i < target.size(); ++i) { + auto curr = mp[target[i]]; + auto prev = mp[target[i - 1]]; + dx = curr.first - prev.first; + dy = curr.second - prev.second; + if (dy < 0) + path += string(-dy, 'L'); + if (dx < 0) + path += string(-dx, 'U'); + if (dy > 0) + path += string(dy, 'R'); + if (dx > 0) + path += string(dx, 'D'); + path += '!'; + } + return path; + } +}; + +int main() { + Solution boj; + cout << boj.alphabetBoardPath("leet") << endl; // expect: DDR!UURRR!!DDD! + cout << boj.alphabetBoardPath("code") << endl; // expect: RR!DDRR!UUL!R! +} diff --git a/amount_time_bt_infect.c b/amount_time_bt_infect.c new file mode 100644 index 0000000..6af96e1 --- /dev/null +++ b/amount_time_bt_infect.c @@ -0,0 +1,84 @@ +// 2385. Amount of Time for Binary Tree to Be Infected +#include "leetcode.h" + +/* + * given the 'root' of a binary tree with unique values, and an integer 'start'. + * at minute 0, an infection starts from the node with value 'start' each + * minute, a node becomes infected if the node is currently uninfected, or the + * node is adjacent to an infected node. return the number of minutes needed for + * the entire tree to be infected. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int depthAndFindVal(struct TreeNode *root, int val, bool *exist, + int *height_start) { + if (!root) + return -1; + int height = 1 + fmax(depthAndFindVal(root->left, val, exist, height_start), + depthAndFindVal(root->right, val, exist, height_start)); + if (root->val == val) { + *exist = true; + *height_start = height; + } + return height; +} + +int depth(struct TreeNode *root) { + if (!root) + return -1; + return 1 + fmax(depth(root->left), depth(root->right)); +} + +void findPath(struct TreeNode *root, int start, struct TreeNode **data, + int data_idx, struct TreeNode **path, int *path_idx) { + if (!root) + return; + data[data_idx] = root; + if (root->val == start) { + *path_idx = data_idx + 1; + for (int i = 0; i < *path_idx; i++) + path[i] = data[i]; + return; + } + findPath(root->left, start, data, data_idx + 1, path, path_idx); + findPath(root->right, start, data, data_idx + 1, path, path_idx); +} + +int amountOfTime(struct TreeNode *root, int start) { + bool left_exist = false, right_exist = false; + int height_start = 0, data_idx = 0, path_idx = 0, ans; + + int left_height = + depthAndFindVal(root->left, start, &left_exist, &height_start) + 1; + int right_height = + depthAndFindVal(root->right, start, &right_exist, &height_start) + 1; + + if (root->val == start) + return fmax(left_height, right_height); + + int n = fmax(left_height, right_height); + struct TreeNode **data = malloc(n * sizeof(struct TreeNode *)); + struct TreeNode **path = malloc(n * sizeof(struct TreeNode *)); + struct TreeNode *tmp = left_exist ? root->left : root->right; + findPath(tmp, start, data, data_idx, path, &path_idx); + ans = left_exist ? right_height + path_idx : left_height + path_idx; + + int start_height = depth(path[path_idx - 1]); + ans = fmax(ans, start_height); + int k = 1; + for (int i = path_idx - 2; i >= 0; i--) { + int d; + if (path[i]->left == path[i + 1]) + d = depth(path[i]->right); + else + d = depth(path[i]->left); + ans = fmax(ans, d + 1 + k); + k++; + } + return ans; +} diff --git a/amount_time_bt_infect.py b/amount_time_bt_infect.py new file mode 100644 index 0000000..9592126 --- /dev/null +++ b/amount_time_bt_infect.py @@ -0,0 +1,59 @@ +# 2385. Amount of Time for Binary Tree to Be Infected + +""" +given the 'root' of a binary tree with unique values, and an integer 'start'. +at minute 0, an infection starts from the node with value 'start' each +minute, a node becomes infected if the node is currently uninfected, or the +node is adjacent to an infected node. return the number of minutes needed for +the entire tree to be infected. +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def amountOfTime(self, root, start): + """ + :type root: Optional[TreeNode] + :type start: int + :rtype: int + """ + + def dfs(node): + if node is None: + return + if node.left: + graph[node.val].append(node.left.val) + graph[node.left.val].append(node.val) + if node.right: + graph[node.val].append(node.right.val) + graph[node.right.val].append(node.val) + dfs(node.left) + dfs(node.right) + + graph = defaultdict(list) + dfs(root) + visited = set() + queue = deque([start]) + time = -1 + while queue: + time += 1 + for _ in range(len(queue)): + current_node = queue.popleft() + visited.add(current_node) + for neighbor in graph[current_node]: + if neighbor not in visited: + queue.append(neighbor) + return time + + +if __name__ == "__main__": + obj = Solution() + print(obj.amountOfTime(root=[1, 5, 3, null, 4, 10, 6, 9, 2], start=3)) + print(obj.amountOfTime(root=[1], start=1)) diff --git a/append_char_str_make_subseq.c b/append_char_str_make_subseq.c new file mode 100644 index 0000000..0718a95 --- /dev/null +++ b/append_char_str_make_subseq.c @@ -0,0 +1,28 @@ +// 2486. Append Characters to String to Make Subsequence +#include "leetcode.h" + +/* + * given two strings 's' and 't' consisting of only lowercase english letters. + * return the minimum number of characters that need to be appened to the end of + * 's' so that 't' becomes a subsequence of 's'. a subsequence is a string that + * can be derived from another string by deleting some or no characters without + * changing the order of the remaining characters. + */ + +int appendCharacters(char *s, char *t) { + int ns = strlen(s), nt = strlen(t), p1 = 0, p2 = 0; + while (p1 < ns && p2 < nt) { + if (s[p1] == t[p2]) + p2++; + p1++; + } + return nt - p2; +} + +int main() { + char *s1 = "coaching", *t1 = "coding", *s2 = "abcde", *t2 = "a", *s3 = "z", + *t3 = "abcde"; + printf("%d\n", appendCharacters(s1, t1)); // expect: 4 + printf("%d\n", appendCharacters(s2, t2)); // expect: 0 + printf("%d\n", appendCharacters(s3, t3)); // expect: 5 +} diff --git a/append_char_str_make_subseq.py b/append_char_str_make_subseq.py new file mode 100644 index 0000000..1e78830 --- /dev/null +++ b/append_char_str_make_subseq.py @@ -0,0 +1,30 @@ +# 2486. Append Characters to String to Make Subsequence + +""" +given two strings 's' and 't' consisting of only lowercase english letters. +return the minimum number of characters that need to be appened to the end of +'s' so that 't' becomes a subsequence of 's'. a subsequence is a string that +can be derived from another string by deleting some or no characters without +changing the order of the remaining characters. +""" + + +class Solution(object): + def appendCharacters(self, s, t): + """ + :type s: str + :type t: str + :rtype: int + """ + n = iter(s) + for i, c in enumerate(t): + if c not in n: + return len(t) - i + return 0 + + +if __name__ == "__main__": + obj = Solution() + print(obj.appendCharacters("coaching", "coding")) + print(obj.appendCharacters("abcde", "a")) + print(obj.appendCharacters("z", "abcde")) diff --git a/arithmetic_progression.c b/arithmetic_progression.c new file mode 100644 index 0000000..6358900 --- /dev/null +++ b/arithmetic_progression.c @@ -0,0 +1,30 @@ +// 1502. Can Make Arithmetic Progression From Sequence +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * a sequence of numbers is called an arithmetic progression if the difference + * between any two consecutive elements is the same. gien an array of numbers + * 'arr', return true if the array can rearranged to form an arithmetic + * progression. otherwise, return false. + */ + +int cmp(const void *a, const void *b) { + return *(const int *)a - *(const int *)b; +} + +bool canMakeArithmeticProgression(int *arr, int arr_size) { + qsort(arr, arr_size, sizeof(int), cmp); + int diff = arr[1] - arr[0]; + for (int i = 2; i < arr_size; i++) + if (arr[i] - arr[i - 1] != diff) + return false; + return true; +} + +int main() { + int a1[] = {3, 5, 1}, a2[] = {1, 2, 4}; + printf("%d\n", canMakeArithmeticProgression(a1, 3)); // expect: 1 + printf("%d\n", canMakeArithmeticProgression(a2, 3)); // expect: 0 +} diff --git a/arithmetic_progression.cpp b/arithmetic_progression.cpp new file mode 100644 index 0000000..4c1c996 --- /dev/null +++ b/arithmetic_progression.cpp @@ -0,0 +1,44 @@ +// 1502. Can Make Arithmetic Progression From Sequence +#include "leetcode.h" + +/* + * a sequence of numbers is called an arithmetic progression if the difference + * between any two consecutive elements is the same. gien an array of numbers + * 'arr', return true if the array can rearranged to form an arithmetic + * progression. otherwise, return false. + */ + +class Solution { +public: + bool canMakeArithmeticProgression(vector<int> &arr) { + if (arr.size() <= 2) + return true; + auto min = *min_element(begin(arr), end(arr)); + auto max = *max_element(begin(arr), end(arr)); + if ((max - min) % (arr.size() - 1)) + return false; + int d = (max - min) / (arr.size() - 1); + for (int i = 0; i < arr.size();) { + if (arr[i] == min + i * d) + i++; + else if ((arr[i] - min) % d) + return false; + else { + int pos = (arr[i] - min) / d; + if (pos < i) + return false; + if (arr[pos] == arr[i]) + return false; + swap(arr[i], arr[pos]); + } + } + return true; + } +}; + +int main() { + Solution obj; + vector<int> a1 = {3, 5, 1}, a2 = {1, 2, 4}; + printf("%d\n", obj.canMakeArithmeticProgression(a1)); // expect: 1 + printf("%d\n", obj.canMakeArithmeticProgression(a2)); // expect: 0 +} diff --git a/arithmetic_sequence.c b/arithmetic_sequence.c new file mode 100644 index 0000000..5e60eda --- /dev/null +++ b/arithmetic_sequence.c @@ -0,0 +1,62 @@ +// 1630. Arithmetic Subarrays +#include "leetcode.h" + +/* + * a sequence of numbers is called arithmetic if it consists of at least two + * elements and the difference between every two consecutive elements is the + * same. more formally, a sequence 's' is arithmetic if and only if 's[i + 1] - + * s[i] == s[1] - s[0]' for all valid 'i'. you are given an array of 'n' + * integers 'nums' and two arrays of 'm' integers each 'l' and 'r' respectively + * representingthe 'm' range queries where the i'th query isthe range '[l[i], + * r[i]]'. all the arrays are 0-indexed. return a list of boolean elements 'ans' + * where 'ans[i]' is true if the subarray 'nums[l[i]], nums[l[i] + 1], ..., + * nums[r[i]]' can be rearrange to form an arithmetic sequence and false + * otherwise + */ + +int cmp(const void *a, const void *b) { + return *(const int *)a - *(const int *)b; +} + +bool check(int *nums, int start, int size) { + int *arr = (int *)malloc(size * sizeof(int)); + memcpy(arr, nums + start, size * sizeof(int)); + qsort(arr, size, sizeof(int), cmp); + int res = arr[1] - arr[0]; + for (int i = 1; i < size; i++) + if (arr[i] - arr[i - 1] != res) { + free(arr); + return false; + } + free(arr); + return true; +} + +bool *checkArithmeticSubarrays(int *nums, int nums_size, int *l, int l_size, + int *r, int r_size, int *return_size) { + *return_size = l_size; + bool *ans = (bool *)malloc((*return_size) * sizeof(bool)); + for (int i = 0; i < (*return_size); i++) { + int start = l[i], size = r[i] - l[i] + 1; + ans[i] = check(nums, start, size); + } + return ans; +} + +int main() { + int n1[] = {4, 6, 5, 9, 3, 7}, + n2[] = {-12, -9, -3, -12, -6, 15, 20, -25, -20, -15, -10}; + int l1[] = {0, 0, 2}, r1[] = {2, 3, 5}, l2[] = {0, 1, 6, 4, 8, 7}, + r2[] = {4, 4, 9, 7, 9, 10}; + int rs1[] = {}, rs2[] = {}; + bool *cas1 = checkArithmeticSubarrays(n1, ARRAY_SIZE(n1), l1, ARRAY_SIZE(l1), + r1, ARRAY_SIZE(r1), rs1); + bool *cas2 = checkArithmeticSubarrays(n2, ARRAY_SIZE(n2), l2, ARRAY_SIZE(l2), + r2, ARRAY_SIZE(r2), rs2); + for (int i = 0; i < 3; i++) + printf("%d", cas1[i]); // expect: 1 0 1 + printf("\n"); + for (int i = 0; i < 6; i++) + printf("%d", cas2[i]); // expect: 0 1 0 0 1 1 + printf("\n"); +} diff --git a/arithmetic_sequence.py b/arithmetic_sequence.py new file mode 100644 index 0000000..e8c1230 --- /dev/null +++ b/arithmetic_sequence.py @@ -0,0 +1,65 @@ +# 1630. Arithmetic Subarrays + +""" +a sequence of numbers is called arithmetic if it consists of at least two +elements and the difference between every two consecutive elements is the +same. more formally, a sequence 's' is arithmetic if and only if 's[i + 1] - +s[i] == s[1] - s[0]' for all valid 'i'. you are given an array of 'n' +integers 'nums' and two arrays of 'm' integers each 'l' and 'r' respectively +representingthe 'm' range queries where the i'th query isthe range '[l[i], +r[i]]'. all the arrays are 0-indexed. return a list of boolean elements 'ans' +where 'ans[i]' is true if the subarray 'nums[l[i]], nums[l[i] + 1], ..., +nums[r[i]]' can be rearrange to form an arithmetic sequence and false +otherwise +""" + + +class Solution(object): + def is_arithmetic(self, nums, l, r): + max_val, min_val = float("-inf"), float("inf") + for i in range(l, r + 1): + max_val = max(nums[i], max_val) + min_val = min(nums[i], min_val) + length = r - l + 1 + if (max_val - min_val) % (length - 1) != 0: + return False + diff = (max_val - min_val) // (length - 1) + if diff == 0: + return True + visited = [False] * length + for i in range(l, r + 1): + val = nums[i] + if (val - min_val) % diff != 0: + return False + else: + pos = (val - min_val) // diff + if visited[pos]: + return False + visited[pos] = True + return True + + def checkArithmeticSubarrays(self, nums, l, r): + """ + :type nums: List[int] + :type l: List[int] + :type r: List[int] + :rtype: List[bool] + """ + ans = [] + for i in range(len(l)): + ans.append(self.is_arithmetic(nums, l[i], r[i])) + return ans + + +if __name__ == "__main__": + obj = Solution() + print( + obj.checkArithmeticSubarrays(nums=[4, 6, 5, 9, 3, 7], l=[0, 0, 2], r=[2, 3, 5]) + ) + print( + obj.checkArithmeticSubarrays( + nums=[-12, -9, -3, -12, -6, 15, 20, -25, -20, -15, -10], + l=[0, 1, 6, 4, 8, 7], + r=[4, 4, 9, 7, 9, 10], + ) + ) diff --git a/arithmetic_slices2.c b/arithmetic_slices2.c new file mode 100644 index 0000000..184d136 --- /dev/null +++ b/arithmetic_slices2.c @@ -0,0 +1,58 @@ +// 446. Arithmetic Slices II - Subsequence +#include "leetcode.h" +#include "lib/uthash/src/uthash.h" + +/* + * given an integer array 'nums', return the number of all the arithmetic + * subsequences of 'nums'. a sequence of numbers is called arithmetic if it + * consists of at least three elements and if the difference between any two + * consecutive elements is the same. the test cases are generated such that the + * answer fits in a 32-bit integer. + */ + +struct seq_hash { + long long diff; + int cnt; + UT_hash_handle hh; +}; + +int numberOfArithmeticSlices(int *nums, int nums_size) { + int ans = 0; + struct seq_hash **const dp = calloc(nums_size, sizeof(struct seq_hash *)); + for (int end = 1; end < nums_size; ++end) { + for (int i = 0; i < end; i++) { + const long long diff = ((long long)nums[end]) - nums[i]; + struct seq_hash *end_entry; + HASH_FIND(hh, dp[end], &diff, sizeof(diff), end_entry); + if (!end_entry) { + end_entry = malloc(sizeof(struct seq_hash)); + end_entry->diff = diff; + end_entry->cnt = 0; + HASH_ADD(hh, dp[end], diff, sizeof(end_entry->diff), end_entry); + } + struct seq_hash *prev_entry; + HASH_FIND(hh, dp[i], &diff, sizeof(diff), prev_entry); + if (!prev_entry) + ++end_entry->cnt; + else { + end_entry->cnt += prev_entry->cnt + 1; + ans += prev_entry->cnt; + } + } + } + for (int i = 0; i < nums_size; i++) { + struct seq_hash *entry, *tmp; + HASH_ITER(hh, dp[i], entry, tmp) { + HASH_DEL(dp[i], entry); + free(entry); + } + } + free(dp); + return ans; +} + +int main() { + int n1[] = {2, 4, 6, 8, 10}, n2[] = {7, 7, 7, 7, 7}; + printf("%d\n", numberOfArithmeticSlices(n1, ARRAY_SIZE(n1))); // expect: 7 + printf("%d\n", numberOfArithmeticSlices(n2, ARRAY_SIZE(n2))); // expect: 16 +} diff --git a/arithmetic_slices2.cpp b/arithmetic_slices2.cpp new file mode 100644 index 0000000..8dd553c --- /dev/null +++ b/arithmetic_slices2.cpp @@ -0,0 +1,35 @@ +#include "leetcode.h" + +class Solution { +public: + int numberOfArithmeticSlices(vector<int> &nums) { + unordered_map<int, vector<int>> num_idx; + vvd(int) dp(nums.size(), vector<int>(nums.size())); + int ans = 0; + for (auto i = 0; i < nums.size(); ++i) + num_idx[nums[i]].push_back(i); + for (auto i = 0; i < nums.size(); ++i) { + for (int j = 0; j < i; j++) { + auto prev = 2l * nums[j] - nums[i]; + if (prev < INT_MIN || prev > INT_MAX) + continue; + auto it = num_idx.find(prev); + if (it != end(num_idx)) { + for (auto k : it->second) { + if (k >= j) + break; + dp[i][j] += dp[j][k] + 1; + } + } + ans += dp[i][j]; + } + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums = {2, 4, 6, 8, 10}; + cout << obj.numberOfArithmeticSlices(nums); +} diff --git a/arithmetic_slices2.py b/arithmetic_slices2.py new file mode 100644 index 0000000..c2a7444 --- /dev/null +++ b/arithmetic_slices2.py @@ -0,0 +1,35 @@ +# 446. Arithmetic Slices II - Subsequence +from collections import defaultdict + +""" +given an integer array 'nums', return the number of all the arithmetic +subsequences of 'nums'. a sequence of numbers is called arithmetic if it +consists of at least three elements and if the difference between any two +consecutive elements is the same. the test cases are generated such that the +answer fits in a 32-bit integer. +""" + + +class Solution(object): + def numberOfArithmeticSlices(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + n = len(nums) + total_cnt = 0 + dp = [defaultdict(int) for _ in range(n)] + for i in range(1, n): + for j in range(i): + diff = nums[i] - nums[j] + dp[i][diff] += 1 + if diff in dp[j]: + dp[i][diff] += dp[j][diff] + total_cnt += dp[j][diff] + return total_cnt + + +if __name__ == "__main__": + obj = Solution() + print(obj.numberOfArithmeticSlices(nums=[2, 4, 6, 8, 10])) # expect: 7 + print(obj.numberOfArithmeticSlices(nums=[7, 7, 7, 7, 7])) # expect: 16 diff --git a/arithmetic_slices2.rs b/arithmetic_slices2.rs new file mode 100644 index 0000000..41162f0 --- /dev/null +++ b/arithmetic_slices2.rs @@ -0,0 +1,30 @@ +use std::collections::HashMap; +struct Solution; + +impl Solution { + pub fn number_of_arithmetic_slices(nums: Vec<i32>) -> i32 { + let (n, mut ans) = (nums.len(), 0); + let mut map: Vec<HashMap<i64, i32>> = Vec::with_capacity(n); + for i in 1..n { + for j in 0..i { + let diff: i64 = nums[i] as i64 - nums[j] as i64; + let count = match map.len() { + 0 => 0, + _ => *map[j].get(&diff).unwrap_or(&0) + }; + if map.len() < i + 1 { + let n = i - map.len() + 1; + map.extend(vec![HashMap::new(); n]); + } + map[i].entry(diff).and_modify(|x| *x += count + 1).or_insert(count + 1); + ans += count; + } + } + ans + } +} + +fn main() { + let nums = vec![2,4,6,8,10]; + print!("{}", Solution::number_of_arithmetic_slices(nums)); +} diff --git a/assign_cookies.c b/assign_cookies.c new file mode 100644 index 0000000..cc55512 --- /dev/null +++ b/assign_cookies.c @@ -0,0 +1,38 @@ +// 455. Assign Cookies +#include "leetcode.h" + +/* + * assume you are an awesome parent and want to give your children some cookies. + * but you should give each child at most one cookie. each child 'i' has a greed + * factor 'g[i]', which is the minimum size of a cookie that the child will be + * content with; and each cookie 'j' has a size 's[j]' if 's[j] >= g[i]', we can + * assign the cookie 'j' to the child 'i', and the child 'i' will be content. + * your goal is to maximise the number of your content children and output the + * maximum number. + */ + +int cmp(const void *a, const void *b) { + return *(const int *)a > *(const int *)b; +} + +int findContentChildren(int *g, int g_size, int *s, int s_size) { + qsort(g, g_size, sizeof(int), cmp); + qsort(s, s_size, sizeof(int), cmp); + int s_idx = 0, g_idx = 0, cnt = 0; + while (s_idx < s_size && g_idx < g_size) { + if (s[s_idx] < g[g_idx]) + s_idx++; + else + s_idx++, g_idx++, cnt++; + } + return cnt; +} + +int main() { + int g1[] = {1, 2, 3}, g2[] = {1, 2}; + int s1[] = {1, 1}, s2[] = {1, 2, 3}; + printf("%d\n", findContentChildren(g1, ARRAY_SIZE(g1), s1, + ARRAY_SIZE(s1))); // expect: 1 + printf("%d\n", findContentChildren(g2, ARRAY_SIZE(g2), s2, + ARRAY_SIZE(s2))); // expect: 2 +} diff --git a/assign_cookies.py b/assign_cookies.py new file mode 100644 index 0000000..87e4f68 --- /dev/null +++ b/assign_cookies.py @@ -0,0 +1,37 @@ +# 455. Assign Cookies + +""" +assume you are an awesome parent and want to give your children some cookies. +but you should give each child at most one cookie. each child 'i' has a greed +factor 'g[i]', which is the minimum size of a cookie that the child will be +content with; and each cookie 'j' has a size 's[j]' if 's[j] >= g[i]', we can +assign the cookie 'j' to the child 'i', and the child 'i' will be content. +your goal is to maximise the number of your content children and output the +maximum number. +""" + + +class Solution(object): + def findContentChildren(self, g, s): + """ + :type g: List[int] + :type s: List[int] + :rtype: int + """ + g.sort(reverse=True) + s.sort(reverse=True) + res, i, j = 0, 0, 0 + while i < len(g) and j < len(s): + if g[i] <= s[j]: + res += 1 + i += 1 + j += 1 + else: + i += 1 + return res + + +if __name__ == "__main__": + obj = Solution() + print(obj.findContentChildren(g=[1, 2, 3], s=[1, 1])) # expect: 1 + print(obj.findContentChildren(g=[1, 2], s=[1, 2, 3])) # expect: 2 diff --git a/asteroid_collision.c b/asteroid_collision.c new file mode 100644 index 0000000..3d7393a --- /dev/null +++ b/asteroid_collision.c @@ -0,0 +1,55 @@ +// 735. Asteroid Collision +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array 'asteroids' o intergers representing asteroids in a row. for + * each asteroid, the absolute value represents its size, and the sign + * represents its direction (positive meaning right, negative meaning left). + * each asteroid moves at the same speed. find out the state of the asteroids + * after all collisions. if two asteroids meet the smaller one will explode. if + * both are the same size, both will explode. two asteroids moving in the same + * direction will never meet. + */ + +int *asteroidCollision(int *asteroids, int asteroids_size, int *return_size) { + int n = asteroids_size, ans_idx = 0; + int *ans = malloc(n * sizeof(int)); + ans[ans_idx] = asteroids[ans_idx]; + for (int i = 0; i < n; i++) { + ans_idx++; + ans[ans_idx] = asteroids[i]; + while (ans_idx && ans[ans_idx] < 0 && ans[ans_idx - 1]) { + if (abs(ans[ans_idx]) == abs(ans[ans_idx - 1])) { + ans_idx -= 2; + continue; + } + if (abs(ans[ans_idx]) > abs(ans[ans_idx - 1])) { + ans[ans_idx - 1] = ans[ans_idx]; + ans_idx--; + } else + ans_idx--; + } + } + *return_size = ans_idx + 1; + ans = realloc(ans, (*return_size) * sizeof(int)); + return ans; +} + +int main() { + int a1[] = {5, 10, -5}, a2[] = {8, -8}, a3[] = {10, 2, -5}; + int as1 = 3, as2 = 2, as3 = 3; + int rs1[] = {}, rs2[] = {}, rs3[] = {}; + int *ac1 = asteroidCollision(a1, as1, rs1); + int *ac2 = asteroidCollision(a2, as2, rs2); + int *ac3 = asteroidCollision(a3, as3, rs3); + for (int i = 0; i < as1; i++) + printf("%d ", ac1[i]); // expect: 5 10 + printf("\n"); + for (int i = 0; i < as2; i++) + printf("%d ", ac2[i]); // expect: + printf("\n"); + for (int i = 0; i < as3; i++) + printf("%d ", ac3[i]); // expect: 10 + printf("\n"); +} diff --git a/asteroid_collision.cpp b/asteroid_collision.cpp new file mode 100644 index 0000000..3597c8a --- /dev/null +++ b/asteroid_collision.cpp @@ -0,0 +1,52 @@ +// 735. Asteroid Collision +#include "leetcode.h" + +/* + * given an array 'asteroids' o intergers representing asteroids in a row. for + * each asteroid, the absolute value represents its size, and the sign + * represents its direction (positive meaning right, negative meaning left). + * each asteroid moves at the same speed. find out the state of the asteroids + * after all collisions. if two asteroids meet the smaller one will explode. if + * both are the same size, both will explode. two asteroids moving in the same + * direction will never meet. + */ + +class Solution { +public: + vector<int> asteroidCollision(vector<int> &asteroids) { + int n = asteroids.size(); + stack<int> s; + for (int i = 0; i < n; i++) { + if (asteroids[i] || s.empty()) + s.push(asteroids[i]); + else { + while (!s.empty() && s.top() && s.top() < abs(asteroids[i])) + s.pop(); + if (!s.empty() && s.top() == abs(asteroids[i])) + s.pop(); + else if (s.empty() || s.top() < 0) + s.push(asteroids[i]); + } + } + vector<int> ans(s.size()); + for (int i = (int)s.size() - 1; i >= 0; i--) { + ans[i] = s.top(); + s.pop(); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> a1 = {5, 10, -5}, a2 = {8, -8}, a3 = {10, 2, -5}; + for (auto i : obj.asteroidCollision(a1)) + printf("%d ", i); // expect: 5 10 + printf("\n"); + for (auto i : obj.asteroidCollision(a2)) + printf("%d ", i); // expect: nil + printf("\n"); + for (auto i : obj.asteroidCollision(a3)) + printf("%d ", i); // expect: 10 + printf("\n"); +} diff --git a/avg_levels_bst.cpp b/avg_levels_bst.cpp new file mode 100644 index 0000000..a18d38d --- /dev/null +++ b/avg_levels_bst.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + vector<double> averageOfLevels(TreeNode *root) { + vector<double> ans; + queue<TreeNode *> q; + q.push(root); + while (!q.empty()) { + double tmp = q.size(), sum = 0; + for (int i = 0; i < tmp; i++) { + auto tt = q.front(); + q.pop(); + sum += (tt->val); + if (tt->left) + q.push(tt->left); + if (tt->right) + q.push(tt->right); + } + ans.push_back(sum / tmp); + } + return ans; + } +}; diff --git a/avg_salary.c b/avg_salary.c new file mode 100644 index 0000000..55009c6 --- /dev/null +++ b/avg_salary.c @@ -0,0 +1,29 @@ +// 1491. Average Salary Excluding the Minimum and Maximum Salary +#include <float.h> +#include <stdio.h> + +/* + * given an array of unique integers 'salary' where 'salary[i]' is the salaray + * of the i'th employee. return the average salary of employees excluding the + * minimum and maximum salary. answer within 10^-5 of actual answer + */ + +double average(int *salary, int salary_size) { + double max = DBL_MIN, min = DBL_MAX, sum = 0; + for (int i = 0; i < salary_size; i++) { + sum += salary[i]; + if (salary[i] < min) + min = salary[i]; + if (salary[i] > max) + max = salary[i]; + } + sum = sum - min - max; + return sum / (salary_size - 2); +} + +int main() { + int s1[] = {4000, 3000, 1000, 2000}; + int s2[] = {1000, 2000, 3000}; + printf("%f\n", average(s1, 4)); // expect: 2500.00000 + printf("%f\n", average(s2, 3)); // expect: 2000.00000 +} diff --git a/avg_salary.cpp b/avg_salary.cpp new file mode 100644 index 0000000..12d49ce --- /dev/null +++ b/avg_salary.cpp @@ -0,0 +1,32 @@ +// 1491. Average Salary Excluding the Minimum and Maximum Salary +#include "leetcode.h" + +/* + * given an array of unique integers 'salary' where 'salary[i]' is the salaray + * of the i'th employee. return the average salary of employees excluding the + * minimum and maximum salary. answer within 10^-5 of actual answer + */ + +class Solution { +public: + double average(vector<int> &salary) { + double max = DBL_MIN, min = DBL_MAX, sum = 0; + for (int i = 0; i < salary.size(); i++) { + sum += salary[i]; + if (salary[i] < min) + min = salary[i]; + if (salary[i] > max) + max = salary[i]; + } + sum = sum - min - max; + return sum / (salary.size() - 2); + } +}; + +int main() { + Solution obj; + vector<int> s1 = {4000, 3000, 1000, 2000}; + vector<int> s2 = {1000, 2000, 3000}; + printf("%f\n", obj.average(s1)); // expect: 2500.00000 + printf("%f\n", obj.average(s2)); // expect: 2000.00000 +} diff --git a/backspace_string_compare.c b/backspace_string_compare.c new file mode 100644 index 0000000..e0b8cf6 --- /dev/null +++ b/backspace_string_compare.c @@ -0,0 +1,44 @@ +// 844. Backspace String Compare +#include "leetcode.h" + +/* + * given two strings 's' and 't', return 'true' if they are equal when both are + * typed into empty text editors. '#' means a backspace character. note that + * after backspacing an empty text, the text will continue empty. + */ + +char *process(char *s) { + int idx = 0, n = strlen(s); + for (int i = 0; i < n; i++) { + if (s[i] >= 'a' && s[i] <= 'z') { + s[idx] = s[i]; + idx++; + continue; + } else if (idx) + idx--; + } + s[idx] = '\0'; + return s; +} + +bool backspaceCompare(char *s, char *t) { + char *a = process(s), *b = process(t); + int na = strlen(a), nb = strlen(b); + if (na != nb) + return false; + else { + for (int i = 0; i < na; i++) + if (a[i] != b[i]) + return false; + } + return true; +} + +int main() { + char s1[] = {"ab#c"}, t1[] = {"ad#c"}; + char s2[] = {"ab##"}, t2[] = {"c#d#"}; + char s3[] = {"a#c"}, t3[] = {"b"}; + printf("%d\n", backspaceCompare(s1, t1)); // expect: 1 + printf("%d\n", backspaceCompare(s2, t2)); // expect: 1 + printf("%d\n", backspaceCompare(s3, t3)); // expect: 0 +} diff --git a/backspace_string_compare.cpp b/backspace_string_compare.cpp new file mode 100644 index 0000000..110e469 --- /dev/null +++ b/backspace_string_compare.cpp @@ -0,0 +1,36 @@ +#include "leetcode.h" + +class Solution { +public: + bool backspaceCompare(string s, string t) { + int k = 0, p = 0; + for (int i = 0; i < s.size(); i++) { + if (s[i] == '#') { + k--; + k = max(0, k); + } else { + s[k] = s[i]; + k++; + } + } + for (int i = 0; i < t.size(); i++) { + if (t[i] == '#') { + p--; + p = max(0, p); + } else { + t[p] = t[i]; + p++; + } + } + if (k != p) + return false; + else { + for (int i = 0; i < k; i++) + if (s[i] != t[i]) + return false; + return true; + } + } +}; + +int main() {} diff --git a/backspace_string_compare.py b/backspace_string_compare.py new file mode 100644 index 0000000..327ad2c --- /dev/null +++ b/backspace_string_compare.py @@ -0,0 +1,27 @@ +# 844. Backspace String Compare +from functools import reduce + +""" +given two strings 's' and 't', return 'true' if they are equal when both are +typed into empty text editors. '#' means a backspace character. note that +after backspacing an empty text, the text will continue empty. +""" + + +class Solution(object): + def back(self, res, c): + if c != "#": + res.append(c) + elif res: + res.pop() + return res + + def backspaceCompare(self, s, t): + return reduce(self.back, s, []) == reduce(self.back, t, []) + + +if __name__ == "__main__": + obj = Solution() + print(obj.backspaceCompare(s="ab#c", t="ad#c")) # expect: 1 + print(obj.backspaceCompare(s="ab##", t="c#d#")) # expect: 1 + print(obj.backspaceCompare(s="a#c", t="b")) # expect: 0 diff --git a/bag_of_tokens.c b/bag_of_tokens.c new file mode 100644 index 0000000..2c26f82 --- /dev/null +++ b/bag_of_tokens.c @@ -0,0 +1,45 @@ +// 948. Bag of Tokens +#include "leetcode.h" + +/* + * you have an initial power of 'power', an initial score of 0, and a bag of + * 'tokens' where 'tokens[i]' is the value of the i'th token (0-indexed). your + * goal is to maximise your total score by potentially playing each token in one + * of two ways: -if your current power is at least 'tokens[i]', you may play the + * i'th token face up, losing 'tokens[i]' power and gaining one score + * - if your current score is at least one, you may play the i'th token face + * down, gaining 'tokens[i]' power and losing score 1 each token may be played + * at most once and in any order. you do not have to play all the tokens. return + * the largest possible score you can achieve after playing any number of token. + */ + +int cmp(const void *a, const void *b) { + return *(const int *)a - *(const int *)b; +} + +int bagOfTokensScore(int *tokens, int tokens_size, int power) { + if (!tokens_size) + return 0; + qsort(tokens, tokens_size, sizeof(int), cmp); + int left = 0, right = tokens_size - 1, cnt = 0; + while (left < right) { + if (tokens[left] <= power) { + power -= tokens[left++]; + cnt++; + } else { + if (!cnt) + break; + power += tokens[right--]; + cnt--; + } + } + if (tokens[left] <= power) + cnt++; + return cnt; +} + +int main() { + int t1[] = {100}, t2[] = {100, 200}; + printf("%d\n", bagOfTokensScore(t1, 1, 50)); // expect: 0 + printf("%d\n", bagOfTokensScore(t2, 2, 200)); // expect: 2 +} diff --git a/bag_of_tokens.cpp b/bag_of_tokens.cpp new file mode 100644 index 0000000..d645d2b --- /dev/null +++ b/bag_of_tokens.cpp @@ -0,0 +1,27 @@ +#include "leetcode.h" + +class Solution { +public: + int bagOfTokensScore(vector<int> &tokens, int power) { + sort(tokens.begin(), tokens.end()); + int i, j, n; + i = 0; + j = n = tokens.size(); + while (i < j) { + if (power >= tokens[i]) + power -= tokens[i++]; + else if (i - (n - j) && j > i + 1) + power += tokens[--j]; + else + break; + } + return i - (n - j); + } +}; + +int main() { + Solution obj; + vector<int> tokens = {100}; + int power = 50; + cout << obj.bagOfTokensScore(tokens, power); +} diff --git a/bag_of_tokens.py b/bag_of_tokens.py new file mode 100644 index 0000000..ebf7cb5 --- /dev/null +++ b/bag_of_tokens.py @@ -0,0 +1,44 @@ +# 948. Bag of Tokens + +""" +you have an initial power of 'power', an initial score of 0, and a bag of +'tokens' where 'tokens[i]' is the value of the i'th token (0-indexed). your +goal is to maximise your total score by potentially playing each token in one +of two ways: -if your current power is at least 'tokens[i]', you may play the +i'th token face up, losing 'tokens[i]' power and gaining one score +- if your current score is at least one, you may play the i'th token face +down, gaining 'tokens[i]' power and losing score 1 each token may be played +at most once and in any order. you do not have to play all the tokens. return +the largest possible score you can achieve after playing any number of token. +""" + + +class Solution(object): + def bagOfTokensScore(self, tokens, power): + """ + :type tokens: List[int] + :type power: int + :rtype: int + """ + tokens.sort() + s, ans, l, r = 0, 0, 0, len(tokens) - 1 + while l <= r: + if power >= tokens[l]: + power -= tokens[l] + s += 1 + l += 1 + ans = max(ans, s) + elif s > 0: + power += tokens[r] + s -= 1 + r -= 1 + else: + break + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.bagOfTokensScore(tokens=[100], power=50)) # expect: 0 + print(obj.bagOfTokensScore(tokens=[200, 100], power=150)) # expect: 1 + print(obj.bagOfTokensScore(tokens=[100, 200, 300, 400], power=200)) # expect: 2 diff --git a/balanced_num.c b/balanced_num.c new file mode 100644 index 0000000..c7154ed --- /dev/null +++ b/balanced_num.c @@ -0,0 +1,40 @@ +// 2048. Next Greater Numerically Balanced Number +#include "leetcode.h" + +/* + * an integer 'x' is numerically balanced if for every digit 'd' in the number + * 'x', there are exactly 'd' occurences of that digit in 'x'. given an integer + * 'n', return the smallest numerically balanced number strictly greater than + * 'n' + */ + +bool is_balanced(int n) { + int *digit = calloc(10, sizeof(int)); + while (n) { + int d = n % 10; + n /= 10; + digit[d]++; + if (!d || digit[d] > d) + return 0; + } + for (int i = 1; i < 10; i++) + if (digit[i] && digit[i] != i) + return 0; + return 1; +} + +int nextBeautifulNumber(int n) { + n += 1; + while (1) { + if (is_balanced(n)) + return n; + n++; + } + return -1; +} + +int main() { + printf("%d\n", nextBeautifulNumber(1)); // expect: 22 + printf("%d\n", nextBeautifulNumber(1000)); // expect: 1333 + printf("%d\n", nextBeautifulNumber(3000)); // expect: 3133 +} diff --git a/balanced_num.cpp b/balanced_num.cpp new file mode 100644 index 0000000..779cb06 --- /dev/null +++ b/balanced_num.cpp @@ -0,0 +1,55 @@ +// 2048. Next Greater Numerically Balanced Number +#include "leetcode.h" + +/* + * an integer 'x' is numerically balanced if for every digit 'd' in the number + * 'x', there are exactly 'd' occurences of that digit in 'x'. given an integer + * 'n', return the smallest numerically balanced number strictly greater than + * 'n' + */ + +class Solution { +public: + int nextBeautifulNumber(int n) { + /* + vector<int> all; + for (int i = 0; i <= 1224444; ++i) { + int v = i; + unordered_map<int, int> m; + while (v > 0) { + ++m[v % 10]; + v /= 10; + } + for (auto &p : m) { + if (p.first != p.second) + goto L; + } + all.push_back(i); + L:; + } + */ + static vector<int> all{ + 0, 1, 22, 122, 212, 221, 333, 1333, 3133, + 3313, 3331, 4444, 14444, 22333, 23233, 23323, 23332, 32233, + 32323, 32332, 33223, 33232, 33322, 41444, 44144, 44414, 44441, + 55555, 122333, 123233, 123323, 123332, 132233, 132323, 132332, 133223, + 133232, 133322, 155555, 212333, 213233, 213323, 213332, 221333, 223133, + 223313, 223331, 224444, 231233, 231323, 231332, 232133, 232313, 232331, + 233123, 233132, 233213, 233231, 233312, 233321, 242444, 244244, 244424, + 244442, 312233, 312323, 312332, 313223, 313232, 313322, 321233, 321323, + 321332, 322133, 322313, 322331, 323123, 323132, 323213, 323231, 323312, + 323321, 331223, 331232, 331322, 332123, 332132, 332213, 332231, 332312, + 332321, 333122, 333212, 333221, 422444, 424244, 424424, 424442, 442244, + 442424, 442442, 444224, 444242, 444422, 515555, 551555, 555155, 555515, + 555551, 666666, 1224444, + }; + return *upper_bound(all.begin(), all.end(), n); + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.nextBeautifulNumber(1)); + printf("%d\n", obj.nextBeautifulNumber(1000)); + printf("%d\n", obj.nextBeautifulNumber(3000)); +} diff --git a/balanced_num.py b/balanced_num.py new file mode 100644 index 0000000..b9ed677 --- /dev/null +++ b/balanced_num.py @@ -0,0 +1,48 @@ +# 2048. Next Greater Numerically Balanced Number +from collections import Counter + +""" +an integer 'x' is numerically balanced if for every digit 'd' in the number +'x', there are exactly 'd' occurences of that digit in 'x'. given an integer +'n', return the smallest numerically balanced number strictly greater than +'n' +""" + + +class Solution(object): + def nextBeautifulNumber(self, n): + """ + :type n: int + :rtype: int + """ + + def backtracking(i, numLen, curNum, counter): + if i == numLen: + isBalanceNumber = True + for d, freq in counter.items(): + if freq != 0 and d != freq: + isBalanceNumber = False + if isBalanceNumber: + yield curNum + return + + for d in range(1, numLen + 1): + if counter[d] >= d: + continue + if counter[d] + (numLen - i) < d: + continue + counter[d] += 1 + yield from backtracking(i + 1, numLen, curNum * 10 + d, counter) + counter[d] -= 1 + + for numLen in range(len(str(n)), len(str(n)) + 2): + for num in backtracking(0, numLen, 0, Counter()): + if num > n: + return num + + +if __name__ == "__main__": + obj = Solution() + print(obj.nextBeautifulNumber(1)) + print(obj.nextBeautifulNumber(1000)) + print(obj.nextBeautifulNumber(3000)) diff --git a/baseball_game.cpp b/baseball_game.cpp new file mode 100644 index 0000000..f5d1b35 --- /dev/null +++ b/baseball_game.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + int calPoints(vector<string> &ops) { + int val1, val2, ans = 0; + stack<int> s; + for (string i : ops) { + if (i == "C") + s.pop(); + else if (i == "D") + s.push(s.top() * 2); + else if (i == "+") { + val1 = s.top(); + s.pop(); + val2 = s.top(); + s.push(val1); + s.push(val1 + val2); + } else + s.push(stoi(i)); + } + while (s.size() != 0) { + ans += s.top(); + s.pop(); + } + return ans; + } +}; + +int main() {} diff --git a/basic_calculator.cpp b/basic_calculator.cpp new file mode 100644 index 0000000..80e0ffe --- /dev/null +++ b/basic_calculator.cpp @@ -0,0 +1,37 @@ +#include "leetcode.h" + +class Solution { +public: + int calculate(string s) { + stack<pair<int, int>> sp; + long long int ans = 0; + int sign = +1; + for (int i = 0; i < s.size(); ++i) { + char ch = s[i]; + if (isdigit(ch)) { + long long int num = 0; + while (i < s.size() && isdigit(s[i])) { + num = (num * 10) + s[i] - '0'; + i++; + } + i--; + ans += (num * sign); + sign = +1; + } else if (ch == '(') { + sp.push(make_pair(ans, sign)); + ans = 0; + sign = +1; + } else if (ch == ')') { + ans = sp.top().first + (sp.top().second * ans); + sp.pop(); + } else if (ch == '-') + sign = (-1 * sign); + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.calculate("1 + 1"); +} diff --git a/basic_calculator.rs b/basic_calculator.rs new file mode 100644 index 0000000..d33a18c --- /dev/null +++ b/basic_calculator.rs @@ -0,0 +1,29 @@ +struct Solution; + +impl Solution { + pub fn calculate(s: String) -> i32 { + let mut sp: Vec<i32> = Vec::new(); + let (mut ans, mut num, mut sign) = (0, 0, 1); + sp.push(sign); + for ch in s.chars() { + match ch { + ' ' => {} + '+' | '-' => { + ans += num * sign; + sign = sp.last().unwrap() * if ch == '+' {1} else {-1}; + num = 0; + } + '(' => {sp.push(sign);} + ')' => {sp.pop();} + _ => {num * 10 + (ch as i32 - '0' as i32)} + }; + } + ans += num * sign; + ans + } +} + +fn main() { + let s = String::from("1 + 1"); + print!("{}", Solution::calculate(s)); +} diff --git a/best_buy_sell_stock.c b/best_buy_sell_stock.c new file mode 100644 index 0000000..1029826 --- /dev/null +++ b/best_buy_sell_stock.c @@ -0,0 +1,28 @@ +// 121. Best Time to Buy and Sell Stock +#include <limits.h> +#include <stdio.h> + +/* + * given an array 'prices' where 'prices[i]' is the price of a given stock on + * the ith day. maximise profit by choosing a single day to buy one stock and + * choosing a diff day in future to sell stock. return maximum profit achievable + * from transaction. + */ + +int maxProfit(int *prices, int pricesSize) { + int lsf = INT_MAX, op = 0, pist = 0; + for (int i = 0; i < pricesSize; i++) { + if (prices[i] < lsf) + lsf = prices[i]; + pist = prices[i] - lsf; + if (op < pist) + op = pist; + } + return op; +} + +int main() { + int p1[] = {7, 1, 5, 3, 6, 4}, p2[] = {7, 6, 4, 3, 1}; + printf("%d\n", maxProfit(p1, 6)); // expect: 5 + printf("%d\n", maxProfit(p2, 5)); // expect: 0 +} diff --git a/best_buy_sell_stock.cpp b/best_buy_sell_stock.cpp new file mode 100644 index 0000000..31b2a17 --- /dev/null +++ b/best_buy_sell_stock.cpp @@ -0,0 +1,31 @@ +// 121. Best Time to Buy and Sell Stock +#include "leetcode.h" + +/* + * given an array 'prices' where 'prices[i]' is the price of a given stock on + * the ith day. maximise profit by choosing a single day to buy one stock and + * choosing a diff day in future to sell stock. return maximum profit achievable + * from transaction. + */ + +class Solution { +public: + int maxProfit(vector<int> &prices) { + int lsf = INT_MAX, op = 0, pist = 0; + for (int i = 0; i < prices.size(); i++) { + if (prices[i] < lsf) + lsf = prices[i]; + pist = prices[i] - lsf; + if (op < pist) + op = pist; + } + return op; + } +}; + +int main() { + Solution obj; + vector<int> p1 = {7, 1, 5, 3, 6, 4}, p2 = {7, 6, 4, 3, 1}; + cout << obj.maxProfit(p1) << endl; // expect: 5 + cout << obj.maxProfit(p2) << endl; // expect: 0 +} diff --git a/best_team_no_conflict.c b/best_team_no_conflict.c new file mode 100644 index 0000000..15f27e3 --- /dev/null +++ b/best_team_no_conflict.c @@ -0,0 +1,62 @@ +// 1626. Best Team With No Conflicts +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * you are manager of a basketball team. for upcoming tournament you want to + * choose the team with the highest overall score. the score of the team is the + * sum of scores of all the players in the team. however the basketball team is + * not allowed to have conflicts. a conflict exists if a younger player has a + * strictly high score than an older player. a conflict does not occur between + * players of the same age. given two lists, 'scores', & 'ages', where each + * 'scores[i]' and 'ages[i]' represents the score and age of the ith player + * respectively. return highest overall score of all teams. + */ + +int cmp(const void *a, const void *b) { + int *aa = *(int **)a; + int *bb = *(int **)b; + if (aa[0] == bb[0]) + return aa[1] - bb[1]; + return aa[0] - bb[0]; +} + +int bestTeamScore(int *scores, int scoresSize, int *ages, int agesSize) { + int n = scoresSize; + int **data = malloc(n * sizeof(int *)); + for (int i = 0; i < n; i++) { + data[i] = malloc(2 * sizeof(int)); + data[i][0] = ages[i]; + data[i][1] = scores[i]; + } + qsort(data, n, sizeof(int *), cmp); + int *dp = malloc(n * sizeof(int)); + dp[0] = data[0][1]; + int ans = dp[0]; + for (int i = 1; i < n; i++) { + int pre = INT_MIN; + dp[i] = data[i][1]; + for (int j = 0; j < i; j++) + if (data[j][i] <= data[i][1]) + pre = fmax(pre, dp[j]); + if (pre != INT_MIN) + dp[i] += pre; + ans = fmax(ans, dp[i]); + } + free(dp); + for (int i = 0; i < n; i++) + free(data[i]); + free(data); + return ans; +} + +int main() { + int scores1[] = {1, 3, 5, 10, 15}, ages1[] = {1, 2, 3, 4, 5}; + int scores2[] = {4, 5, 6, 5}, ages2[] = {2, 1, 2, 1}; + int scores3[] = {1, 2, 3, 5}, ages3[] = {8, 9, 10, 1}; + printf("%d\n", bestTeamScore(scores1, 5, ages1, 5)); // expect: 34 + printf("%d\n", bestTeamScore(scores2, 4, ages1, 4)); // expect: 16 + printf("%d\n", bestTeamScore(scores3, 4, ages1, 4)); // expect: 6 +} diff --git a/best_team_no_conflict.cpp b/best_team_no_conflict.cpp new file mode 100644 index 0000000..0773202 --- /dev/null +++ b/best_team_no_conflict.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" + +class Solution { +public: + int bestTeamScore(vector<int> &scores, vector<int> &ages) { + int n = scores.size(), ans = 0; + vector<int> dp(n, 0); + vector<pair<int, int>> arr(n, {0, 0}); + for (int i = 0; i < n; ++i) { + arr[i].first = ages[i]; + arr[i].second = scores[i]; + } + for (int i = 0; i < n; ++i) { + dp[i] = arr[i].second; + for (int j = i - 1; j >= 0; --j) + if (arr[i].second >= arr[j].second) + dp[i] = max(dp[i], dp[j] + arr[i].second); + ans = max(ans, dp[i]); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> scores = {1, 3, 5, 10, 15}, ages = {1, 2, 3, 4, 5}; + cout << obj.bestTeamScore(scores, ages); +} diff --git a/binary_search.c b/binary_search.c new file mode 100644 index 0000000..bd8f855 --- /dev/null +++ b/binary_search.c @@ -0,0 +1,22 @@ +// 704. Binary Search +#include <stdio.h> + +int search(int *nums, int nums_size, int target) { + int low = 0, high = nums_size - 1; + while (low <= high) { + int mid = low + (high - low) / 2; + if (nums[mid] == target) + return mid; + else if (nums[mid] > target) + high = mid - 1; + else + low = mid + 1; + } + return -1; +} + +int main() { + int nums[] = {-1, 0, 3, 5, 9, 12}; + printf("%d\n", search(nums, 6, 9)); // expect: 4 + printf("%d\n", search(nums, 6, 2)); // expect: -1 +} diff --git a/binary_search.cpp b/binary_search.cpp new file mode 100644 index 0000000..478281e --- /dev/null +++ b/binary_search.cpp @@ -0,0 +1,27 @@ +// 704. Binary Search +#include "leetcode.h" + +class Solution { +public: + int search(vector<int> &nums, int target) { + int n = nums.size() - 1; + int low = 0, high = n; + while (low <= high) { + int mid = low + (high - low) / 2; + if (nums[mid] == target) + return mid; + else if (nums[mid] > target) + high = mid - 1; + else + low = mid + 1; + } + return -1; + } +}; + +int main() { + Solution obj; + vector<int> nums = {-1, 0, 3, 5, 9, 12}; + printf("%d\n", obj.search(nums, 9)); // expect: 4 + printf("%d\n", obj.search(nums, 2)); // expect: -1 +} diff --git a/binary_string_substr_1n.c b/binary_string_substr_1n.c new file mode 100644 index 0000000..ec03c8c --- /dev/null +++ b/binary_string_substr_1n.c @@ -0,0 +1,39 @@ +// 1016. Binary String With Substrings Representing 1 To N +#include "leetcode.h" + +/* + * given a binary string 's' and a positive integer 'n', return 'true' if the + * binary representation of all the integers in the range '[1, n]' are + * substrings of 's' or 'false' otherwise. a substring is a contiguous sequence + * of characters within a string. + */ + +char *int_to_str(int val) { + char *res = (char *)malloc(32 * sizeof(char)); + res[31] = '\0'; + int idx = 30; + while (val) { + res[idx] = val % 2 + '0'; + val /= 2; + idx--; + } + return &res[idx + 1]; +} + +bool queryString(char *s, int n) { + bool ans = true; + for (int i = n; i; i--) { + char *tmp = int_to_str(i); + if (!strstr(s, tmp)) { + ans = false; + break; + } + } + return ans; +} + +int main() { + char *s = "0110"; + printf("%d\n", queryString(s, 3)); // expect: 1 + printf("%d\n", queryString(s, 4)); // expect: 0 +} diff --git a/binary_string_substr_1n.py b/binary_string_substr_1n.py new file mode 100644 index 0000000..892a5c5 --- /dev/null +++ b/binary_string_substr_1n.py @@ -0,0 +1,30 @@ +# 1016. Binary String With Substrings Representing 1 To N + +""" +given a binary string 's' and a positive integer 'n', return 'true' if the +binary representation of all the integers in the range '[1, n]' are +substrings of 's' or 'false' otherwise. a substring is a contiguous sequence +of characters within a string. +""" + + +class Solution(object): + def queryString(self, s, n): + """ + :type s: str + :type n: int + :rtype: bool + """ + if n > len(s) * 2: + return False + l = len(bin(n)) - 2 + seen = {s[i : i + l] for i in range(len(s))} | { + s[i : i + l - 1] for i in range(len(s)) + } + return all(bin(i)[2:] in seen for i in range(n, n / 2, -1)) + + +if __name__ == "__main__": + obj = Solution() + print(obj.queryString("0110", 3)) # expect: true + print(obj.queryString("0110", 4)) # expect: false diff --git a/binary_subarr_sum.c b/binary_subarr_sum.c new file mode 100644 index 0000000..c20bfdb --- /dev/null +++ b/binary_subarr_sum.c @@ -0,0 +1,52 @@ +// 930. Binary Subarrays With Sum +#include "leetcode.h" + +/* + * given a binary array 'nums' and an integer 'goal', return the number o + * non-empty subarrays with a sum 'goal'. a subarray is a contiguous part of the + * array + */ + +int numSubarraysWithSum(int *nums, int numsSize, int goal) { + int n = numsSize, m = n + 1, sum = 0, rm, d, ans = 0; + int **hash = calloc(m, sizeof(int *)); + hash[0] = malloc(2 * sizeof(int)); + hash[0][0] = 0; + hash[0][1] = 1; + for (int i = 0; i < n; i++) { + sum += nums[i]; + rm = sum - goal; + d = rm; + while (1 && rm >= 0) { + if (hash[d % n] == NULL) + break; + else if (hash[d % n][0] == rm) { + ans += hash[d % n][1]; + break; + } else { + d++; + } + } + d = sum; + while (1) { + if (hash[d % n] == NULL) { + hash[d % n] = malloc(2 * sizeof(int)); + hash[d % n][0] = sum; + hash[d % n][1] = 1; + break; + } else if (hash[d % n][0] == sum) { + hash[d % n][1]++; + break; + } else { + d++; + } + } + } + return ans; +} + +int main() { + int n1[] = {1, 0, 1, 0, 1}, n2[] = {0, 0, 0, 0, 0}; + printf("%d\n", numSubarraysWithSum(n1, ARRAY_SIZE(n1), 2)); // expect: 4 + printf("%d\n", numSubarraysWithSum(n2, ARRAY_SIZE(n2), 0)); // expect: 15 +} diff --git a/binary_subarr_sum.py b/binary_subarr_sum.py new file mode 100644 index 0000000..75a9df7 --- /dev/null +++ b/binary_subarr_sum.py @@ -0,0 +1,30 @@ +# 930. Binary Subarrays With Sum +import collections + +""" +given a binary array 'nums' and an integer 'goal', return the number o +non-empty subarrays with a sum 'goal'. a subarray is a contiguous part of the +array + """ + + +class Solution(object): + def numSubarraysWithSum(self, nums, goal): + """ + :type nums: List[int] + :type goal: int + :rtype: int + """ + c = collections.Counter({0: 1}) + psum = ans = 0 + for i in nums: + psum += i + ans += c[psum - goal] + c[psum] += 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.numSubarraysWithSum(nums=[1, 0, 1, 0, 1], goal=2)) + print(obj.numSubarraysWithSum(nums=[0, 0, 0, 0, 0], goal=0)) diff --git a/binary_tree_cameras.cpp b/binary_tree_cameras.cpp new file mode 100644 index 0000000..c73650b --- /dev/null +++ b/binary_tree_cameras.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" + +class Solution { +public: + int ans; + int minCameraCover(TreeNode *root) { + if (helper(root) == 0) + ans++; + return ans; + } + +private: + int helper(TreeNode *root) { + if (!root) + return 1; + int l = helper(root->left); + int r = helper(root->right); + if (l == 0 || r == 0) { + ans++; + return 2; + } else if (l == 2 || r == 2) + return 1; + else + return 0; + } +}; + +int main() {} diff --git a/binary_tree_factors.c b/binary_tree_factors.c new file mode 100644 index 0000000..378d283 --- /dev/null +++ b/binary_tree_factors.c @@ -0,0 +1,46 @@ +// 823. Binary Trees With Factors +#include "leetcode.h" + +/* + * given an array of unique integers 'arr' where each integer 'arr[i]' is + * strictly greater than 1. we make a binary tree using these integers and each + * number may be used for any number of times. each non-leaf node's value should + * be equal to the product of the values of its children. return the number of + * binary trees we can make. the answer may be too large to fit in a signed 32 + * bit integer, so return the answer modulo 10e9+7 + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int numFactoredBinaryTrees(int *arr, int arr_size) { + int ans = 0, mod = 1e9 + 7; + qsort(arr, arr_size, sizeof(int), cmp); + long dp[arr_size]; + for (int i = 0; i < arr_size; i++) + dp[i] = 1; + for (int i = 0; i < arr_size; i++) { + int left = 0, right = i - 1; + while (left <= right) { + if ((long)arr[left] * arr[right] > arr[i]) + right--; + else if ((long)arr[left] * arr[right] < arr[i]) + left++; + else { + if (left == right) + dp[i] += (dp[left] * dp[right]); + else + dp[i] += 2 * (dp[left] * dp[right]); + left++; + right--; + } + } + ans = ((ans % mod) + dp[i]) % mod; + } + return ans; +} + +int main() { + int a1[] = {2, 4}, a2[] = {2, 4, 5, 10}; + printf("%d\n", numFactoredBinaryTrees(a1, ARRAY_SIZE(a1))); // expect: 3 + printf("%d\n", numFactoredBinaryTrees(a2, ARRAY_SIZE(a2))); // expect: 7 +} diff --git a/binary_tree_factors.cpp b/binary_tree_factors.cpp new file mode 100644 index 0000000..7813f17 --- /dev/null +++ b/binary_tree_factors.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + int numFactoredBinaryTrees(vector<int> &arr) { + sort(arr.begin(), arr.end()); + int n = arr.size(); + long ans = 0; + unordered_map<int, long> um; + for (int num : arr) { + long ways = 1; + double lim = sqrt(num); + for (int i = 0, fA = arr[0]; fA <= lim; fA = arr[++i]) { + if (num % fA != 0) + continue; + int fB = num / fA; + if (um.find(fB) != um.end()) + ways += um[fA] * um[fB] * (fA == fB ? 1 : 2); + } + um[num] = ways; + ans = (ans + ways) % 1000000007; + } + return (int)ans; + } +}; + +int main() { + Solution obj; + vector<int> arr = {2, 4}; + cout << obj.numFactoredBinaryTrees(arr); +} diff --git a/binary_tree_factors.py b/binary_tree_factors.py new file mode 100644 index 0000000..03fc3f5 --- /dev/null +++ b/binary_tree_factors.py @@ -0,0 +1,24 @@ +# 823. Binary Trees With Factors + +""" +given an array of unique integers 'arr' where each integer 'arr[i]' is +strictly greater than 1. we make a binary tree using these integers and each +number may be used for any number of times. each non-leaf node's value should +be equal to the product of the values of its children. return the number of +binary trees we can make. the answer may be too large to fit in a signed 32 +bit integer, so return the answer modulo 10e9+7 +""" + + +class Solution(object): + def numFactoredBinaryTrees(self, arr): + dp = {} + for i in sorted(arr): + dp[i] = sum(dp[b] * dp.get(i / b, 0) for b in dp if i % b == 0) + 1 + return sum(dp.values()) % (10**9 + 7) + + +if __name__ == "__main__": + obj = Solution() + print(obj.numFactoredBinaryTrees([2, 4])) # expect: 3 + print(obj.numFactoredBinaryTrees([2, 4, 5, 10])) # expect: 7 diff --git a/binary_tree_inorder.c b/binary_tree_inorder.c new file mode 100644 index 0000000..f72a23d --- /dev/null +++ b/binary_tree_inorder.c @@ -0,0 +1,28 @@ +// 94. Binary Tree Inorder Traversal +#include "leetcode.h" + +/* + * given the root of a binary tree, return the inorder traversal of its nodes + * values + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +void travel(struct TreeNode *root, int *res, int *size) { + if (!root) + return; + travel(root->left, res, size); + res[(*size)++] = root->val; + travel(root->right, res, size); +} + +int *inorderTraversal(struct TreeNode *root, int *return_size) { + *return_size = 0; + int *ans = malloc(sizeof(int) * 100); + travel(root, ans, return_size); + return ans; +} diff --git a/binary_tree_inorder.cpp b/binary_tree_inorder.cpp new file mode 100644 index 0000000..a677d27 --- /dev/null +++ b/binary_tree_inorder.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> inorderTraversal(TreeNode *root) { + vector<int> ans; + stack<TreeNode *> s; + TreeNode *curr = root; + while (curr || !s.empty()) { + while (curr) { + s.push(curr); + curr = curr->left; + } + curr = s.top(); + s.pop(); + ans.push_back(curr->val); + curr = curr->right; + } + return ans; + } +}; + +int main() { Solution obj; } diff --git a/binary_tree_inorder.py b/binary_tree_inorder.py new file mode 100644 index 0000000..6007136 --- /dev/null +++ b/binary_tree_inorder.py @@ -0,0 +1,39 @@ +# 94. Binary Tree Inorder Traversal + +""" +given the root of a binary tree, return the inorder traversal of its nodes +values +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def inorderTraversal(self, root): + """ + :type root: TreeNode + :rtype: List[int] + """ + + def travel(root, result): + if root != None: + travel(root.left, result) + result.append(root.val) + travel(root.right, result) + + ans = [] + travel(root, ans) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.inorderTraversal([1, 0, 2, 3])) + print(obj.inorderTraversal([])) + print(obj.inorderTraversal([1])) diff --git a/binary_tree_level_traverse.cpp b/binary_tree_level_traverse.cpp new file mode 100644 index 0000000..47a69da --- /dev/null +++ b/binary_tree_level_traverse.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + vector<vector<int>> levelOrder(TreeNode *root) { + vector<vector<int>> ans; + if (!root) + return ans; + queue<TreeNode *> q; + q.push(root); + q.push(NULL); + vector<int> curr; + while (!q.empty()) { + TreeNode *t = q.front(); + q.pop(); + if (t == NULL) { + ans.push_back(curr); + curr.resize(0); + if (q.size() > 0) + q.push(NULL); + } else { + curr.push_back(t->val); + if (t->left) + q.push(t->left); + if (t->right) + q.push(t->right); + } + } + return ans; + } +}; diff --git a/binary_tree_preorder.cpp b/binary_tree_preorder.cpp new file mode 100644 index 0000000..7bba435 --- /dev/null +++ b/binary_tree_preorder.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> preorderTraversal(TreeNode *root) { + // morris traversal + vector<int> nodes; + while (root) { + if (root->left) { + TreeNode *pre = root->left; + while (pre->right && pre->right != root) + pre = pre->right; + if (!pre->right) { + pre->right = root; + nodes.push_back(root->val); + root = root->left; + } else { + pre->right = NULL; + root = root->right; + } + } else { + nodes.push_back(root->val); + root = root->right; + } + } + return nodes; + } +}; diff --git a/binary_tree_preorder.rs b/binary_tree_preorder.rs new file mode 100644 index 0000000..da6e0b8 --- /dev/null +++ b/binary_tree_preorder.rs @@ -0,0 +1,35 @@ +use std::rc::Rc; +use std::cell::RefCell; +#[derive(Debug, PartialEq, Eq)] +pub struct TreeNode { + pub val: i32, + pub left: Option<Rc<RefCell<TreeNode>>>, + pub right: Option<Rc<RefCell<TreeNode>>>, +} + +impl TreeNode { + #[inline] + pub fn new(val: i32) -> Self { + TreeNode { + val, left: None, + right: None + } + } +} + +struct Solution; + +impl Solution { + pub fn preorder_traversal(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> { + let mut ans: Vec<i32> = Vec::new(); + let mut stack: Vec<Option<Rc<RefCell<TreeNode>>>> = vec![root]; + while let Some(last) = stack.pop() { + if let Some(n) = last { + ans.push(n.borrow().val); + stack.push(n.borrow().right.clone()); + stack.push(n.borrow().left.clone()); + } + } + ans + } +} diff --git a/binary_tree_pruning.cpp b/binary_tree_pruning.cpp new file mode 100644 index 0000000..3bac07d --- /dev/null +++ b/binary_tree_pruning.cpp @@ -0,0 +1,15 @@ +#include "leetcode.h" + +class Solution { +public: + TreeNode *pruneTree(TreeNode *root) { + if (root) { + root->left = pruneTree(root->left); + root->right = pruneTree(root->right); + if (root->left || root->right || root->val != 0) + return root; + } + delete root; + return nullptr; + } +}; diff --git a/binary_tree_right_view.cpp b/binary_tree_right_view.cpp new file mode 100644 index 0000000..e5a040c --- /dev/null +++ b/binary_tree_right_view.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> rightSideView(TreeNode *root) { + queue<TreeNode *> q; + vector<int> ans; + if (!root) + return ans; + q.push(root); + while (!q.empty()) { + ans.push_back(q.back()->val); + for (int i = q.size(); i > 0; i--) { + TreeNode *n = q.front(); + q.pop(); + if (n->left) + q.push(n->left); + if (n->right) + q.push(n->right); + } + } + return ans; + } +}; diff --git a/binary_tree_traversal.cpp b/binary_tree_traversal.cpp new file mode 100644 index 0000000..601e21c --- /dev/null +++ b/binary_tree_traversal.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) { + unordered_map<int, int> m; + for (int i = 0; i < inorder.size(); i++) + m[inorder[i]] = i; + return splitTree(preorder, m, 0, 0, inorder.size() - 1); + } + +private: + TreeNode *splitTree(vector<int> &preorder, unordered_map<int, int> &m, + int pix, int iLeft, int iRight) { + int rVal = preorder[pix], iMid = m[rVal]; + TreeNode *root = new TreeNode(rVal); + if (iMid > iLeft) + root->left = splitTree(preorder, m, pix + 1, iLeft, iMid - 1); + if (iMid < iRight) + root->right = + splitTree(preorder, m, pix + iMid - iLeft + 1, iMid + 1, iRight); + return root; + } +}; diff --git a/binary_tree_zigzag.c b/binary_tree_zigzag.c new file mode 100644 index 0000000..45ecbd9 --- /dev/null +++ b/binary_tree_zigzag.c @@ -0,0 +1,69 @@ +// 103. Binary Tree Zigzag Level Order Traversal +// given the 'root' of a binary tree, return the zigzag level order traversal of +// its nodes' values (ie. from left to right, then right to left for the next +// level) +#include <math.h> +#include <stddef.h> +#include <stdlib.h> + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int depth(struct TreeNode *root) { + if (root == NULL) + return 0; + else + return 1 + fmax(depth(root->left), depth(root->right)); +} + +int **zigzagLevelOrder(struct TreeNode *root, int *returnSize, + int **returnColumnSizes) { + int dep = depth(root); + if (dep == 0) { + *returnSize = 0; + return NULL; + } + *returnColumnSizes = malloc(dep * sizeof(int)); + int **ans = malloc(dep * sizeof(int *)), ans_idx = 0; + struct TreeNode **q0 = malloc(1000 * sizeof(struct TreeNode *)); + struct TreeNode **q1 = malloc(1000 * sizeof(struct TreeNode *)); + int idx0 = 0, idx1 = 0; + q0[idx0] = root; + idx0 = 1; + while (idx0 || idx1) { + if (idx0) { + ans[ans_idx] = malloc(idx0 * sizeof(int)); + returnColumnSizes[0][ans_idx] = idx0; + for (int i = idx0 - 1; i >= 0; i--) { + ans[ans_idx][idx0 - 1 - i] = q0[i]->val; + if (q0[i]->left) { + q1[idx1] = q0[i]->left; + idx1++; + } + if (q0[i]->right) { + q1[idx1] = q0[i]->right; + idx1++; + } + } + ans_idx++; + idx0 = 0; + } else { + ans[ans_idx] = malloc(idx1 * sizeof(int)); + returnColumnSizes[0][ans_idx] = idx1; + for (int i = idx1 - 1 - i; i >= 0; i--) { + ans[ans_idx][idx1 - 1 - i] = q1[i]->val; + if (q1[i]->right) { + q0[idx0] = q1[i]->left; + idx0++; + } + } + ans_idx++; + idx1 = 0; + } + } + *returnSize = dep; + return ans; +} diff --git a/binary_tree_zigzag.cpp b/binary_tree_zigzag.cpp new file mode 100644 index 0000000..641fc41 --- /dev/null +++ b/binary_tree_zigzag.cpp @@ -0,0 +1,36 @@ +// 103. Binary Tree Zigzag Level Order Traversal +#include "leetcode.h" +// given the 'root' of a binary tree, return the zigzag level order traversal of +// its nodes' values (ie. from left to right, then right to left for the next +// level) + +class Solution { +public: + vvd(int) zigzagLevelOrder(TreeNode *root) { + if (!root) + return {}; + queue<TreeNode *> q; + vvd(int) ans; + q.push(root); + int level = 0; + while (!q.empty()) { + int sz = q.size(); + vector<int> curr(sz); + for (int i = 0; i < sz; i++) { + TreeNode *tmp = q.front(); + q.pop(); + if (level == 0) + curr[i] = tmp->val; + else + curr[sz - i - 1] = tmp->val; + if (tmp->left) + q.push(tmp->left); + if (tmp->right) + q.push(tmp->right); + } + ans.push_back(curr); + level = !level; + } + return ans; + } +}; diff --git a/bitwise_and_num_range.c b/bitwise_and_num_range.c new file mode 100644 index 0000000..ce137c1 --- /dev/null +++ b/bitwise_and_num_range.c @@ -0,0 +1,23 @@ +// 201. Bitwise AND of Numbers Range +#include "leetcode.h" + +/* + * given two integers 'm' and 'n' that represent the range '[m, + * n]', return the bitwise and of all numbers in this range, inclusive. + */ + +int rangeBitwiseAnd(int m, int n) { + int k = 0; + while (m != n) { + m >>= 1; + n >>= 1; + ++k; + } + return n << k; +} + +int main() { + printf("%d\n", rangeBitwiseAnd(5, 7)); // expect: 4 + printf("%d\n", rangeBitwiseAnd(0, 0)); // expect: 0 + printf("%d\n", rangeBitwiseAnd(1, 2147483647)); // expect: 0 +} diff --git a/bitwise_and_num_range.py b/bitwise_and_num_range.py new file mode 100644 index 0000000..11a8ee1 --- /dev/null +++ b/bitwise_and_num_range.py @@ -0,0 +1,29 @@ +# 201. Bitwise AND of Numbers Range +import math + +""" +given two integers 'm' and 'n' that represent the range '[m, +n]', return the bitwise and of all numbers in this range, inclusive. +""" + + +class Solution(object): + def rangeBitwiseAnd(self, m, n): + """ + :type m: int + :type n: int + :rtype: int + """ + if m == n: + return m + diff = n - m + msb = 1 << math.floor(math.log2(diff)) + bit_rem = (msb << 1) - 1 + return m & m & ~bit_rem + + +if __name__ == "__main__": + obj = Solution() + print(obj.rangeBitwiseAnd(5, 7)) + print(obj.rangeBitwiseAnd(0, 0)) + print(obj.rangeBitwiseAnd(1, 82747883)) diff --git a/boats_save_people.c b/boats_save_people.c new file mode 100644 index 0000000..d0cb7f4 --- /dev/null +++ b/boats_save_people.c @@ -0,0 +1,34 @@ +// 881. Boats to Save People +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array 'people' where 'people[i]' is the weight of the i'th person, + * and an infinite number of boats where each boat can carry a maximum weight of + * 'limit'. each boat carries at most two people at the same time, provided the + * sum of the weight of those people is at most 'limit'. return minimum number + * of boats to carry every person + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int numRescueBoats(int *people, int people_size, int limit) { + qsort(people, people_size, sizeof(int), cmp); + int max_weight = people_size - 1, min_weight = 0, ans = 0; + while (min_weight <= max_weight) { + if (people[min_weight] + people[max_weight] <= limit) { + min_weight++; + max_weight--; + } else + max_weight--; + ans++; + } + return ans; +} + +int main() { + int p1[] = {1, 2}, p2[] = {3, 2, 2, 1}, p3[] = {3, 5, 3, 4}; + printf("%d\n", numRescueBoats(p1, 2, 3)); // expect: 1 + printf("%d\n", numRescueBoats(p2, 4, 3)); // expect: 3 + printf("%d\n", numRescueBoats(p3, 4, 5)); // expect: 4 +} diff --git a/boats_save_people.cpp b/boats_save_people.cpp new file mode 100644 index 0000000..7221191 --- /dev/null +++ b/boats_save_people.cpp @@ -0,0 +1,35 @@ +// 881. Boats to Save People +#include "leetcode.h" + +/* + * given an array 'people' where 'people[i]' is the weight of the i'th person, + * and an infinite number of boats where each boat can carry a maximum weight of + * 'limit'. each boat carries at most two people at the same time, provided the + * sum of the weight of those people is at most 'limit'. return minimum number + * of boats to carry every person + */ + +class Solution { +public: + int numRescueBoats(vector<int> &people, int limit) { + sort(people.begin(), people.end()); + int max_weight = people.size() - 1, min_weight = 0, ans = 0; + while (min_weight <= max_weight) { + if (people[min_weight] + people[max_weight] <= limit) { + min_weight++; + max_weight--; + } else + max_weight--; + ans++; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> p1 = {1, 2}, p2 = {3, 2, 2, 1}, p3 = {3, 5, 3, 4}; + printf("%d\n", obj.numRescueBoats(p1, 3)); // expect: 1 + printf("%d\n", obj.numRescueBoats(p2, 3)); // expect: 3 + printf("%d\n", obj.numRescueBoats(p3, 5)); // expect: 4 +} diff --git a/boats_save_people.py b/boats_save_people.py new file mode 100644 index 0000000..92ae1d4 --- /dev/null +++ b/boats_save_people.py @@ -0,0 +1,32 @@ +# 881. Boats to Save People + +""" +given an array 'people' where 'people[i]' is the weight of the i'th person, +and an infinite number of boats where each boat can carry a maximum weight of +'limit'. each boat carries at most two people at the same time, provided the +sum of the weight of those people is at most 'limit'. return minimum number +of boats to carry every person +""" + + +class Solution(object): + def numRescueBoats(self, people, limit): + """ + :type people: List[int] + :type limit: int + :rtype: int + """ + people.sort(reverse=True) + i, j = 0, len(people) - 1 + while i <= j: + if people[i] + people[j] <= limit: + j -= 1 + i += 1 + return i + + +if __name__ == "__main__": + obj = Solution() + print(obj.numRescueBoats([1, 2], 3)) + print(obj.numRescueBoats([3, 2, 2, 1], 3)) + print(obj.numRescueBoats([3, 5, 3, 4], 5)) diff --git a/brainpower.c b/brainpower.c new file mode 100644 index 0000000..dc414bb --- /dev/null +++ b/brainpower.c @@ -0,0 +1,35 @@ +// 2140. Solving Questions With Brainpower +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given a 0-indexed 2d integer array 'questions' where 'questions[i] = + * [pointsi, brainpoweri]'. the array describes the questions of an exam, where + * you have to process the questions in order (ie starting from question 0) and + * make a decision whether to solve or skip each question. solving question 'i' + * will earn you 'pointsi' points, but you will be unable to solve each of the + * next 'brainpoweri' questions. if you skip question 'i', yo get to make the + * decision on the next question. return maximum points you can score. + * + */ + +long long mostPoints(int **questions, int questions_size, + int *questions_col_size) { + long long *dp = malloc((questions_size + 1) * sizeof(long long)); + dp[questions_size] = 0; + for (int i = questions_size - 1; i >= 0; i--) { + int k = fmin(i + questions[i][1] + 1, questions_size); + dp[i] = fmax(questions[i][0] + dp[k], dp[i + 1]); + } + long long ans = dp[0]; + free(dp); + return ans; +} + +int main() { + int q1[4][2] = {{3, 2}, {4, 3}, {4, 4}, {2, 5}}, qs1 = 4, qcs1[] = {}; + int q2[5][2] = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}, qs2 = 5, qcs2[] = {}; + printf("%lld\n", mostPoints(q1, qs1, qcs1)); // expect: 5 + printf("%lld\n", mostPoints(q2, qs2, qcs2)); // expect: 7 +} diff --git a/brainpower.cpp b/brainpower.cpp new file mode 100644 index 0000000..782266f --- /dev/null +++ b/brainpower.cpp @@ -0,0 +1,37 @@ +// 2140. Solving Questions With Brainpower +#include "leetcode.h" + +/* + * given a 0-indexed 2d integer array 'questions' where 'questions[i] = + * [pointsi, brainpoweri]'. the array describes the questions of an exam, where + * you have to process the questions in order (ie starting from question 0) and + * make a decision whether to solve or skip each question. solving question 'i' + * will earn you 'pointsi' points, but you will be unable to solve each of the + * next 'brainpoweri' questions. if you skip question 'i', yo get to make the + * decision on the next question. return maximum points you can score. + * + */ + +class Solution { +public: + long long mostPoints(vvd(int) & questions) { + int n = questions.size(); + vector<long long> dp(n + 1, 0); + for (int i = n - 1; i >= 0; --i) { + int points = questions[i][0]; + int jump = questions[i][1]; + int next_q = min(jump + i + 1, n); + long long p = points + dp[next_q]; + dp[i] = max(p, dp[i + 1]); + } + return dp[0]; + } +}; + +int main() { + Solution obj; + vvd(int) q1 = {{3, 2}, {4, 3}, {4, 4}, {2, 5}}; + vvd(int) q2 = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; + printf("%lld\n", obj.mostPoints(q1)); // expect: 5 + printf("%lld\n", obj.mostPoints(q2)); // expect: 7 +} diff --git a/break_palindrom.cpp b/break_palindrom.cpp new file mode 100644 index 0000000..579359a --- /dev/null +++ b/break_palindrom.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + string breakPalindrom(string palindrome) { + int n = palindrome.size(); + if (n == 1) + return ""; + for (int i = 0; i < n / 2; i++) { + if (palindrome[i] != 'a') { + palindrome[i] = 'a'; + return palindrome; + } + } + palindrome[n - 1] = 'b'; + return palindrome; + } +}; + +int main() { + Solution obj; + cout << obj.breakPalindrom("abccba"); +} diff --git a/broken_calculator.c b/broken_calculator.c new file mode 100644 index 0000000..9afbe7c --- /dev/null +++ b/broken_calculator.c @@ -0,0 +1,27 @@ +// 991. Broken Calculator +#include <stdio.h> +#include <stdlib.h> + +/* + * there is a broken calculator that has the integer 'start_value' on its + * display initially. in one operation, you can + * - multiply thenumber on display by 2 + * - subtract 1 from number on display + * given two integers 'start_value' and 'target', return the minimum number of + * operations needed to display 'target' on the calculator + */ + +int brokenCalc(int start_value, int target) { + int ans = 0; + while (target > start_value) { + target = !(target % 2) ? target / 2 : target + 1; + ++ans; + } + return ans + start_value - target; +} + +int main() { + printf("%d\n", brokenCalc(2, 3)); // expect: 2 + printf("%d\n", brokenCalc(5, 8)); // expect: 2 + printf("%d\n", brokenCalc(3, 10)); // expect: 3 +} diff --git a/broken_calculator.py b/broken_calculator.py new file mode 100644 index 0000000..dfcb64f --- /dev/null +++ b/broken_calculator.py @@ -0,0 +1,26 @@ +# 991. Broken Calculator + +""" +there is a broken calculator that has the integer 'start_value' on its +display initially. in one operation, you can +- multiply thenumber on display by 2 +- subtract 1 from number on display +given two integers 'start_value' and 'target', return the minimum number of +operations needed to display 'target' on the calculator +""" + + +class Solution(object): + def brokenCalc(self, start_value, target): + ans = 0 + while start_value < target: + ans += target % 2 + 1 + target = (target + 1) / 2 + return ans + start_value - target + + +if __name__ == "__main__": + obj = Solution() + print(obj.brokenCalc(2, 3)) # expect: 2 + print(obj.brokenCalc(5, 8)) # expect: 2 + print(obj.brokenCalc(3, 10)) # expect: 3 diff --git a/browser_history.c b/browser_history.c new file mode 100644 index 0000000..43c3bd8 --- /dev/null +++ b/browser_history.c @@ -0,0 +1,65 @@ +// 1472. Design Browser History +#include <math.h> +#include <stdlib.h> +#include <string.h> + +/* + * you have a browser of one tab where you start on the homepage and can visit + * another url, get back in the history number of steps or move forward in the + * history number of steps. implement BrowserHistory class (they're self + * explantory) + */ + +typedef struct { + char **browser; + int top; + int size; +} BrowserHistory; + +BrowserHistory *browserHistoryCreate(char *homepage) { + BrowserHistory *ret = malloc(sizeof(BrowserHistory)); + ret->browser = malloc(5000 * sizeof(char *)); + ret->browser[0] = malloc(21 * sizeof(char)); + ret->browser[0][strlen(homepage)] = '\0'; + memcpy(ret->browser[0], homepage, strlen(homepage)); + ret->top = 0; + ret->size = 1; + return ret; +} + +void browserHistoryVisit(BrowserHistory *obj, char *url) { + obj->top++; + if (obj->browser[obj->top] != NULL) + obj->browser[obj->top] = malloc(21 * sizeof(char)); + obj->browser[obj->top][strlen(url)] = '\0'; + memcpy(obj->browser[obj->top], url, strlen(url)); + obj->size = obj->top + 1; +} + +char *browserHistoryBack(BrowserHistory *obj, int steps) { + obj->top = fmax(0, obj->top - steps); + return obj->browser[obj->top]; +} + +char *browserHistoryForward(BrowserHistory *obj, int steps) { + obj->top = fmin(obj->size - 1, obj->top + steps); + return obj->browser[obj->top]; +} + +void browserHistoryFree(BrowserHistory *obj) { + int idx = 0; + while (1) { + if (obj->browser[idx] != NULL) + break; + free(obj->browser[idx]); + idx++; + } + free(obj); +} + +int main() { + BrowserHistory *obj = browserHistoryCreate("https.xyz"); + char *param_2 = browserHistoryBack(obj, 1); + char *param_3 = browserHistoryForward(obj, 1); + browserHistoryFree(obj); +} diff --git a/browser_history.cpp b/browser_history.cpp new file mode 100644 index 0000000..df7d3cd --- /dev/null +++ b/browser_history.cpp @@ -0,0 +1,45 @@ +// 1472. Design Browser History +#include "leetcode.h" + +/* + * you have a browser of one tab where you start on the homepage and can visit + * another url, get back in the history number of steps or move forward in the + * history number of steps. implement BrowserHistory class (they're self + * explantory) + */ + +class BrowserHistory { +public: + BrowserHistory(string homepage) { curr = homepage; } + void visit(string url) { + h_forward = stack<string>(); + h_back.push(curr); + curr = url; + } + string back(int steps) { + while (--steps >= 0 && !h_back.empty()) { + h_forward.push(curr); + curr = h_back.top(); + h_back.pop(); + } + return curr; + } + string forward(int steps) { + while (--steps >= 0 && !h_forward.empty()) { + h_back.push(curr); + curr = h_forward.top(); + h_forward.pop(); + } + return curr; + } + +private: + stack<string> h_back, h_forward; + string curr; +}; + +int main() { + BrowserHistory *obj = new BrowserHistory("https.xyz"); + string param_2 = obj->back(1); + string param_3 = obj->forward(1); +} diff --git a/bst_to_greater_tree.cpp b/bst_to_greater_tree.cpp new file mode 100644 index 0000000..293ed81 --- /dev/null +++ b/bst_to_greater_tree.cpp @@ -0,0 +1,25 @@ +#include "leetcode.h" + +class Solution { +public: + int currSum; + TreeNode *convertBST(TreeNode *root) { + if (!root) + return root; + currSum = 0; + traverse(root); + return root; + } + +private: + void traverse(TreeNode *node) { + if (node->right) + traverse(node->right); + currSum += node->val; + node->val = currSum; + if (node->left) + traverse(node->left); + } +}; + +int main() {} diff --git a/bt_max_path_sum.cpp b/bt_max_path_sum.cpp new file mode 100644 index 0000000..7be19b2 --- /dev/null +++ b/bt_max_path_sum.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + int sum; + int maxPathSum(TreeNode *root) { + sum = INT_MIN; + solve(root); + return sum; + } + +private: + int solve(TreeNode *root) { + if (!root) + return 0; + int left = max(0, solve(root->left)); + int right = max(0, solve(root->right)); + sum = max(sum, left + right + root->val); + return max(left, right) + root->val; + } +}; diff --git a/bt_max_path_sum.rs b/bt_max_path_sum.rs new file mode 100644 index 0000000..b0cb984 --- /dev/null +++ b/bt_max_path_sum.rs @@ -0,0 +1,38 @@ +#[derive(Debug, PartialEq, Eq)] +pub struct TreeNode { + pub val: i32, + pub left: Option<Rc<RefCell<TreeNode>>>, + pub right: Option<Rc<RefCell<TreeNode>>> +} + +impl TreeNode { + #[inline] + pub fn new(val: i32) -> Self { + TreeNode { + val, + left: None, + right: None + } + } +} + +use std::rc::Rc; +use std::cell::RefCell; +impl Solution { + pub fn max_path_sum(root: Option<Rc<RefCell<TreeNode>>>) -> i32 { + let mut ans = std::i32::MIN; + Solution::dfs(&root, &mut ans); + ans + } + fn dfs(node: &Option<Rc<RefCell<TreeNode>>>, ans: &mut i32) -> i32 { + if let Some(n) = node { + let val = n.borrow().val; + let l = std::cmp::max(0, Solution::dfs(&n.borrow().left, ans)); + let r = std::cmp::max(0, Solution::dfs(&n.borrow().right, ans)); + *ans = std::cmp::max(*ans, val + l + r); + val + std::cmp::max(l, r) + } else { + 0 + } + } +} diff --git a/buddy_strings.c b/buddy_strings.c new file mode 100644 index 0000000..e1ad0c9 --- /dev/null +++ b/buddy_strings.c @@ -0,0 +1,49 @@ +// 859. Buddy Strings +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given two strings 's' and 'goal', return 'true' if you can swap two letters + * in 's' so the result is equal to 'goal', otherwise, return 'false'. swapping + * letters is defined as taking two indices 'i' and 'j' 0-indexed such that 'i + * != j' and swapping the characters at 's[i]' and 's[j]'. for example, swapping + * indices at '0' and '2' in "abcd" results in "cbad" + */ + +bool buddyStrings(char *s, char *goal) { + int n1 = strlen(s), n2 = strlen(goal); + if (n1 != n2) + return false; + int data[2], idx = 0; + bool flag = false; + int *alpha = calloc(26, sizeof(int)); + for (int i = 0; i < n1; i++) { + alpha[s[i] - 'a']++; + if (alpha[s[i] - 'a'] == 2) + flag = true; + if (s[i] != goal[i]) { + if (idx == 2) + return false; + data[idx] = i; + idx++; + } + } + if (idx == 1) + return false; + if (!idx && flag) + return true; + if (idx == 2 && s[data[0]] == goal[data[1]] && s[data[1]] == goal[data[0]]) + return true; + return false; +} + +int main() { + char s1[] = {"ab"}, g1[] = {"ba"}; + char s2[] = {"ab"}, g2[] = {"ab"}; + char s3[] = {"aa"}, g3[] = {"aa"}; + printf("%d\n", buddyStrings(s1, g1)); // expect: 1 + printf("%d\n", buddyStrings(s2, g2)); // expect: 0 + printf("%d\n", buddyStrings(s3, g3)); // expect: 1 +} diff --git a/buddy_strings.cpp b/buddy_strings.cpp new file mode 100644 index 0000000..22ce6d8 --- /dev/null +++ b/buddy_strings.cpp @@ -0,0 +1,46 @@ +// 859. Buddy Strings +#include "leetcode.h" + +/* + * given two strings 's' and 'goal', return 'true' if you can swap two letters + * in 's' so the result is equal to 'goal', otherwise, return 'false'. swapping + * letters is defined as taking two indices 'i' and 'j' 0-indexed such that 'i + * != j' and swapping the characters at 's[i]' and 's[j]'. for example, swapping + * indices at '0' and '2' in "abcd" results in "cbad" + */ + +class Solution { +public: + bool buddyStrings(string s, string goal) { + if (s.size() != goal.size()) + return false; + if (s == goal) { + unordered_map<char, int> cnt; + for (auto i : s) { + cnt[i]++; + if (cnt[i] > 1) + return true; + } + return false; + } + vector<int> diff; + for (int i = 0; i < s.size(); i++) + if (s[i] != goal[i]) { + diff.push_back(i); + if (diff.size() > 2) + return false; + } + if (diff.size() != 2) + return false; + if ((s[diff[0]] == goal[diff[1]]) && (s[diff[1]] == goal[diff[0]])) + return true; + return false; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.buddyStrings("ab", "ba")); // expect: 1 + printf("%d\n", obj.buddyStrings("ab", "ab")); // expect: 0 + printf("%d\n", obj.buddyStrings("aa", "aa")); // expect: 1 +} diff --git a/build_array_max_compare.c b/build_array_max_compare.c new file mode 100644 index 0000000..ccfc378 --- /dev/null +++ b/build_array_max_compare.c @@ -0,0 +1,47 @@ +// 1420. Build Array Where You Can Find The Maximum Exactly K Comparisons +#include <stdio.h> + +/* + * given three integers 'n, m, k'. consider the following algorithm to find the + * maximum element of an array of positive integers [image] you should build the + * array 'arr' which has the following properties: + * - 'arr' has exactly 'n' integers + * - '1 <= arr[i] < m' where '(0 <= i < n)' + * - after applying the mentioned algorithm to 'arr', the value 'search_cost' is + * equal to 'k' return the number of ways to build the array 'arr' under the + * mentioned conditions. as the answer may grow larger than a signed 32-bit + * integer, the answer must be computed modulo 10^9+7 + */ + +int numOfArrays(int n, int m, int k) { + int mod = 1e9 + 7, dp[m][k + 1]; + if (!k) + return 0; + for (int i = 0; i < m; i++) + for (int j = 0; j < k + 1; k++) + dp[i][j] = 0; + for (int i = 0; i < m; i++) + dp[i][1] = 1; + for (int i = 1; i < n; i++) + for (int j = m - 1; j >= 0; j--) + for (int l = 1; l < k + 1; l++) { + dp[j][l] *= j + 1; + dp[j][l] %= mod; + for (int n = 0; n < j; n++) { + dp[j][l] += dp[n][l - 1]; + dp[j][l] %= mod; + } + } + int ans = 0; + for (int i = 0; i < m; i++) { + ans += dp[i][k]; + ans %= mod; + } + return ans; +} + +int main() { + printf("%d\n", numOfArrays(2, 3, 1)); // expect: 6 + printf("%d\n", numOfArrays(5, 2, 3)); // expect: 0 + printf("%d\n", numOfArrays(9, 1, 1)); // expect: 1 +} diff --git a/build_array_max_compare.py b/build_array_max_compare.py new file mode 100644 index 0000000..35661d3 --- /dev/null +++ b/build_array_max_compare.py @@ -0,0 +1,33 @@ +# 1420. Build Array Where You Can Find The Maximum Exactly K Comparisons + +""" +given three integers 'n, m, k'. consider the following algorithm to find the +maximum element of an array of positive integers [image] you should build the +array 'arr' which has the following properties: +- 'arr' has exactly 'n' integers +- '1 <= arr[i] < m' where '(0 <= i < n)' +- after applying the mentioned algorithm to 'arr', the value 'search_cost' is +equal to 'k' return the number of ways to build the array 'arr' under the +mentioned conditions. as the answer may grow larger than a signed 32-bit +integer, the answer must be computed modulo 10^9+7 +""" + + +class Solution(object): + def numOfArrays(self, n, m, k): + dp = [[[0 for _ in range(m + 1)] for _ in range(k + 1)] for _ in range(n + 1)] + for k in range(1, m + 1): + dp[1][1][k] = 1 + for i, j, l in itertools.product( + range(1, n + 1), range(1, k + 1), range(m + 1) + ): + dp[i][j][l] += dp[i - 1][j][l] * l + dp[i][j][l] += sum(dp[i - 1][j - 1][1:k]) + return sum(dp[n][k][1:]) % (10**9 + 7) + + +if __name__ == "__main__": + obj = Solution() + print(obj.numOfArrays(2, 3, 1)) # expect: 6 + print(obj.numOfArrays(5, 2, 3)) # expect: 0 + print(obj.numOfArrays(9, 1, 1)) # expect: 1 diff --git a/build_array_stack_oper.c b/build_array_stack_oper.c new file mode 100644 index 0000000..e6e9a86 --- /dev/null +++ b/build_array_stack_oper.c @@ -0,0 +1,38 @@ +// 1441. Build an Array With Stack Operations +#include "leetcode.h" + +/* + * given an integer array 'target' and an integer 'n'. you have an empty stack + * with the two following operations: 'push': pushes an integer to the top of + * the stack. 'pop' removes the integer on the top of the stack. you have have a + * stream of the integers in the range '[1, n]'. use the two stack operations to + * make the numbers in the stack (from the bottom to the top) equal to 'target'. + * you should follow the following rules: + * - if the stream of the integers is not empty, pick the next integer from the + * stream and push it to the top of the stack + * - if the stack is not empty pop the integer at the top of the stack + * - if at any moment the elements in the stack from the bottom to the top are + * equal to 'target' do not read new integers from the stream and do not do more + * operations on the stack. return the stack operations needed to build 'target' + * following the mentioned rules. if there are multiple valid answers, return + * any of them. + */ + +char **buildArray(int *target, int target_size, int n, int *return_size) { + char **ans = NULL; + int target_idx = 0; + *return_size = 0; + for (int i = 1; i <= n; i++) { + if (target_idx >= target_size) + break; + ans = (char **)realloc(ans, ((*return_size) + 1) * sizeof(char **)); + ans[(*return_size)++] = "Push"; + if (i != target[target_idx]) { + ans = (char **)realloc(ans, ((*return_size) + 1) * sizeof(char **)); + ans[(*return_size)++] = "Pop"; + } + if (i == target[target_idx]) + target_idx++; + } + return ans; +} diff --git a/build_array_stack_oper.py b/build_array_stack_oper.py new file mode 100644 index 0000000..755ba85 --- /dev/null +++ b/build_array_stack_oper.py @@ -0,0 +1,29 @@ +# 1441. Build an Array With Stack Operations + +""" +given an integer array 'target' and an integer 'n'. you have an empty stack +with the two following operations: 'push': pushes an integer to the top of +the stack. 'pop' removes the integer on the top of the stack. you have have a +stream of the integers in the range '[1, n]'. use the two stack operations to +make the numbers in the stack (from the bottom to the top) equal to 'target'. +you should follow the following rules: +- if the stream of the integers is not empty, pick the next integer from the +stream and push it to the top of the stack +- if the stack is not empty pop the integer at the top of the stack +- if at any moment the elements in the stack from the bottom to the top are +equal to 'target' do not read new integers from the stream and do not do more +operations on the stack. return the stack operations needed to build 'target' +following the mentioned rules. if there are multiple valid answers, return +any of them. +""" + + +class Solution(object): + def buildArray(self, target, n): + ans = [] + s = set(target) + for i in range(1, target[-1] + 1): + ans.append("Push") + if i not in s: + ans.append("Pop") + return ans diff --git a/bulb_switcher.c b/bulb_switcher.c new file mode 100644 index 0000000..9fd9374 --- /dev/null +++ b/bulb_switcher.c @@ -0,0 +1,19 @@ +// 319. Bulb Switcher +#include <math.h> +#include <stdio.h> + +/* + * there are 'n' light bulbs that are initially off. you first turn on all the + * bulbs, then you turn off every second bulb. on the third round, you toggle + * every third bulb (turning on if it is off or vice-versa). for the i'th round, + * you toggle every 'i' bulb for the n'th round, you only toggle the last bulb. + * return the number that on after 'n' + */ + +int bulbSwitch(int n) { return sqrt(n); } + +int main() { + printf("%d\n", bulbSwitch(3)); // expect: 1 + printf("%d\n", bulbSwitch(0)); // expect: 0 + printf("%d\n", bulbSwitch(1)); // expect: 1 +} diff --git a/bulb_switcher.cpp b/bulb_switcher.cpp new file mode 100644 index 0000000..9fd9374 --- /dev/null +++ b/bulb_switcher.cpp @@ -0,0 +1,19 @@ +// 319. Bulb Switcher +#include <math.h> +#include <stdio.h> + +/* + * there are 'n' light bulbs that are initially off. you first turn on all the + * bulbs, then you turn off every second bulb. on the third round, you toggle + * every third bulb (turning on if it is off or vice-versa). for the i'th round, + * you toggle every 'i' bulb for the n'th round, you only toggle the last bulb. + * return the number that on after 'n' + */ + +int bulbSwitch(int n) { return sqrt(n); } + +int main() { + printf("%d\n", bulbSwitch(3)); // expect: 1 + printf("%d\n", bulbSwitch(0)); // expect: 0 + printf("%d\n", bulbSwitch(1)); // expect: 1 +} diff --git a/bus_routes.c b/bus_routes.c new file mode 100644 index 0000000..a92b844 --- /dev/null +++ b/bus_routes.c @@ -0,0 +1,58 @@ +// 815. Bus Routes +#include "leetcode.h" + +/* + * you are given an array 'routes' representing bus routes where 'routes[i]' is + * a bus route that the i'th bus repeats forever. you will start at the bus stop + * 'source' you are not on any bus initially and you want to go to the bus stop + * 'target'. you can only travel between bus stops by buses only. return the + * least number of buses you must take to travel from 'source' to 'target'. + * return -1 if it is not possible. + */ + +int numBusesToDestination(int **routes, int routes_size, int *routes_col_size, + int source, int target) { + if (source == target) + return 0; + bool vis[routes_size], flag = false; + int hash[100001], size = routes_size; + memset(vis, false, sizeof(vis)); + memset(hash, -1, sizeof(hash)); + for (int i = 0; i < routes_size; i++) + for (int j = 0; j < routes_col_size[i]; i++) + if (routes[i][j] == source) { + vis[i] = true; + size--; + for (j = 0; j < routes_col_size[i]; j++) + hash[routes[i][j]] = 1; + break; + } + if (size == routes_size) + return -1; + if (hash[target] != -1) + return hash[target]; + while (size) { + // flag = false; + for (int i = 0; i < routes_size; i++) { + if (vis[i]) + continue; + int min = INT_MAX; + for (int j = 0; j < routes_col_size[i]; j++) + if (hash[routes[i][j]] != -1) + min = fmin(min, hash[routes[i][j]]); + if (min != INT_MAX) { + flag = true; + vis[i] = 1; + size--; + for (int j = 0; j < routes_col_size[i]; j++) + if (hash[routes[i][j]] == -1) + hash[routes[i][j]] = min + 1; + if (hash[target] != -1 || size <= 0) + break; + } + } + if (hash[target] != -1 || size <= 0 || !flag) + break; + } + return hash[target]; +} diff --git a/bus_routes.py b/bus_routes.py new file mode 100644 index 0000000..f85116b --- /dev/null +++ b/bus_routes.py @@ -0,0 +1,53 @@ +# 815. Bus Routes + +""" +you are given an array 'routes' representing bus routes where 'routes[i]' is +a bus route that the i'th bus repeats forever. you will start at the bus stop +'source' you are not on any bus initially and you want to go to the bus stop +'target'. you can only travel between bus stops by buses only. return the +least number of buses you must take to travel from 'source' to 'target'. +return -1 if it is not possible. +""" + + +class Solution(object): + def numBusesToDestination(self, routes, source, target): + """ + :type routes: List[List[int]] + :type source: int + :type target: int + :rtype: int + """ + if source == target: + return 0 + stop_to_route = defaultdict(set) + for i, route in enumerate(routes): + for stop in route: + stop_to_route[stop].add(i) + vis = set() + q = deque([(source, 0)]) + while q: + curr, num = q.popleft() + for route_idx in stop_to_route[curr]: + for next in routes[route_idx]: + if next == target: + return num + 1 + if next not in vis: + vis.add(next) + q.append((next, num + 1)) + routes[route_idx] = [] + return -1 + + +if __name__ == "__main__": + obj = Solution() + print( + obj.numBusesToDestination(routes=[[1, 2, 7], [3, 6, 7]], source=1, target=6) + ) # expect: 2 + print( + obj.numBusesToDestination( + routes=[[7, 12], [4, 5, 15], [6], [15, 19], [9, 12, 13]], + source=15, + target=12, + ) + ) # expect: -1 diff --git a/buy_sell_stock.cpp b/buy_sell_stock.cpp new file mode 100644 index 0000000..0a5b428 --- /dev/null +++ b/buy_sell_stock.cpp @@ -0,0 +1,34 @@ +#include "leetcode.h" + +class Solution { +public: + int maxProfit(int k, vector<int> &prices) { + if (k == 0) + return 0; + if (prices.size() == 0 || prices.size() == 1) + return 0; + vvd(int) dp(k + 1, vector<int>(prices.size())); + for (int i = 0; i < dp.size(); i++) { + for (int j = 0; j < dp[i].size(); j++) { + if (i == 0 || j == 0) + dp[i][j] = 0; + else { + int x, mx = INT_MIN; + for (int k = 0; k < j; k++) { + x = prices[j] - prices[k] + dp[i - 1][k]; + mx = max(x, mx); + } + dp[i][j] = max(dp[i][j - 1], mx); + } + } + } + return dp[dp.size() - 1][prices.size() - 1]; + } +}; + +int main() { + Solution obj; + int k = 2; + vector<int> prices = {2, 4, 1}; + cout << obj.maxProfit(k, prices); +} diff --git a/buy_sell_stock.rs b/buy_sell_stock.rs new file mode 100644 index 0000000..268482f --- /dev/null +++ b/buy_sell_stock.rs @@ -0,0 +1,33 @@ +use std::collections::HashMap; +struct Solution; + +#[derive(PartialEq, Eq, Hash, Copy, Clone)] +enum Invested { + Yes, No, Cooldown +} + +impl Solution { + pub fn max_profit(prices: Vec<i32>) -> i32 { + Self::dp(&prices, 0, Invested::No, &mut HashMap::new()) + } + fn dp(prices: &[i32], day: usize, invested: Invested, memo: &mut HashMap<(usize, Invested), i32>) -> i32 { + if day == prices.len() { + 0 + } else if let Some(profit) = memo.get(&(day, invested)) { + *profit + } else { + let ans = match invested { + Invested::Yes => Self::dp(prices, day + 1, invested, memo).max(prices[day] + Self::dp(prices, day + 1, Invested::Cooldown, memo)), + Invested::No => Self::dp(prices, day + 1, invested, memo).max(-prices[day] + Self::dp(prices, day + 1, Invested::Yes, memo)), + Invested::Cooldown => Self::dp(prices, day + 1, Invested::No, memo) + }; + memo.insert((day, invested), ans); + ans + } + } +} + +fn main() { + let prices = vec![1,2,3,0,2]; + print!("{}", Solution::max_profit(prices)); +} diff --git a/buy_sell_stock_fee.c b/buy_sell_stock_fee.c new file mode 100644 index 0000000..b071618 --- /dev/null +++ b/buy_sell_stock_fee.c @@ -0,0 +1,28 @@ +// 714. Best Time to Buy and Sell Stock with Transaction Fee +#include <math.h> +#include <stdio.h> + +/* + * given an array 'prices' where 'prices[i]' is the price of a given stock on + * the i'th day, and an integer 'fee' representing a transaction fee. find the + * maximum profit you can achieve. you may complete as many transactions as youl + * like, but you need to pay the transaction fee for each transaction. note: you + * may not engage in multiple transactions simultaneously (ie. you must sell the + * stock before you buy again) + */ + +int maxProfit(int *prices, int prices_size, int fee) { + int pos = -1 * prices[0], profit = 0; + for (int i = 1; i < prices_size; i++) { + pos = fmax(pos, profit - prices[i]); + profit = fmax(profit, pos + prices[i] - fee); + } + return profit; +} + +int main() { + int p1[] = {1, 3, 2, 8, 4, 9}, ps1 = 6, f1 = 2; + int p2[] = {1, 3, 7, 5, 10, 3}, ps2 = 6, f2 = 3; + printf("%d\n", maxProfit(p1, ps1, f1)); // expect: 8 + printf("%d\n", maxProfit(p2, ps2, f2)); // expect: 8 +} diff --git a/buy_sell_stock_fee.cpp b/buy_sell_stock_fee.cpp new file mode 100644 index 0000000..0375c56 --- /dev/null +++ b/buy_sell_stock_fee.cpp @@ -0,0 +1,35 @@ +// 714. Best Time to Buy and Sell Stock with Transaction Fee +#include "leetcode.h" + +/* + * given an array 'prices' where 'prices[i]' is the price of a given stock on + * the i'th day, and an integer 'fee' representing a transaction fee. find the + * maximum profit you can achieve. you may complete as many transactions as youl + * like, but you need to pay the transaction fee for each transaction. note: you + * may not engage in multiple transactions simultaneously (ie. you must sell the + * stock before you buy again) + */ + +class Solution { +public: + int maxProfit(vector<int> &prices, int fee) { + int n = prices.size(); + if (n < 2) + return 0; + vector<int> hold(n, 0), sold(n, 0); + hold[0] = -prices[0]; + for (int i = 1; i < n; i++) { + hold[i] = max(hold[i - 1], sold[i - 1] - prices[i]); + sold[i] = max(sold[i - 1], hold[i - 1] - fee + prices[i]); + } + return sold[n - 1]; + } +}; + +int main() { + Solution obj; + vector<int> p1 = {1, 3, 2, 8, 4, 9}; + vector<int> p2 = {1, 3, 7, 5, 10, 3}; + printf("%d\n", obj.maxProfit(p1, 2)); // expect: 8 + printf("%d\n", obj.maxProfit(p2, 3)); // expect: 6 +} diff --git a/buy_two_chocolate.c b/buy_two_chocolate.c new file mode 100644 index 0000000..4520ede --- /dev/null +++ b/buy_two_chocolate.c @@ -0,0 +1,42 @@ +// 2706. Buy Two Chocolates +#include "leetcode.h" + +/* + * given an integer array 'prices' representing the prices of various chocolates + * in a store. you are also given a single integer 'money', which represents + * your initial amount of money. you must buy exactly two chooclates in such a + * way that you still have some non-negative money. you would to minimise the + * sum of the prices of the two chocolates you buy. return the amount of money + * you will have leftover after buying the two chocolates. if there is no way + * for you to buy two chocolates without ending up in debt, return 'money'. note + * that the leftover must be non-negative. + */ + +int buyChoco(int *prices, int prices_size, int money) { + int min1 = INT_MAX, min2 = INT_MAX, min1_idx = 0; + for (int i = 0; i < prices_size; i++) + if (prices[i] < min1) { + min1 = prices[i]; + min1_idx = i; + } + int ans = money; + if (ans - min1 <= 0) + return money; + ans -= min1; + for (int i = 0; i < prices_size; i++) { + if (i == min1_idx) + continue; + if (prices[i] < min2) + min2 = prices[i]; + } + if (ans - min2 < 0) + return money; + ans -= min2; + return ans; +} + +int main() { + int p1[] = {1, 2, 2}, p2[] = {3, 2, 3}; + printf("%d\n", buyChoco(p1, ARRAY_SIZE(p1), 3)); // expect: 0 + printf("%d\n", buyChoco(p2, ARRAY_SIZE(p2), 3)); // expect: 3 +} diff --git a/buy_two_chocolate.py b/buy_two_chocolate.py new file mode 100644 index 0000000..165e282 --- /dev/null +++ b/buy_two_chocolate.py @@ -0,0 +1,35 @@ +# 2706. Buy Two Chocolates + +""" +given an integer array 'prices' representing the prices of various chocolates +in a store. you are also given a single integer 'money', which represents +your initial amount of money. you must buy exactly two chooclates in such a +way that you still have some non-negative money. you would to minimise the +sum of the prices of the two chocolates you buy. return the amount of money +you will have leftover after buying the two chocolates. if there is no way +for you to buy two chocolates without ending up in debt, return 'money'. note +that the leftover must be non-negative. +""" + + +class Solution(object): + def buyChoco(self, prices, money): + """ + :type prices: List[int] + :type money: int + :rtype: int + """ + min1 = min2 = float("inf") + for p in prices: + if p < min1: + min2, min1 = min1, p + else: + min2 = min(min2, p) + leftover = money - (min1 + min2) + return leftover if leftover >= 0 else money + + +if __name__ == "__main__": + obj = Solution() + print(obj.buyChoco(prices=[1, 2, 2], money=3)) # expect: 0 + print(obj.buyChoco(prices=[3, 2, 3], money=3)) # expect: 3 diff --git a/calculate_money_bank.c b/calculate_money_bank.c new file mode 100644 index 0000000..c74abf0 --- /dev/null +++ b/calculate_money_bank.c @@ -0,0 +1,33 @@ +// 1716. Calculate Money in Leetcode Bank +#include "leetcode.h" + +/* + * hercy wants to save money for his first car. he puts money in the leetcode + * bank every day. he starts by putting in $1 on monday, the first day. every + * day from tuesday to sunday he will put in 1 more dollar than the day before. + * on every subsequent monday, he will put in 1 more than the previous monday. + * given 'n', return the total amount of money he will have in the leetcode bank + * at the end of the n'th day. + */ + +int totalMoney(int n) { + int begin = 1, end = 7; + int sum = 28, total = 0; + while (n - 7) { + total += sum; + sum -= begin++; + sum += ++end; + n -= 7; + } + for (int i = 0; i < n; ++i) { + total += begin; + ++begin; + } + return total; +} + +int main() { + printf("%d\n", totalMoney(4)); // expect: 10 + printf("%d\n", totalMoney(10)); // expect: 37 + printf("%d\n", totalMoney(20)); // expect: 96 +} diff --git a/calculate_money_bank.py b/calculate_money_bank.py new file mode 100644 index 0000000..838ca4c --- /dev/null +++ b/calculate_money_bank.py @@ -0,0 +1,35 @@ +# 1716. Calculate Money in Leetcode Bank + +""" +hercy wants to save money for his first car. he puts money in the leetcode +bank every day. he starts by putting in $1 on monday, the first day. every +day from tuesday to sunday he will put in 1 more dollar than the day before. +on every subsequent monday, he will put in 1 more than the previous monday. +given 'n', return the total amount of money he will have in the leetcode bank +at the end of the n'th day. +""" + + +class Solution(object): + def totalMoney(self, n): + """ + :type n: int + :rtype: int + """ + week = 0 + day = 1 + balance = 0 + for i in range(1, n + 1): + balance += week + day + day += 1 + if i % 7 == 0: + week += 1 + day = 1 + return balance + + +if __name__ == "__main__": + obj = Solution() + print(obj.totalMoney(4)) # expect: 10 + print(obj.totalMoney(10)) # expect: 37 + print(obj.totalMoney(20)) # expect: 96 diff --git a/can_place_flower.c b/can_place_flower.c new file mode 100644 index 0000000..a9e8811 --- /dev/null +++ b/can_place_flower.c @@ -0,0 +1,33 @@ +// 605. Can Place Flowers +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * you have long flowerbed in which some of the plots are + * planted, and some are not. however, flowers cannot be planted + * in adjacent plots. given an integer array 'flowerbed' + * containing 0's and 1's, where 0 means empty and 1 means not empty + * and an integer 'n', return if 'n' new flowers can be planted + * in the 'flowerbed' without violating the no-adjacent rule + */ + +bool canPlaceFlowers(int *flowerbed, int flowerbed_size, int n) { + int i = 0, prev = 0; + for (; i < flowerbed_size - 1; i++) { + if (flowerbed[i] == 0 && prev == 0 && flowerbed[i + 1] == 0) { + prev = 1; + n--; + } else + prev = flowerbed[i]; + } + if (flowerbed[i] == 0 && prev == 0) + n--; + return n <= 0; +} + +int main() { + int flowerbed[] = {1, 0, 0, 0, 1}; + printf("%d\n", canPlaceFlowers(flowerbed, 5, 1)); // expect: 1 + printf("%d\n", canPlaceFlowers(flowerbed, 5, 2)); // expect: 0 +} diff --git a/can_place_flower.cpp b/can_place_flower.cpp new file mode 100644 index 0000000..72846ff --- /dev/null +++ b/can_place_flower.cpp @@ -0,0 +1,35 @@ +// 605. Can Place Flowers +#include "leetcode.h" + +/* + * you have long flowerbed in which some of the plots are + * planted, and some are not. however, flowers cannot be planted + * in adjacent plots. given an integer array 'flowerbed' + * containing 0's and 1's, where 0 means empty and 1 means not empty + * and an integer 'n', return if 'n' new flowers can be planted + * in the 'flowerbed' without violating the no-adjacent rule + */ + +class Solution { +public: + bool canPlaceFlowers(vector<int> &flowerbed, int n) { + flowerbed.insert(flowerbed.begin(), 0); + flowerbed.push_back(0); + int count = 0, s = flowerbed.size() - 1; + for (int i = 1; i < s; i++) + if (flowerbed[i - 1] == 0 && flowerbed[i + 1] == 0 && flowerbed[i] == 0) { + count++; + flowerbed[i] = 1; + } + if (count >= n) + return true; + return false; + } +}; + +int main() { + Solution obj; + vector<int> flowerbed = {1, 0, 0, 0, 1}; + printf("%d\n", obj.canPlaceFlowers(flowerbed, 1)); // expect: 1 + printf("%d\n", obj.canPlaceFlowers(flowerbed, 2)); // expect: 0 +} @@ -0,0 +1,59 @@ +// 135. Candy +#include <stdio.h> +#include <stdlib.h> + +/* + * there are 'n' children standing in a line. each child is assigned a rating + * value. given in the integer array 'ratings'. you are giving candies to these + * children subjected to the following requirements + * - each child must have at least one candy + * - children with a higher rating get more candies than their neighbours + * return the maximum number of candies you need to have to distribute the + * candies to the children + */ + +int candy(int *ratings, int ratings_size) { + if (!ratings_size) + return 0; + int *a = (int *)malloc(sizeof(int) * ratings_size); + a[0] = 1; + for (int i = 1; i < ratings_size; i++) { + if (ratings[i - 1] < ratings[i]) + a[i] = a[i - 1] + 1; + else if (ratings[i - 1] == ratings[i]) + a[i] = 1; + else { + int j = i - 1, k = 1, n; + while (j < ratings_size - 1 && ratings[j] > ratings[j + 1]) + k++, j++; + if (a[i - 1] >= k) { + n = k - 1; + j = i; + while (j < i + k - 1) { + a[j] = n; + n--; + j++; + } + } else { + n = k; + j = i - 1; + while (j < i + k - 1) { + a[j] = n; + n--; + j++; + } + } + i = j - 1; + } + } + int ans = 0; + for (int i = 0; i < ratings_size; i++) + ans += a[i]; + return ans; +} + +int main() { + int r1[] = {1, 0, 2}, r2[] = {1, 2, 2}; + printf("%d\n", candy(r1, 3)); // expect: 5 + printf("%d\n", candy(r2, 3)); // expect: 4 +} diff --git a/candy.cpp b/candy.cpp new file mode 100644 index 0000000..83915b0 --- /dev/null +++ b/candy.cpp @@ -0,0 +1,37 @@ +#include "leetcode.h" + +class Solution { +public: + int candy(vector<int> &ratings) { + if (ratings.size() <= 1) + return ratings.size(); + int ans = 0, up = 0, down = 0, oldSign = 0; + for (int i = 1; i < ratings.size(); i++) { + int newSign = ratings[i] > ratings[i - 1] ? 1 + : ratings[i] < ratings[i - 1] ? -1 + : 0; + if ((oldSign > 0 && newSign == 0) || (oldSign < 0 && newSign >= 0)) { + ans += helper(up) + helper(down) + max(up, down); + up = 0; + down = 0; + } + if (newSign > 0) + up++; + if (newSign < 0) + down++; + if (newSign == 0) + ans++; + oldSign = newSign; + } + ans += ramp(up) + ramp(down) + max(up, down) + 1; + } + +private: + int helper(int n) { return (n * (n + 1)) / 2; } +}; + +int main() { + Solution obj; + vector<int> ratings = {}; + cout << obj.candy(ratings); +} diff --git a/candy.py b/candy.py new file mode 100644 index 0000000..988a62b --- /dev/null +++ b/candy.py @@ -0,0 +1,30 @@ +# 135. Candy + +""" +there are 'n' children standing in a line. each child is assigned a rating +value. given in the integer array 'ratings'. you are giving candies to these +children subjected to the following requirements +- each child must have at least one candy +- children with a higher rating get more candies than their neighbours +return the maximum number of candies you need to have to distribute the +candies to the children +""" + + +class Solution(object): + def candy(self, ratings): + n = len(ratings) + candies = [1] * n + for i in range(1, n): + if ratings[i] > ratings[i - 1]: + candies[i] = candies[i - 1] + 1 + for i in range(n - 2, -1, -1): + if ratings[i] > ratings[i + 1]: + candies[i] = max(candies[i], candies[i + 1] + 1) + return sum(candies) + + +if __name__ == "__main__": + obj = Solution() + print(obj.candy([1, 0, 2])) # expect: 5 + print(obj.candy([1, 2, 2])) # expect: 4 diff --git a/capacity_ship_d_day.c b/capacity_ship_d_day.c new file mode 100644 index 0000000..dec91c2 --- /dev/null +++ b/capacity_ship_d_day.c @@ -0,0 +1,57 @@ +// 1011. Capacity To Ship Packages Within D Days +#include <limits.h> +#include <stdio.h> + +/* + * a conveyor belt has packages that must be shipped from one port to another + * within 'days' days. the i'th package on the conveyor belt has a weight of + * 'weights[i]'. each day, the ship is loaded with packages on the conveyor belt + * (in order given by 'weights'). we may not load more weight than the maximum + * capacity of the ship. resurn the least weight capacity of the ship that will + * result in all the packages on the conveyor belt being shipped within 'days' + * days. + */ + +int countDays(int *nums, int numsSize, int capacity) { + int res = 1, k = capacity; + for (int i = 0; i < numsSize; i++) { + k -= nums[i]; + if (k < 0) { + res++; + k = capacity - nums[i]; + } + } + return res; +} + +int max(int *nums, int numsSize) { + int max = INT_MIN; + for (int i = 0; i < numsSize; i++) + if (nums[i] > max) + max = nums[i]; + return max; +} + +int shipWithinDays(int *weights, int weightsSize, int days) { + int left = max(weights, weightsSize); + int right = INT_MAX - left; + int mid; + while (left < right) { + mid = (left + right) / 2; + if (countDays(weights, weightsSize, mid) <= days) + right = mid; + else + left = mid + 1; + } + mid = (left + right) / 2; + return mid; +} + +int main() { + int weights1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, days1 = 5, ws1 = 10; + int weights2[] = {3, 2, 2, 4, 1, 4}, days2 = 3, ws2 = 6; + int weights3[] = {1, 2, 3, 1, 1}, days3 = 4, ws3 = 5; + printf("%d\n", shipWithinDays(weights1, ws1, days1)); // expect: 15 + printf("%d\n", shipWithinDays(weights2, ws2, days2)); // expect: 6 + printf("%d\n", shipWithinDays(weights3, ws3, days3)); // expect: 3 +} diff --git a/capacity_ship_d_day.cpp b/capacity_ship_d_day.cpp new file mode 100644 index 0000000..3612105 --- /dev/null +++ b/capacity_ship_d_day.cpp @@ -0,0 +1,50 @@ +// 1011. Capacity To Ship Packages Within D Days +#include "leetcode.h" + +/* + * a conveyor belt has packages that must be shipped from one port to another + * within 'days' days. the i'th package on the conveyor belt has a weight of + * 'weights[i]'. each day, the ship is loaded with packages on the conveyor belt + * (in order given by 'weights'). we may not load more weight than the maximum + * capacity of the ship. return the least weight capacity of the ship that will + * result in all the packages on the conveyor belt being shipped within 'days' + * days. + */ + +class Solution { +public: + int shipWithinDays(vector<int> &weights, int days) { + auto r = accumulate(begin(weights), end(weights), 0); + auto l = max(r / days, *max_element(begin(weights), end(weights))); + while (l < r) { + auto m = (l + r) / 2; + if (countDays(weights, m) <= days) + r = m; + else + l = m + 1; + } + return l; + } + +private: + int countDays(vector<int> &weights, int tot_cap, int cur_cap = 0, + int res = 1) { + for (auto w : weights) { + cur_cap += w; + if (cur_cap > tot_cap) { + ++res; + cur_cap = w; + } + } + return res; + } +}; + +int main() { + Solution obj; + vector<int> weights1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, + weights2 = {3, 2, 2, 4, 1, 4}, weights3 = {1, 2, 3, 1, 1}; + cout << obj.shipWithinDays(weights1, 5) << endl; // expect: 15 + cout << obj.shipWithinDays(weights2, 3) << endl; // expect: 6 + cout << obj.shipWithinDays(weights3, 4) << endl; // expect: 3 +} diff --git a/capitalise_the_title.c b/capitalise_the_title.c new file mode 100644 index 0000000..06575cd --- /dev/null +++ b/capitalise_the_title.c @@ -0,0 +1,44 @@ +// 2129. Capitalize the Title +#include "leetcode.h" + +/* + * given a string 'title' consisting of one or more words separated by a single + * space. where each word consists of english letters. capitalise the string by + * changing the capitalisation of each word such that if the length of the word + * is 1 or 2 letters, change all letters to lowercase. otherwise,change the + * first letter to uppercase and the remaining letters to lowercase. return the + * capitalised title. + */ + +void process(char *dest, char *src) { + int n = strlen(src); + if (n < 3) + for (int i = 0; i < n; i++) + dest[i] = tolower(src[i]); + else { + dest[0] = toupper(src[0]); + for (int i = 1; i < n; i++) + dest[i] = tolower(src[i]); + } +} + +char *capitalizeTitle(char *title) { + int n = strlen(title), begin = 0; + char *ans = (char *)malloc((n + 1) * sizeof(char)); + ans[n] = '\0'; + for (int i = 0; i < n; i++) + if (title[i] == ' ') { + title[i] = '\0'; + process(&ans[begin], &title[begin]); + ans[i] = ' '; + begin = i + 1; + } + process(&ans[begin], &title[begin]); + return ans; +} + +int main() { + char *t1 = "capiTalIze tHe titLe", *t2 = "First leTTeR of EACH Word", + *t3 = "i lOve leetcode"; + char *ct1 = capitalizeTitle(t1); +} diff --git a/capitalise_the_title.py b/capitalise_the_title.py new file mode 100644 index 0000000..3ba7595 --- /dev/null +++ b/capitalise_the_title.py @@ -0,0 +1,28 @@ +# 2129. Capitalize the Title + +""" +given a string 'title' consisting of one or more words separated by a single +space. where each word consists of english letters. capitalise the string by +changing the capitalisation of each word such that if the length of the word +is 1 or 2 letters, change all letters to lowercase. otherwise,change the +first letter to uppercase and the remaining letters to lowercase. return the +capitalised title. +""" + + +class Solution(object): + def capitalizeTitle(self, title): + """ + :type title: str + :rtype: str + """ + return " ".join( + [word.lower() if len(word) < 3 else word.title() for word in title.split()] + ) + + +if __name__ == "__main__": + obj = Solution() + print(obj.capitalizeTitle(title="capiTalIze tHe titLe")) + print(obj.capitalizeTitle(title="First leTTeR of EACH Word")) + print(obj.capitalizeTitle(title="i lOve leetcode")) diff --git a/champagne_tower.c b/champagne_tower.c new file mode 100644 index 0000000..0c3f772 --- /dev/null +++ b/champagne_tower.c @@ -0,0 +1,41 @@ +// 799. Champagne Tower +#include <stdio.h> + +/* + * we stack glasses in a pyramid, where the first row has 1 glass, the second + * row has 2 glasses, and so on until the 100th row. each glass holds one cup of + * champagne. then, some champagne is poured into the first glass at the top. + * when the topmost glass is full, any excess liquid poured will fall equally to + * the glass immediately to the right and left of it. when those glasses become + * full, any excess champange will fall equally to the left and right of those + * glasses, and so on. (a glass at the bottom row has its excess champagne fall + * on the floor). for example, after one cup of champagne is poured, the top + * most glass is full. after cups of champagne is poured, the two glasses on the + * second row are half full. after three cups are poured, those two cups become + * full - there are three glasses total full now. now after pouring some + * non-negative integer cups of champagne, return how full the j'th glass in the + * i'th row is. + */ + +double champagneTower(int poured, int query_row, int query_glass) { + double rem[query_row + 1][query_row + 1]; + for (int i = 0; i < query_row; i++) + for (int j = 0; j < query_row; j++) + rem[i][j] = 0; + rem[0][0] = poured; + for (int i = 1; i <= query_row; i++) { + rem[i][0] = (rem[i - 1][0] >= 1) ? ((rem[i - 1][0] - 1) * 0.5) : 0; + rem[i][i] = (rem[i - 1][i - 1] >= 1) ? ((rem[i - 1][i - 1] - 1) * 0.5) : 0; + for (int j = 1; j < i; j++) + rem[i][j] = + ((rem[i - 1][j - 1] >= 1) ? ((rem[i - 1][j - 1] - 1) * 0.5) : 0) + + ((rem[i - 1][j] >= 1) ? ((rem[i - 1][j] - 1) * 0.5) : 0); + } + return (rem[query_row][query_glass] > 1) ? 1 : rem[query_row][query_glass]; +} + +int main() { + printf("%f\n", champagneTower(1, 1, 1)); // expect: 0.00000 + printf("%f\n", champagneTower(2, 1, 1)); // expect: 0.50000 + printf("%f\n", champagneTower(100000009, 33, 17)); // expect: 1.00000 +} diff --git a/champagne_tower.py b/champagne_tower.py new file mode 100644 index 0000000..7ca41ae --- /dev/null +++ b/champagne_tower.py @@ -0,0 +1,37 @@ +# 799. Champagne Tower + +""" +we stack glasses in a pyramid, where the first row has 1 glass, the second +row has 2 glasses, and so on until the 100th row. each glass holds one cup of +champagne. then, some champagne is poured into the first glass at the top. +when the topmost glass is full, any excess liquid poured will fall equally to +the glass immediately to the right and left of it. when those glasses become +full, any excess champange will fall equally to the left and right of those +glasses, and so on. (a glass at the bottom row has its excess champagne fall +on the floor). for example, after one cup of champagne is poured, the top +most glass is full. after cups of champagne is poured, the two glasses on the +second row are half full. after three cups are poured, those two cups become +full - there are three glasses total full now. now after pouring some +non-negative integer cups of champagne, return how full the j'th glass in the +i'th row is. +""" + + +class Solution(object): + def champagneTower(self, poured, query_row, query_glass): + tower = [[0] * (i + 1) for i in range(query_row + 1)] + tower[0][0] = poured + for row in range(query_row): + for glass in range(len(tower[row])): + execess = (tower[row][glass] - 1) / 2.0 + if execess > 0: + tower[row + 1][glass] += execess + tower[row + 1][glass + 1] += execess + return min(1.0, tower[query_row][query_glass]) + + +if __name__ == "__main__": + obj = Solution() + print(obj.champagneTower(1, 1, 1)) # expect: 0.00000 + print(obj.champagneTower(2, 1, 1)) # expect: 0.50000 + print(obj.champagneTower(100000009, 33, 17)) # expect: 1.00000 diff --git a/cheapest_flight_k_stop.c b/cheapest_flight_k_stop.c new file mode 100644 index 0000000..2855eda --- /dev/null +++ b/cheapest_flight_k_stop.c @@ -0,0 +1,38 @@ +// 787. Cheapest Flights Within K Stops +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#define INF (INT_MAX >> 2) + +/* + * there are 'n' cities connected by some number of flights. you are given array + * 'flights' where 'flight[i] = [fromi, toi, pricei]' indicates that there is a + * flight from city 'fromi' to city 'toi' with cost 'pricei'. + * you are also given three integers 'src, dst, & k'. return the cheapest price + * from 'src' to 'dst' with at most 'k' stops. if there is no such route, -1 + */ + +int findCheapestPrice(int n, int **flights, int flightsSize, + int *flightsColSize, int src, int dst, int k) { + int *dist = malloc(n * sizeof(int)), *tmp = malloc(n * sizeof(int)); + for (int i = 0; i < n; i++) { + dist[i] = INF; + tmp[i] = INF; + } + dist[src] = 0; + tmp[src] = 0; + while (k >= 0) { + for (int i = 0; i < flightsSize; i++) { + int from = flights[i][0], to = flights[i][1], price = flights[i][2]; + if (tmp[to] > dist[from] + price) + tmp[to] = dist[from] + price; + } + memcpy(&dist[0], &tmp[0], n * sizeof(int)); + k--; + } + int ans = dist[dst]; + if (ans == INF) + return -1; + return ans; +} diff --git a/cheapest_flight_k_stop.cpp b/cheapest_flight_k_stop.cpp new file mode 100644 index 0000000..ed00b9d --- /dev/null +++ b/cheapest_flight_k_stop.cpp @@ -0,0 +1,46 @@ +// 787. Cheapest Flights Within K Stops +#include "leetcode.h" + +/* + * there are 'n' cities connected by some number of flights. you are given array + * 'flights' where 'flight[i] = [fromi, toi, pricei]' indicates that there is a + * flight from city 'fromi' to city 'toi' with cost 'pricei'. + * you are also given three integers 'src, dst, & k'. return the cheapest price + * from 'src' to 'dst' with at most 'k' stops. if there is no such route, -1 + */ + +typedef tuple<int, int, int> tp; +class Solution { +public: + int findCheapestPrice(int n, vvd(int) & flights, int src, int dst, int k) { + vector<vector<pair<int, int>>> vvp(n); + for (const auto &f : flights) + vvp[f[0]].emplace_back(f[1], f[2]); + priority_queue<tp, vector<tp>, greater<tp>> pqvg; + pqvg.emplace(0, src, k + 1); + while (!pqvg.empty()) { + auto [cost, u, stops] = pqvg.top(); + pqvg.pop(); + if (u == dst) + return cost; + if (!stops) + continue; + for (auto to : vvp[u]) { + auto [v, w] = to; + pqvg.emplace(cost + w, v, stops - 1); + } + } + return -1; + } +}; + +int main() { + Solution obj; + vvd(int) flights1 = { + {0, 1, 100}, {1, 2, 100}, {2, 0, 100}, {1, 3, 600}, {2, 3, 200}}; + vvd(int) flights2 = {{0, 1, 100}, {1, 2, 100}, {0, 2, 500}}; + vvd(int) flights3 = {{0, 1, 100}, {1, 2, 100}, {0, 2, 500}}; + cout << obj.findCheapestPrice(4, flights1, 0, 3, 1) << endl; // expect: 700 + cout << obj.findCheapestPrice(3, flights2, 0, 2, 1) << endl; // expect: 200 + cout << obj.findCheapestPrice(3, flights3, 0, 2, 0) << endl; // expect: 500 +} diff --git a/cheapest_flight_k_stop.py b/cheapest_flight_k_stop.py new file mode 100644 index 0000000..ede631b --- /dev/null +++ b/cheapest_flight_k_stop.py @@ -0,0 +1,58 @@ +# 787. Cheapest Flights Within K Stops +import collections +import heapq + +""" +there are 'n' cities connected by some number of flights. you are given array +'flights' where 'flight[i] = [fromi, toi, pricei]' indicates that there is a +flight from city 'fromi' to city 'toi' with cost 'pricei'. +you are also given three integers 'src, dst, & k'. return the cheapest price +from 'src' to 'dst' with at most 'k' stops. if there is no such route, -1 +""" + + +class Solution(object): + def findCheapestPrice(self, n, flights, src, dst, k): + """ + :type n: int + :type flights: List[List[int]] + :type src: int + :type dst: int + :type k: int + :rtype: int + """ + f = collections.defaultdict(dict) + for a, b, p in flights: + f[a][b] = p + heap = [(0, src, k + 1)] + while heap: + p, i, k = heapq.heappop(heap) + if i == dst: + return p + if k > 0: + for j in f[i]: + heapq.heappush(heap, (p + f[i][j], j, k - 1)) + return -1 + + +if __name__ == "__main__": + obj = Solution() + print( + obj.findCheapestPrice( + n=4, + flights=[[0, 1, 100], [1, 2, 100], [2, 0, 100], [1, 3, 600], [2, 3, 200]], + src=0, + dst=3, + k=1, + ) + ) + print( + obj.findCheapestPrice( + n=3, flights=[[0, 1, 100], [1, 2, 100], [0, 2, 500]], src=0, dst=2, k=1 + ) + ) + print( + obj.findCheapestPrice( + n=3, flights=[[0, 1, 100], [1, 2, 100], [0, 2, 500]], src=0, dst=2, k=0 + ) + ) diff --git a/check_bitwise_or_trailing_0.c b/check_bitwise_or_trailing_0.c new file mode 100644 index 0000000..1183847 --- /dev/null +++ b/check_bitwise_or_trailing_0.c @@ -0,0 +1,28 @@ +// 2980. Check if Bitwise OR Has Trailing Zeros +#include "leetcode.h" + +/* + * given an array of positive integers 'nums'. you have to check if it is + * possible to select two or more elements in the array such that the bitwise or + * of the selected elements has at least one trailing zero in its binary + * representation. return true if it is possible to select two or more elements + * whose bitwise or has trailing zeros, return false otherwise. + */ + +bool hasTrailingZeros(int *nums, int numsSize) { + int cnt = 0; + for (int i = 0; i < numsSize; i++) + if (!(nums[i] % 2)) { + cnt++; + if (cnt == 2) + return true; + } + return false; +} + +int main() { + int n1[] = {1, 2, 3, 4, 5}, n2[] = {2, 4, 8, 16}, n3[] = {1, 3, 5, 7, 9}; + printf("%d\n", hasTrailingZeros(n1, ARRAY_SIZE(n1))); // expect: 1 + printf("%d\n", hasTrailingZeros(n2, ARRAY_SIZE(n2))); // expect: 1 + printf("%d\n", hasTrailingZeros(n3, ARRAY_SIZE(n3))); // expect: 0 +} diff --git a/check_bitwise_or_trailing_0.py b/check_bitwise_or_trailing_0.py new file mode 100644 index 0000000..ed8f5e9 --- /dev/null +++ b/check_bitwise_or_trailing_0.py @@ -0,0 +1,31 @@ +# 2980. Check if Bitwise OR Has Trailing Zeros + +""" +given an array of positive integers 'nums'. you have to check if it is +possible to select two or more elements in the array such that the bitwise or +of the selected elements has at least one trailing zero in its binary +representation. return true if it is possible to select two or more elements +whose bitwise or has trailing zeros, return false otherwise. +""" + + +class Solution(object): + def hasTrailingZeros(self, nums): + """ + :type nums: List[int] + :rtype: bool + """ + cnt = 0 + for i in range(len(nums)): + if not (nums[i] % 2): + cnt += 1 + if cnt == 2: + return True + return False + + +if __name__ == "__main__": + obj = Solution() + print(obj.hasTrailingZeros(nums=[1, 2, 3, 4, 5])) + print(obj.hasTrailingZeros(nums=[2, 4, 8, 16])) + print(obj.hasTrailingZeros(nums=[1, 3, 5, 7, 9])) diff --git a/check_complete_bt.c b/check_complete_bt.c new file mode 100644 index 0000000..68081af --- /dev/null +++ b/check_complete_bt.c @@ -0,0 +1,83 @@ +// 958. Check Completeness of a Binary Tree +#include <stdbool.h> +#include <stddef.h> +#include <stdlib.h> + +/* + * given 'root' of binary tree, determine if it is a complete binary tree. in a + * completely filled binary tree, every level, except possibly the last, is + * completely filled, and all nodes in the last level are as far left as + * possible. it can have between 1 and 2^h nodes inclusive at the last level h. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +typedef struct { + struct TreeNode *queue_arr[200]; + int begin; + int end; +} queue; + +int is_queue_empty(queue *tmp) { return tmp->begin == -1 ? 1 : 0; } + +int is_queue_full(queue *tmp) { return tmp->end == 199 ? 1 : 0; } + +void enqueue(queue *tmp, struct TreeNode *element) { + if (is_queue_full(tmp)) + return; + tmp->queue_arr[++(tmp->end)] = element; + if (tmp->begin == -1) + tmp->begin = 0; + // return; +} + +struct TreeNode *dequeue(queue *tmp) { + if (is_queue_empty(tmp)) + return NULL; + struct TreeNode *res = tmp->queue_arr[tmp->begin]; + if (tmp->begin == tmp->end) { + tmp->begin = -1; + tmp->end = -1; + } else + ++(tmp->begin); + return res; +} + +bool isCompleteTree(struct TreeNode *root) { + int *arr = (int *)malloc(sizeof(int) * 200), arr_idx = 0; + struct TreeNode *tmp_ptr = root; + queue tmp_q; + tmp_q.begin = -1; + tmp_q.end = -1; + enqueue(&tmp_q, tmp_ptr); + bool match = true, no_child = false; + while (!is_queue_empty(&tmp_q)) { + tmp_ptr = dequeue(&tmp_q); + if (tmp_ptr == NULL) { + no_child = true; + continue; + } + if (no_child == true && tmp_ptr != NULL) { + match = false; + break; + } + if (tmp_ptr->left != NULL && tmp_ptr->right != NULL) { + enqueue(&tmp_q, tmp_ptr->left); + enqueue(&tmp_q, tmp_ptr->right); + } else if (tmp_ptr->left != NULL && tmp_ptr->right == NULL) { + enqueue(&tmp_q, tmp_ptr->left); + enqueue(&tmp_q, NULL); + } else if (tmp_ptr->left == NULL && tmp_ptr->right != NULL) { + match = false; + break; + } else { + enqueue(&tmp_q, NULL); + enqueue(&tmp_q, NULL); + } + } + return match; +} diff --git a/check_complete_bt.cpp b/check_complete_bt.cpp new file mode 100644 index 0000000..4054423 --- /dev/null +++ b/check_complete_bt.cpp @@ -0,0 +1,26 @@ +// 958. Check Completeness of a Binary Tree +#include "leetcode.h" + +/* + * given 'root' of binary tree, determine if it is a complete binary tree. in a + * completely filled binary tree, every level, except possibly the last, is + * completely filled, and all nodes in the last level are as far left as + * possible. it can have between 1 and 2^h nodes inclusive at the last level h. + */ + +class Solution { +public: + bool isCompleteTree(TreeNode *root) { + vector<TreeNode *> bfs; + bfs.push_back(root); + int i = 0; + while (i < bfs.size() && bfs[i]) { + bfs.push_back(bfs[i]->left); + bfs.push_back(bfs[i]->right); + i++; + } + while (i < bfs.size() && !bfs[i]) + i++; + return i == bfs.size(); + } +}; diff --git a/check_existence_edge.c b/check_existence_edge.c new file mode 100644 index 0000000..2a70cc4 --- /dev/null +++ b/check_existence_edge.c @@ -0,0 +1,66 @@ +// 1697. Checking Existence of Edge Length Limited Paths +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * an undirected graph of 'n' nodes is defined by 'edge_list', + * where 'edge_list[i] = [ui, vi, disi]' denotes an edge between + * nodes 'ui' and 'vi' with distance 'disi'. note that there may + * be multiple edges between two nodes. given an array 'queries', + * where 'queries[j] = [pj, qj, limitj]', your task is to determine + * for each 'queries[j]' whthere there is a path between 'pj' and + * 'qj' such that each edge on the path has a distance strictly less + * than 'limitj'. return boolean array where 'ans.length == queries.len' + * and the j'th value of 'ans' is true if there is a path for + * 'queries[j]' is true, and false otherwise + */ + +int *root, **qcopy; + +int find(int x) { + if (x == root[x]) + return x; + else + return root[x] = find(root[x]); +} + +int cmp(void const *a, void const *b) { + return (*(int **)a)[2] - (*(int **)b)[2]; +} + +int cmp2(void const *a, void const *b) { + return qcopy[*(int *)a][2] - qcopy[*(int *)b][2]; +} + +bool *distanceLimitedPathsExist(int n, int **edge_list, int edge_list_size, + int *edge_list_col_size, int **queries, + int queries_size, int *queries_col_size, + int *return_size) { + *return_size = queries_size; + int i = 0; + root = (int *)malloc(sizeof(int) * n); + for (i = 0; i < n; i++) + root[i] = i; + bool *ans = (bool *)malloc(sizeof(bool) * queries_size); + int idx[queries_size]; + for (i = 0; i < queries_size; ++i) + idx[i] = i; + qcopy = queries; + qsort(idx, queries_size, sizeof(int), cmp2); + qsort(edge_list, edge_list_size, sizeof(int *), cmp); + int j = 0; + for (i = 0; i < queries_size; ++i) { + int curr = idx[i], len = queries[curr][2]; + while (j < edge_list_size && edge_list[j][2] < len) { + int a = find(edge_list[j][0]), b = find(edge_list[j][1]); + root[b] = a; + j++; + } + if (find(queries[curr][0]) == find(queries[curr][1])) + ans[curr] = 1; + else + ans[curr] = 0; + } + return ans; +} diff --git a/check_existence_edge.cpp b/check_existence_edge.cpp new file mode 100644 index 0000000..2ad7150 --- /dev/null +++ b/check_existence_edge.cpp @@ -0,0 +1,68 @@ +// 1697. Checking Existence of Edge Length Limited Paths +#include "leetcode.h" + +/* + * an undirected graph of 'n' nodes is defined by 'edge_list', + * where 'edge_list[i] = [ui, vi, disi]' denotes an edge between + * nodes 'ui' and 'vi' with distance 'disi'. note that there may + * be multiple edges between two nodes. given an array 'queries', + * where 'queries[j] = [pj, qj, limitj]', your task is to determine + * for each 'queries[j]' whthere there is a path between 'pj' and + * 'qj' such that each edge on the path has a distance strictly less + * than 'limitj'. return boolean array where 'ans.length == queries.len' + * and the j'th value of 'ans' is true if there is a path for + * 'queries[j]' is true, and false otherwise + */ + +class UnionFind { + vector<int> parent; + +public: + UnionFind(int n) : parent(n) { iota(begin(parent), end(parent), 0); } + void connect(int a, int b) { + int x = find(a), y = find(b); + if (x == y) + return; + parent[x] = y; + } + bool connected(int i, int j) { return find(i) == find(j); } + int find(int a) { return parent[a] == a ? a : (parent[a] = find(parent[a])); } +}; + +class Solution { +public: + vector<bool> distanceLimitedPathsExist(int n, vvd(int) & edge_list, + vvd(int) & queries) { + vector<bool> ans(queries.size()); + for (int i = 0; i < queries.size(); ++i) + queries[i].push_back(i); + sort(begin(queries), end(queries), + [&](auto &a, auto &b) { return a[2] < b[2]; }); + sort(begin(edge_list), end(edge_list), + [&](auto &a, auto &b) { return a[2] < b[2]; }); + UnionFind uf(n); + int i = 0; + for (auto &q : queries) { + int u = q[0], v = q[1], limit = q[2], qid = q[3]; + for (; i < edge_list.size() && edge_list[i][2] < limit; ++i) + uf.connect(edge_list[i][0], edge_list[i][1]); + ans[qid] = uf.connected(u, v); + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) el1 = {{0, 1, 2}, {1, 2, 4}, {2, 0, 8}, {1, 0, 6}}; + vvd(int) q1 = {{0, 1, 2}, {0, 2, 5}}; + vector<bool> dlpe1 = obj.distanceLimitedPathsExist(3, el1, q1); + vvd(int) el2 = {{0, 1, 10}, {1, 2, 5}, {2, 3, 9}, {3, 4, 13}}; + vvd(int) q2 = {{0, 4, 14}, {1, 4, 13}}; + vector<bool> dlpe2 = obj.distanceLimitedPathsExist(5, el2, q2); + for (int i = 0; i < 2; i++) + cout << dlpe1[i] << ' '; // expect: 0 1 + printf("\n"); + for (int i = 0; i < 2; i++) + cout << dlpe2[i] << ' '; // expect: 1 0 +} diff --git a/check_good_array.c b/check_good_array.c new file mode 100644 index 0000000..d031096 --- /dev/null +++ b/check_good_array.c @@ -0,0 +1,33 @@ +// 1250. Check If It Is a Good Array +#include <stdbool.h> +#include <stdio.h> + +/* + * given an array 'nums' of positive integers. your task is to select some + * subset of 'nums', multiply each element by an integer and add all these + * numbers. the array is said to be good if you can obtain a sum of 1 from the + * array by any possible subset and multiplicand. return 'true' if the array is + * good, otherwise return 'false' + */ + +int gcd(int a, int b) { + if (!a) + return b; + return gcd(b % a, a); +} + +bool isGoodArray(int *nums, int nums_size) { + if (nums_size == 1) + return (nums[0] == 1); + int flag = gcd(nums[0], nums[1]); + for (int i = 2; i < nums_size; i++) + flag = gcd(flag, nums[i]); + return flag == 1; +} + +int main() { + int n1[] = {12, 5, 7, 23}, n2[] = {29, 6, 10}, n3[] = {3, 6}; + printf("%d\n", isGoodArray(n1, 4)); // expect: 1 + printf("%d\n", isGoodArray(n2, 3)); // expect: 1 + printf("%d\n", isGoodArray(n3, 2)); // expect: 0 +} diff --git a/check_good_array.py b/check_good_array.py new file mode 100644 index 0000000..b223b12 --- /dev/null +++ b/check_good_array.py @@ -0,0 +1,25 @@ +# 1250. Check If It Is a Good Array + +""" +given an array 'nums' of positive integers. your task is to select some +subset of 'nums', multiply each element by an integer and add all these +numbers. the array is said to be good if you can obtain a sum of 1 from the +array by any possible subset and multiplicand. return 'true' if the array is +good, otherwise return 'false' +""" + + +class Solution(object): + def isGoodArray(self, nums): + gcd = nums[0] + for i in nums: + while i: + gcd, i = i, gcd % i + return gcd == 1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.isGoodArray([12, 5, 7, 23])) # expect: True + print(obj.isGoodArray([29, 6, 10])) # expect: True + print(obj.isGoodArray([3, 6])) # expect: False diff --git a/check_knight_config.c b/check_knight_config.c new file mode 100644 index 0000000..6dde08e --- /dev/null +++ b/check_knight_config.c @@ -0,0 +1,55 @@ +// 2596. Check Knight Tour Configuration +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * there is a knight on an 'n * n' chessboard. in a valid config + * the knight starts at the topl-left cell of the board and visits + * every cell on the board exactly once. you are given an 'n * n' + * integer matrix 'grid' consisting of distinct integers from the + * range '[0, n * n - 1]' where 'grid[row][col]' indicates that + * the cell '(row, col)' is the 'grid[row][col]'th cell that the + * knight visited. the moves are 0-indexed. return true if grid + * represents a valid configuration of the knight's movements or + * false otherwise. note that a valid knight move consists of + * moving two squares vertically and one square horizontally, + * or two squares horizontally and one square vertically. the + * figure illustrates all possible 8 moves of a knight from cell + */ + +void check_path(int **grid, int r_len, int c_len, int r, int c, int next, + int *check_cnt) { + if (r < 0 || c < 0 || r >= r_len || c >= c_len || grid[r][c] == -1 || + grid[r][c] != next) + return; + grid[r][c] = -1; + (*check_cnt)++; + check_path(grid, r_len, c_len, r + 2, c + 1, next + 1, check_cnt); + check_path(grid, r_len, c_len, r + 1, c + 2, next + 1, check_cnt); + check_path(grid, r_len, c_len, r - 1, c + 2, next + 1, check_cnt); + check_path(grid, r_len, c_len, r - 2, c + 1, next + 1, check_cnt); + check_path(grid, r_len, c_len, r - 2, c - 1, next + 1, check_cnt); + check_path(grid, r_len, c_len, r - 1, c - 2, next + 1, check_cnt); + check_path(grid, r_len, c_len, r + 1, c - 2, next + 1, check_cnt); + check_path(grid, r_len, c_len, r + 2, c - 1, next + 1, check_cnt); +} + +bool checkValidGrid(int **grid, int grid_size, int *grid_col_size) { + int check_cnt = 0; + check_path(grid, grid_size, *grid_col_size, 0, 0, 0, &check_cnt); + return check_cnt != grid_size * *grid_col_size ? false : true; +} + +int main() { + int g1[5][5] = {{0, 11, 16, 5, 20}, + {17, 4, 19, 10, 15}, + {12, 1, 8, 21, 6}, + {3, 18, 23, 14, 9}, + {24, 13, 2, 7, 22}}; + int g2[3][3] = {{0, 3, 6}, {5, 8, 1}, {2, 7, 4}}; + int gs1 = 5, gs2 = 3; + int gcs1[] = {5, 5, 5, 5, 5}, gcs2[] = {3, 3, 3}; + printf("%d\n", checkValidGrid(g1, gs1, gcs1)); // expect: 1 + printf("%d\n", checkValidGrid(g2, gs2, gcs2)); // expect: 0 +} diff --git a/check_knight_config.cpp b/check_knight_config.cpp new file mode 100644 index 0000000..0fb83c1 --- /dev/null +++ b/check_knight_config.cpp @@ -0,0 +1,59 @@ +// 2596. Check Knight Tour Configuration +#include "leetcode.h" + +/* + * there is a knight on an 'n * n' chessboard. in a valid config + * the knight starts at the topl-left cell of the board and visits + * every cell on the board exactly once. you are given an 'n * n' + * integer matrix 'grid' consisting of distinct integers from the + * range '[0, n * n - 1]' where 'grid[row][col]' indicates that + * the cell '(row, col)' is the 'grid[row][col]'th cell that the + * knight visited. the moves are 0-indexed. return true if grid + * represents a valid configuration of the knight's movements or + * false otherwise. note that a valid knight move consists of + * moving two squares vertically and one square horizontally, + * or two squares horizontally and one square vertically. the + * figure illustrates all possible 8 moves of a knight from cell + */ + +class Solution { +public: + bool checkValidGrid(vvd(int) & grid) { + int dir[8][2] = {{1, -2}, {2, -1}, {2, 1}, {1, 2}, + {-1, 2}, {-2, 1}, {-2, -1}, {-1, -2}}; + int cnt = 0, max_cnt = grid.size() * grid.size() - 1; + int x = 0, y = 0, i, j; + if (grid[x][y] != cnt) + return false; + while (cnt < max_cnt) { + cnt++; + int flag = 1; + for (auto d : dir) { + i = x + d[0]; + j = y + d[1]; + if (i >= 0 && j >= 0 && i < grid.size() && j < grid.size() && + grid[i][j] == cnt) { + x = i; + y = j; + flag = 0; + break; + } + } + if (flag) + return false; + } + return true; + } +}; + +int main() { + Solution obj; + vvd(int) g1 = {{0, 11, 16, 5, 20}, + {17, 4, 19, 10, 15}, + {12, 1, 8, 21, 6}, + {3, 18, 23, 14, 9}, + {24, 13, 2, 7, 22}}; + vvd(int) g2 = {{0, 3, 6}, {5, 8, 1}, {2, 7, 4}}; + printf("%d\n", obj.checkValidGrid(g1)); // expect: 1 + printf("%d\n", obj.checkValidGrid(g2)); // expect: 0 +} diff --git a/check_pangram_sentence.cpp b/check_pangram_sentence.cpp new file mode 100644 index 0000000..67f1af2 --- /dev/null +++ b/check_pangram_sentence.cpp @@ -0,0 +1,19 @@ +#include "leetcode.h" + +class Solution { +public: + bool checkIfPangram(string sentence) { + set<int> s; + for (auto &i : sentence) + s.insert(i); + return s.size() == 26; + } +}; + +int main() { + Solution obj; + if (obj.checkIfPangram("thequickbrownfoxjumpsoverthelazydog")) + cout << "true"; + else + cout << "false"; +} diff --git a/check_pangram_sentence.rs b/check_pangram_sentence.rs new file mode 100644 index 0000000..0f69c31 --- /dev/null +++ b/check_pangram_sentence.rs @@ -0,0 +1,21 @@ +struct Solution; + +impl Solution { + pub fn check_if_pangram(sentence: String) -> bool { + let mut bit_mask: u32 = 0; + let mut count = 0; + for c in sentence.chars() { + let idx = c as usize - 'a' as usize; + if bit_mask & (1 << idx) == 0 { + count += 1; + } + bit_mask |= 1 << idx; + } + count == 26 + } +} + +fn main() { + let sentence = String::from("thequickbrownfoxjumpsoverthelazydog"); + print!("{}", Solution::check_if_pangram(sentence)); +} diff --git a/check_straight_line.c b/check_straight_line.c new file mode 100644 index 0000000..02d3674 --- /dev/null +++ b/check_straight_line.c @@ -0,0 +1,49 @@ +// 1232. Check If It Is a Straight Line +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array 'coordinates, coordinates[i] = [x, y]' where '[x, y]' + * represents the coordinate of a point. check if these points make a straight + * line in the xy plane + */ + +bool checkStraightLine(int **coordinates, int coordinates_size, + int *coordinates_col_size) { + int n = coordinates_size, *x_coords = (int *)malloc(n * sizeof(int)), + unique_x = 1, unique_slope = 1; + float *slopes = (float *)malloc((n - 1) * sizeof(float)); + for (int i = 0; i < n; i++) + x_coords[i] = coordinates[i][0]; + for (int i = 1; i < n; i++) + if (x_coords[i] != x_coords[0]) { + unique_x = 0; + break; + } + if (unique_x) { + free(x_coords); + free(slopes); + return true; + } + for (int i = 1; i < n; i++) + slopes[i - 1] = (float)(coordinates[i][1] - coordinates[0][1]) / + (coordinates[i][0] - coordinates[0][0]); + for (int i = 1; i < n - 1; i++) + if (slopes[i] != slopes[0]) { + unique_slope = 0; + break; + } + free(x_coords); + free(slopes); + return unique_slope; +} + +int main() { + int c1[6][2] = {{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7}}, cs1 = 6, + *ccs1; + int c2[6][2] = {{1, 1}, {2, 2}, {3, 4}, {4, 5}, {5, 6}, {7, 7}}, cs2 = 6, + *ccs2; + printf("%d\n", checkStraightLine(c1, cs2, ccs1)); // expect: 1 + printf("%d\n", checkStraightLine(c2, cs2, ccs2)); // expect: 0 +} diff --git a/check_straight_line.cpp b/check_straight_line.cpp new file mode 100644 index 0000000..1319b73 --- /dev/null +++ b/check_straight_line.cpp @@ -0,0 +1,35 @@ +// 1232. Check If It Is a Straight Line +#include "leetcode.h" + +/* + * given an array 'coordinates, coordinates[i] = [x, y]' where '[x, y]' + * represents the coordinate of a point. check if these points make a straight + * line in the xy plane + */ + +class Solution { +public: + bool checkStraightLine(vvd(int) & coordinates) { + int n = coordinates.size(); + if (n == 1) + return false; + if (n == 2) + return true; + int x0 = coordinates[0][0], y0 = coordinates[0][1]; + int dx = coordinates[1][0] - x0, dy = coordinates[1][1] - y0; + for (int i = 1; i < n; i++) { + int x = coordinates[i][0], y = coordinates[i][1]; + if (dx * (y - y0) != dy * (x - x0)) + return false; + } + return true; + } +}; + +int main() { + Solution obj; + vvd(int) c1 = {{1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 6}, {6, 7}}; + vvd(int) c2 = {{1, 1}, {2, 2}, {3, 4}, {4, 5}, {5, 6}, {7, 7}}; + printf("%d\n", obj.checkStraightLine(c1)); // expect: 1 + printf("%d\n", obj.checkStraightLine(c2)); // expect: 0 +} diff --git a/check_string_cont_k.cpp b/check_string_cont_k.cpp new file mode 100644 index 0000000..e041052 --- /dev/null +++ b/check_string_cont_k.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + bool hasAllCodes(string s, int k) { + int bitLimit = 1 << k, n = 0; + bool combos[bitLimit]; + for (int i = 0; i < bitLimit; i++) + combos[i] = true; + for (int i = 0, limit = k - 1; i < limit; i++) + n = (n << 1) + (s[i] == '1'); + for (int i = k - 1, limit = s.size(), total = bitLimit; i < limit; i++) { + n = (n << 1) + (s[i] == '1'); + if (n >= bitLimit) + n -= bitLimit; + if (combos[n]) + combos[n] = false, total--; + if (!total) + return true; + } + return false; + } +}; + +int main() { + Solution obj; + string s = "00110110"; + int k = 2; + cout << obj.hasAllCodes(s, k); +} diff --git a/check_two_str_arr.cpp b/check_two_str_arr.cpp new file mode 100644 index 0000000..5e4d8a7 --- /dev/null +++ b/check_two_str_arr.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + bool arrayStringsAreEqual(vector<string> &word1, vector<string> &word2) { + int i = 0, j = 0, m = 0, n = 0; + while (i < word1.size() && j < word2.size()) { + if (word1[i][m++] != word2[j][n++]) + return false; + if (m >= word1[i].size()) + i++, m = 0; + if (n >= word2[j].size()) + j++, n = 0; + } + return i == word1.size() && j == word2.size(); + } +}; + +int main() { + Solution obj; + vector<string> word1 = {"ab", "c"}, word2 = {"a", "bc"}; + if (obj.arrayStringsAreEqual(word1, word2)) + cout << "true"; + else + cout << "false"; +} diff --git a/check_two_str_arr.rs b/check_two_str_arr.rs new file mode 100644 index 0000000..7fd2a2d --- /dev/null +++ b/check_two_str_arr.rs @@ -0,0 +1,19 @@ +struct Solution; + +impl Solution { + pub fn array_strings_are_equal(word1: Vec<String>, word2: Vec<String>) -> bool { + let ans: bool; + if word1.join("") == word2.join("") { + ans = true; + } else { + ans = false; + } + return ans; + } +} + +fn main() { + let word1 = vec!["ab".to_string(), "c".to_string()]; + let word2 = vec!["a".to_string(), "bc".to_string()]; + print!("{}", Solution::array_strings_are_equal(word1, word2)); +} diff --git a/check_valid_partition.c b/check_valid_partition.c new file mode 100644 index 0000000..c58c3ed --- /dev/null +++ b/check_valid_partition.c @@ -0,0 +1,61 @@ +// 2369. Check if There is a Valid Partition For The Array +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given a 0-indexed integer array 'nums', you have to partition the array into + * one or more contiguous subarrays. we call a partition of the array valid if + * each of the obtained subarrays satisfies one of the following conditions + * - the subarray consists of exactly 2 equal elements. for example, the + * subarray '[2,2]' is good. + * - the subarray consists of exactly 3 equal elements. for example, the + * subarray '[4,4,4]' is good. + * - the subarray consists of exactly 3 consecutive increasing elements, that + * is, the difference between adjacent elements is 1. for example, the subarray + * '[3,4,5]' is good, but the subarray '[1,3,5]' is not. return true if the + * array has at least one valid partition. otherwise, return false. + */ + +bool validPartition(int *nums, int nums_size) { + int n = nums_size, *dp = calloc(n + 1, sizeof(bool)); + dp[0] = true; + if (nums[0] == nums[1]) + dp[2] = true; + int consecutive_false = 0; + for (int i = 3; i <= n; i++) { + if (nums[i - 1] == nums[i - 2]) { + dp[i] |= dp[i - 2]; + if (dp[i]) { + consecutive_false = 0; + continue; + } + if (nums[i - 2] == nums[i - 3]) { + dp[i] |= dp[i - 3]; + if (dp[i]) { + consecutive_false = 0; + continue; + } + } + } else { + if ((nums[i - 1] == nums[i - 2] + 1) && + (nums[i - 2] == nums[i - 3] + 1)) { + dp[i] |= dp[i - 3]; + if (dp[i]) { + consecutive_false = 0; + continue; + } + } + } + consecutive_false++; + if (consecutive_false == 3) + break; + } + return dp[n]; +} + +int main() { + int n1[] = {4, 4, 4, 5, 6}, n2[] = {1, 1, 1, 2}; + printf("%d\n", validPartition(n1, 5)); // expect: 1 + printf("%d\n", validPartition(n2, 4)); // expect: 0 +} diff --git a/check_valid_partition.cpp b/check_valid_partition.cpp new file mode 100644 index 0000000..3f4cd76 --- /dev/null +++ b/check_valid_partition.cpp @@ -0,0 +1,50 @@ +// 2369. Check if There is a Valid Partition For The Array +#include "leetcode.h" + +/* + * given a 0-indexed integer array 'nums', you have to partition the array into + * one or more contiguous subarrays. we call a partition of the array valid if + * each of the obtained subarrays satisfies one of the following conditions + * - the subarray consists of exactly 2 equal elements. for example, the + * subarray '[2,2]' is good. + * - the subarray consists of exactly 3 equal elements. for example, the + * subarray '[4,4,4]' is good. + * - the subarray consists of exactly 3 consecutive increasing elements, that + * is, the difference between adjacent elements is 1. for example, the subarray + * '[3,4,5]' is good, but the subarray '[1,3,5]' is not. return true if the + * array has at least one valid partition. otherwise, return false. + */ + +class Solution { + bool solve(vector<int> &nums, int i, vector<int> &dp) { + if (nums.size() == i) + return true; + if (dp[i] != -1) + return dp[i]; + if (i + 1 < nums.size() && nums[i] == nums[i + 1]) { + if (solve(nums, i + 2, dp)) + return true; + if (i + 2 < nums.size() && nums[i] == nums[i + 2]) + if (solve(nums, i + 3, dp)) + return true; + } + if (i + 2 < nums.size() && nums[i] == nums[i + 1] - 1 && + nums[i] == nums[i + 2] - 2) + if (solve(nums, i + 3, dp)) + return true; + return !dp[i]; + } + +public: + bool validPartition(vector<int> &nums) { + vector<int> dp(nums.size(), -1); + return solve(nums, 0, dp); + } +}; + +int main() { + Solution obj; + vector<int> n1 = {4, 4, 4, 5, 6}, n2 = {1, 1, 1, 2}; + printf("%d\n", obj.validPartition(n1)); // expect: 1 + printf("%d\n", obj.validPartition(n2)); // expect: 0 +} diff --git a/cherry_pickup2.c b/cherry_pickup2.c new file mode 100644 index 0000000..77a9d09 --- /dev/null +++ b/cherry_pickup2.c @@ -0,0 +1,40 @@ +// 1463. Cherry Pickup II +#include "leetcode.h" + +/* + * given a row * cols matrix grid representing a field of cherries where + * 'grid[i][j]' represents the number of cherries that you can collect from the + * '(i, j)' cell. you have two robots that can collect cherries for you located + * at corner (0, 0) and (cols - 1). return the maximum number of cherries + * collection using both robots by following the rulew below. + */ + +int dp[70][70][70]; + +int dfs(int **grid, int size, int col_size, int i, int l, int r) { + if (i >= size || l == r) + return 0; + if (l < 0 || l >= col_size || r < 0 || r >= col_size) + return 0; + if (dp[i][l][r] >= 0) + return dp[i][l][r]; + int res = 0, dir[3] = {-1, 0, 1}; + for (int x = 0; x < 3; x++) + for (int y = 0; y < 3; y++) { + int tmp = dfs(grid, size, col_size, i + 1, l + dir[x], r + dir[y]); + res = res > grid[i][l] + grid[i][r] + tmp ? res + : grid[i][l] + grid[i][r] + tmp; + } + return dp[i][l][r] = res; +} + +int cherryPickup(int **grid, int grid_size, int *grid_col_size) { + memset(dp, -1, sizeof(dp)); + return dfs(grid, grid_size, *grid_col_size, 0, 0, *grid_col_size - 1); +} + +int main() { + int grid[4][3] = {{3, 1, 1}, {2, 5, 1}, {1, 5, 5}, {2, 1, 1}}; + int grid_col_size[] = {}; + printf("%d\n", cherryPickup((int **)grid, 4, grid_col_size)); // expect: 24 +} diff --git a/cherry_pickup2.py b/cherry_pickup2.py new file mode 100644 index 0000000..10995e1 --- /dev/null +++ b/cherry_pickup2.py @@ -0,0 +1,48 @@ +# 1463. Cherry Pickup II + +""" +given a row cols matrix grid representing a field of cherries where +'grid[i][j]' represents the number of cherries that you can collect from the +'(i, j)' cell. you have two robots that can collect cherries for you located +at corner (0, 0) and (cols - 1). return the maximum number of cherries +collection using both robots by following the rulew below. +""" + + +class Solution(object): + def cherryPickup(self, grid): + """ + :type grid: List[List[int]] + :rtype: int + """ + m, n = len(grid), len(grid[0]) + + #@lru_cache(None) + def dfs(r, c1, c2): + if r == m: + return 0 + cherries = grid[r][c1] if c1 == c2 else grid[r][c1] + grid[r][c2] + ans = 0 + for nc1 in range(c1 - 1, c1 + 2): + for nc2 in range(c2 - 1, c2 + 2): + if 0 <= nc1 < n and 0 <= nc2 < n: + ans = max(ans, dfs(r + 1, nc1, nc2)) + return ans + cherries + + return dfs(0, 0, n - 1) + + +if __name__ == "__main__": + obj = Solution() + print(obj.cherryPickup(grid=[[3, 1, 1], [2, 5, 1], [1, 5, 5], [2, 1, 1]])) + print( + obj.cherryPickup( + grid=[ + [1, 0, 0, 0, 0, 0, 1], + [2, 0, 0, 0, 0, 3, 0], + [2, 0, 9, 0, 0, 0, 0], + [0, 3, 0, 5, 4, 0, 0], + [1, 0, 2, 3, 0, 0, 6], + ] + ) + ) diff --git a/cinema_seat_allocation.c b/cinema_seat_allocation.c new file mode 100644 index 0000000..30d2195 --- /dev/null +++ b/cinema_seat_allocation.c @@ -0,0 +1,66 @@ +// 1386. Cinema Seat Allocation +#include <stdio.h> +#include <stdlib.h> + +/* + * a cinema has 'n' rows of seats, numbered from 1 to 'n' and there + * are ten seats in each row, labelled from 1 to 10 as shown in + * the figure above. given the array 'reserved_seats' containing + * the number of seats already reserved, for example 'reserved_seats[i] + * = [3,8]' means the seat located in row 3 and labelled with 8 + * is already reserved. return the maximum number of four-person + * groups you can assign on the cinema seats. a four-person group + * occupies four adjacent seats in one single row. seats across + * an aisle are not considered to be adjacent, but there is an + * exceptional case on which an aisle split a four-person group + * in that case the aisle split a four-person group in the middle + * which means to have two people on each side. + */ + +int cmp(const void *a, const void *b) { + int *new_a = *(int **)a, *new_b = *(int **)b; + if (new_a[0] == new_b[0]) + return new_a[1] - new_b[1]; + return new_a[0] - new_b[0]; +} + +int maxNumberOfFamilies(int n, int **reserved_seats, int reserved_seats_size, + int *reserved_seats_col_size) { + qsort(reserved_seats, reserved_seats_size, sizeof(int *), cmp); + int hash[256] = {}, ans = 2 * n; + hash[0] = 2; + for (int i = 1; i < 256; i++) { + int val = i; + if (!(val & 0x0F)) + hash[i] = 1; + else if (!(val & 0xF0)) + hash[i] = 1; + else if (!(val & 0x3C)) + hash[i] = 1; + } + int val = 0, col = reserved_seats[0][1]; + if (col != 1 && col != 10) + val |= 1 << (col - 2); + for (int i = 1; i < reserved_seats_size; i++) { + col = reserved_seats[i][1]; + if (reserved_seats[i][0] == reserved_seats[i - 1][0]) { + if (col != 1 && col != 10) + val |= 1 << (col - 2); + } else { + ans -= 2 - hash[val]; + val = 0; + if (col != 1 && col != 10) + val |= 1 << (col - 2); + } + } + ans -= 2 - hash[val]; + return ans; +} + +int main() { + int n1 = 2, rs1[6][2] = {{1, 2}, {1, 3}, {1, 8}, {2, 6}, {3, 1}, {3, 10}}, + rss1 = 6, rscs1[] = {}; + int n2 = 4, rs2[3][2] = {{2, 1}, {1, 8}, {2, 6}}, rss2 = 3, rscs2[] = {}; + printf("%d\n", maxNumberOfFamilies(n1, rs1, rss1, rscs1)); + printf("%d\n", maxNumberOfFamilies(n2, rs2, rss2, rscs2)); +} diff --git a/climbing_stairs.c b/climbing_stairs.c new file mode 100644 index 0000000..51ebdbb --- /dev/null +++ b/climbing_stairs.c @@ -0,0 +1,36 @@ +// 70. Climbing Stairs +#include "leetcode.h" + +/* + * you are climbinga staircase. it takes 'n' steps to reach the top. each time + * you can either climb one or two steps. in how many distinct ways can you + * climb to the top? + */ + +double combination(int m, int n) { + if (!n || m == n) + return 1; + double res = 1; + for (int i = m; i > m - n; i--) + res *= i; + for (int i = n; i >= 1; i--) + res /= i; + return res; +} + +int climbingStairs(int n) { + int one_step, two_step, total_step; + double method = 0; + for (int i = 0; i <= floor((double)n / 2); i++) { + two_step = i; + one_step = n - 2 * i; + total_step = one_step + two_step; + method += combination(total_step, one_step); + } + return (int)method; +} + +int main() { + printf("%d\n", climbingStairs(2)); // expect: 2 + printf("%d\n", climbingStairs(3)); // expect: 3 +} diff --git a/climbing_stairs.cpp b/climbing_stairs.cpp new file mode 100644 index 0000000..afc3d7e --- /dev/null +++ b/climbing_stairs.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + int climbStairs(int n) { + /* + * base case + * because if 0 steps -> 0 ways, + * 1 step -> 1 way, & 2 step -> 2 ways + */ + if (n <= 2) + return n; + /* + * last step was either: + * 1 step (oneStep) or 2 steps (twoStep) + * so simply add the two values (fibonacci sequence) + */ + int oneStep = 1, twoStep = 2, ans; + for (int i = 3; i <= n; i++) { // 0-2 steps already determined + ans = oneStep + twoStep; + oneStep = twoStep; + twoStep = ans; + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.climbStairs(4); +} diff --git a/climbing_stairs.py b/climbing_stairs.py new file mode 100644 index 0000000..6c1f357 --- /dev/null +++ b/climbing_stairs.py @@ -0,0 +1,28 @@ +# 70. Climbing Stairs + +""" +you are climbinga staircase. it takes 'n' steps to reach the top. each time +you can either climb one or two steps. in how many distinct ways can you +climb to the top? +""" + + +class Solution(object): + def climbStairs(self, n): + """ + :type n: int + :rtype: int + """ + ways = 1 + for i in range(1, (n // 2) + 1): + product = 1 + for j in range(i, 2 * i): + product *= (n - j) / (j - i + 1) + ways += product + return int(ways) + + +if __name__ == "__main__": + obj = Solution() + print(obj.climbStairs(2)) + print(obj.climbStairs(3)) diff --git a/climbing_stairs.rs b/climbing_stairs.rs new file mode 100644 index 0000000..e3bf42d --- /dev/null +++ b/climbing_stairs.rs @@ -0,0 +1,16 @@ +struct Solution; + +impl Solution { + pub fn climb_stairs(n: i32) -> i32 { + let (mut ans, mut i) = ([2, 1], 3); + while i <= n as usize { + ans[i & 0b01] = ans[0] + ans[1]; + i += 1; + } + ans[n as usize & 0b01] + } +} + +fn main() { + print!("{}", Solution::climb_stairs(2)); +} diff --git a/clone_graph.c b/clone_graph.c new file mode 100644 index 0000000..b47c9e8 --- /dev/null +++ b/clone_graph.c @@ -0,0 +1,35 @@ +// 133. Clone Graph +#include <stdbool.h> +#include <stdlib.h> + +// given reference of a node in a connected undirected graph. return a deep copy +// (clone) of the graph. each node in the graph contains a value (int) and a +// list (list[node]). + +struct Node { + int val; + int numNeighbors; + struct Node **neighbors; +}; + +struct Node *process(struct Node *s, bool *hash, struct Node **data) { + if (hash[s->val]) + return data[s->val]; + struct Node *root = malloc(sizeof(struct Node)); + root->val = s->val; + hash[s->val] = true; + data[s->val] = root; + root->numNeighbors = s->numNeighbors; + root->neighbors = malloc(s->numNeighbors * sizeof(struct Node *)); + for (int i = 0; i < s->numNeighbors; i++) + root->neighbors[i] = process(s->neighbors[i], hash, data); + return root; +} + +struct Node *cloneGraph(struct Node *s) { + if (s == NULL) + return NULL; + bool *hash = calloc(101, sizeof(int)); + struct Node **data = malloc(101 * sizeof(struct Node *)); + return process(s, hash, data); +} diff --git a/clone_graph.cpp b/clone_graph.cpp new file mode 100644 index 0000000..1564856 --- /dev/null +++ b/clone_graph.cpp @@ -0,0 +1,55 @@ +// 133. Clone Graph +#include <cstddef> +#include <unordered_map> +#include <vector> +using namespace std; + +// given reference of a node in a connected undirected graph. return a deep copy +// (clone) of the graph. each node in the graph contains a value (int) and a +// list (list[node]). + +class Node { +public: + int val; + vector<Node *> neighbors; + Node() { + val = 0; + neighbors = vector<Node *>(); + } + Node(int _val) { + val = _val; + neighbors = vector<Node *>(); + } + Node(int _val, vector<Node *> _neighbors) { + val = _val; + neighbors = _neighbors; + } +}; + +class Solution { + Node *dfs(Node *curr, unordered_map<Node *, Node *> &um) { + vector<Node *> neighbour; + Node *clone = new Node(curr->val); + um[curr] = clone; + for (auto i : curr->neighbors) { + if (um.find(i) != um.end()) + neighbour.push_back(um[i]); + else + neighbour.push_back(dfs(i, um)); + } + clone->neighbors = neighbour; + return clone; + } + +public: + Node *cloneGraph(Node *node) { + unordered_map<Node *, Node *> um; + if (node == NULL) + return NULL; + if (!node->neighbors.size()) { + Node *clone = new Node(node->val); + return clone; + } + return dfs(node, um); + } +}; diff --git a/closest_node_2_nodes.c b/closest_node_2_nodes.c new file mode 100644 index 0000000..85801e9 --- /dev/null +++ b/closest_node_2_nodes.c @@ -0,0 +1,50 @@ +// 2359. Find Closest Node to Given Two Nodes +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int closestMeetingNode(int *edges, int edgesSize, int node1, int node2) { + int n = edgesSize, *path1 = malloc(n * sizeof(int)), + *path2 = malloc(n * sizeof(int)); + memset(path1, -1, n * sizeof(int)); + memset(path2, -1, n * sizeof(int)); + int p = node1, step = 0; + while (1) { + path1[p] = step; + step++; + p = edges[p]; + if (p == -1) + break; + if (path1[p] != -1) + break; + } + p = node2; + step = 0; + while (1) { + path2[p] = step; + step++; + p = edges[p]; + if (p == -1) + break; + if (path2[p] != -1) + break; + } + int min = INT_MAX, ans = -1; + for (int i = 0; i < n; i++) + if (path1[i] != -1 && path2[i] != -1) + if (fmax(path1[i], path2[i]) < min) { + min = fmax(path1[i], path2[i]); + ans = i; + } + free(path1); + free(path2); + return ans; +} + +int main() { + int edges1[] = {2, 2, 3, -1}, edges2[] = {1, 2, -1}; + printf("%d\n", closestMeetingNode(edges1, 3, 0, 2)); // expect: 2 + printf("%d\n", closestMeetingNode(edges2, 3, 0, 2)); // expect: 2 +} diff --git a/closest_node_2_nodes.cpp b/closest_node_2_nodes.cpp new file mode 100644 index 0000000..7b85f22 --- /dev/null +++ b/closest_node_2_nodes.cpp @@ -0,0 +1,55 @@ +#include "leetcode.h" + +class Solution { +public: + int closestMeetingNode(vector<int> &edges, int node1, int node2) { + pair<int, int> p1 = dfs(edges, node1, node2); + pair<int, int> p2 = dfs(edges, node2, node1); + if (p1.second != -1 && p1.first < p2.first) + return p1.second; + else if (p2.second != -1 && p2.first < p1.first) + return p2.second; + else if (p1.first == p2.first) { + if (p1.second < p2.second) + return p1.second; + else + return p2.second; + } + return -1; + } + +private: + pair<int, int> dfs(vector<int> &edges, int node1, int node2) { + unordered_map<int, int> um; + int n = edges.size(); + vector<int> vis1(n + 2, 0), vis2(n + 2, 0); + um[node1] = 1; + int len = 0; + while (edges[node1] != -1 && vis1[node1] != 1) { + vis1[node1] = 1; + node1 = edges[node1]; + um[node1] = len++; + } + pair<int, int> pp = make_pair(INT_MAX, -1); + if (um.find(node2) != um.end()) { + pp = make_pair(um[node2], node2); + return pp; + } + while (edges[node2] != -1 && vis2[node2] != 1) { + vis2[node2] = 1; + node2 = edges[node2]; + if (um.find(node2) != um.end()) { + pp = make_pair(um[node2], node2); + return pp; + } + } + return pp; + } +}; + +int main() { + Solution obj; + vector<int> edges1 = {2, 2, 3, -1}, edges2 = {1, 2, -1}; + cout << obj.closestMeetingNode(edges1, 0, 2) << endl; // expect: 2 + cout << obj.closestMeetingNode(edges2, 0, 2) << endl; // expect: 2 +} diff --git a/closest_node_2_nodes.rs b/closest_node_2_nodes.rs new file mode 100644 index 0000000..ea3ee86 --- /dev/null +++ b/closest_node_2_nodes.rs @@ -0,0 +1,45 @@ +struct Solution; + +impl Solution { + pub fn closest_meeting_node(edges: Vec<i32>, node1: i32, node2: i32) -> i32 { + let n = edges.len(); + let (mut d1, mut d2) = (vec![n; n], vec![n; n]); + d1[node1 as usize] = 0; + d2[node2 as usize] = 0; + let mut u = node1 as usize; + while edges[u] != -1 { + let v = edges[u] as usize; + if d1[v] < d1[u] { + break; + } + d1[v] = d1[u] + 1; + u = v; + } + u = node2 as usize; + while edges[u] != -1 { + let v = edges[u] as usize; + if d2[v] < d2[u] { + break; + } + d2[v] = d2[u] + 1; + u = v; + } + let (mut ans, mut mx) = (-1i32, n); + for i in 0..n { + let tmp = d1[i].max(d2[i]); + if tmp >= mx { + continue; + } + ans = i as i32; + mx = tmp; + } + ans + } +} + +fn main() { + let edges1 = vec![2,2,3,-1]; + let edges2 = vec![1,2,-1]; + println!("{}", Solution::closest_meeting_node(edges1, 0, 1)); //expect: 2 + println!("{}", Solution::closest_meeting_node(edges2, 0, 2)); //expect: 2 +} diff --git a/cnt_node_equal_subtree.c b/cnt_node_equal_subtree.c new file mode 100644 index 0000000..781bdcf --- /dev/null +++ b/cnt_node_equal_subtree.c @@ -0,0 +1,36 @@ +// 2265. Count Nodes Equal to Average of Subtree +#include "leetcode.h" + +/* + * given the root of a binary tree, return the number of nodes where the value + * of the node is equal to the average of the values in its subtree. note, the + * average of 'n' elements is the sum of the n elements divided by n and rounded + * down to the nearest integer. also, a subtree of root is a tree consisting of + * root and all of its descendants + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int cnt_subtree(struct TreeNode *root, int *res) { + if (!root) + return 0; + int left = cnt_subtree(root->left, res); + int rght = cnt_subtree(root->right, res); + int curr_cnt = left + rght + 1, curr_sum = root->val; + curr_sum += (root->left) ? root->left->val : 0; + curr_sum += (root->right) ? root->right->val : 0; + if (root->val == (curr_sum / curr_cnt)) + (*res)++; + root->val = curr_sum; + return curr_cnt; +} + +int averageOfSubtree(struct TreeNode *root) { + int ans = 0; + cnt_subtree(root, &ans); + return ans; +} diff --git a/cnt_node_equal_subtree.py b/cnt_node_equal_subtree.py new file mode 100644 index 0000000..70c6ab9 --- /dev/null +++ b/cnt_node_equal_subtree.py @@ -0,0 +1,42 @@ +# 2265. Count Nodes Equal to Average of Subtree + +""" +given the root of a binary tree, return the number of nodes where the value +of the node is equal to the average of the values in its subtree. note, the +average of 'n' elements is the sum of the n elements divided by n and rounded +down to the nearest integer. also, a subtree of root is a tree consisting of +root and all of its descendants +""" + + +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def averageOfSubtree(self, root): + ans = 0 + + def traverse(node): + nonlocal ans + if not node: + return 0, 0 + left_sum, left_count = traverse(node.left) + right_sum, right_count = traverse(node.right) + s = node.val + left_sum + right_sum + c = 1 + left_count + right_count + if s // c == node.val: + ans += 1 + return s, c + + traverse(root) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.averageOfSubtree(root=[4, 8, 5, 0, 1, null, 6])) + print(obj.averageOfSubtree(root=[1])) diff --git a/coin_change.cpp b/coin_change.cpp new file mode 100644 index 0000000..5d31f7a --- /dev/null +++ b/coin_change.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + int coinChange(vector<int> &coins, int amount) { + int m = amount + 1; + vector<int> dp(amount + 1, m); + dp[0] = 0; + for (int i = 1; i <= amount; i++) + for (int j = 0; j < coins.size(); j++) + if (coins[j] <= i) + dp[i] = min(dp[i], dp[i - coins[j]] + 1); + return dp[amount] > amount ? -1 : dp[amount]; + } +}; + +int main() { + vector<int> coins = {1, 2, 5}; + int amount = 11; + Solution obj; + cout << obj.coinChange(coins, amount); +} diff --git a/coin_change2.c b/coin_change2.c new file mode 100644 index 0000000..086ba0c --- /dev/null +++ b/coin_change2.c @@ -0,0 +1,33 @@ +// 518. Coin Change II +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array 'coins' representing cons of different denominations + * and an integer 'amount' representing a total amount of money. return the + * number of combinations that make up the amount. if that amount of money + * cannot be made up by any combination the coins, return 0. you may assume that + * you have an infinite number of each kind of coin. the answer is guaranteed to + * fit into a signed 32-bit integer. + */ + +int change(int amount, int *coins, int coins_size) { + if (!coins_size) { + if (!amount) + return 1; + return 0; + } + int *dp = (int *)calloc(amount + 1, sizeof(int)); + dp[0] = 1; + for (int i = 0; i < coins_size; i++) + for (int j = coins[i]; j < amount + 1; j++) + dp[j] += dp[j - coins[i]]; + return dp[amount]; +} + +int main() { + int c1[] = {1, 2, 5}, c2[] = {2}, c3[] = {10}; + printf("%d\n", change(5, c1, 3)); // expect: 4 + printf("%d\n", change(3, c2, 1)); // expect: 0 + printf("%d\n", change(10, c3, 1)); // expect: 1 +} diff --git a/coin_change2.cpp b/coin_change2.cpp new file mode 100644 index 0000000..4680c95 --- /dev/null +++ b/coin_change2.cpp @@ -0,0 +1,31 @@ +// 518. Coin Change II +#include "leetcode.h" + +/* + * given an integer array 'coins' representing cons of different denominations + * and an integer 'amount' representing a total amount of money. return the + * number of combinations that make up the amount. if that amount of money + * cannot be made up by any combination the coins, return 0. you may assume that + * you have an infinite number of each kind of coin. the answer is guaranteed to + * fit into a signed 32-bit integer. + */ + +class Solution { +public: + int change(int amount, vector<int> &coins) { + vector<int> dp(amount + 1, 0); + dp[0] = 1; + for (int i : coins) + for (int j = i; j <= amount; j++) + dp[j] += dp[j - i]; + return dp[amount]; + } +}; + +int main() { + Solution obj; + vector<int> c1 = {1, 2, 5}, c2 = {2}, c3 = {10}; + printf("%d\n", obj.change(5, c1)); // expect: 4 + printf("%d\n", obj.change(3, c2)); // expect: 0 + printf("%d\n", obj.change(10, c3)); // expect: 1 +} diff --git a/combination_sum3.cpp b/combination_sum3.cpp new file mode 100644 index 0000000..bde03a3 --- /dev/null +++ b/combination_sum3.cpp @@ -0,0 +1,38 @@ +#include "leetcode.h" + +class Solution { +public: + vector<vector<int>> combinationSum3(int k, int n) { + vector<vector<int>> ans; + vector<int> sol; + helper(ans, sol, k, n); + return ans; + } + void print(vector<vector<int>> &ans) { + for (int i = 0; i < ans.size(); i++) + for (int j = 0; j < ans.size(); j++) + cout << ans[i][j] << ' '; + } + +private: + void helper(vector<vector<int>> &ans, vector<int> sol, int k, int n) { + if (sol.size() == k && n == 0) { + ans.push_back(sol); + return; + } + if (sol.size() < k) + for (int i = sol.empty() ? 1 : sol.back() + 1; i <= 9; ++i) { + if (n - i < 0) + break; + sol.push_back(i); + helper(ans, sol, k, n - i); + sol.pop_back(); + } + } +}; + +int main() { + Solution obj; + vector<vector<int>> ans; + obj.print(ans); +} diff --git a/combination_sum4.c b/combination_sum4.c new file mode 100644 index 0000000..d4851b5 --- /dev/null +++ b/combination_sum4.c @@ -0,0 +1,37 @@ +// 377. Combination Sum IV +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array of disticint integers 'nums' and a target integer 'target', + * return the number of possible combinations that add up to 'target'. the test + * cases are generated such that the answer can fit in a 32 bit integer. + */ + +int cmp(const void *a, const void *b) { return *(int *)b - *(int *)b; } + +int combinationSum4(int *nums, int nums_size, int target) { + qsort(nums, nums_size, sizeof(int), cmp); + long long *dp = (long long *)calloc(target + 1, sizeof(long long)); + dp[0] = 1; + int ans; + for (int i = 1; i <= target; i++) + for (int j = 0; j < nums_size; j++) { + if (i >= nums[j]) { + dp[i] += dp[i - nums[j]]; + if (dp[i] >= INT_MAX) + dp[i] = INT_MAX; + } else + break; + } + ans = dp[target]; + free(dp); + return ans; +} + +int main() { + int n1[] = {1, 2, 3}, n2[] = {9}; + printf("%d\n", combinationSum4(n1, 3, 4)); // expect: 7 + printf("%d\n", combinationSum4(n2, 1, 3)); // expect: 0 +} diff --git a/combination_sum4.cpp b/combination_sum4.cpp new file mode 100644 index 0000000..b05bc96 --- /dev/null +++ b/combination_sum4.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + int combinationSum4(vector<int> &nums, int target) { + vector<unsigned int> dp(target + 1, 0); + dp[0] = 1; + for (int i = 0; i < target; i++) { + if (!dp[i]) + continue; + for (int num : nums) + if (num + i <= target) + dp[i + num] += dp[i]; + } + return dp[target]; + } +}; + +int main() { + Solution obj; + vector<int> nums = {1, 2, 3}; + int target = 4; + cout << obj.combinationSum4(nums, target); +} diff --git a/combination_sum4.py b/combination_sum4.py new file mode 100644 index 0000000..c4b0b05 --- /dev/null +++ b/combination_sum4.py @@ -0,0 +1,36 @@ +# 377. Combination Sum IV + +""" +given an array of disticint integers 'nums' and a target integer 'target', +return the number of possible combinations that add up to 'target'. the test +cases are generated such that the answer can fit in a 32 bit integer. +""" + + +class Solution(object): + def combinationSum4(self, nums, target): + nums.sort() + memo = {} + + def helper(n): + if n in memo: + return memo[n] + if n == 0: + return 1 + if n < nums[0]: + return 0 + cnt = 0 + for i in nums: + if n - i < 0: + break + cnt += helper(n - i) + memo[n] = cnt + return cnt + + return helper(target) + + +if __name__ == "__main__": + obj = Solution() + print(obj.combinationSum4([1, 2, 3], 4)) # expect: 7 + print(obj.combinationSum4([9], 3)) # expect: 0 diff --git a/combinations.c b/combinations.c new file mode 100644 index 0000000..29df639 --- /dev/null +++ b/combinations.c @@ -0,0 +1,62 @@ +// 77. Combinations +#include <stdio.h> +#include <stdlib.h> + +/* + * given two integers 'n' and 'k', return all possible combinations of 'k' + * numbers chosen from the range '[1, n]'. you may return the answer in any + * order + */ + +long factorial(int n) { + if (n == 1 || n == 0) + return 1; + else + return n * factorial(n - 1); +} + +void process(int **ans, int *idx, int *data, int n, int k, int pos, int curr) { + int i, j; + if (pos == k) { + for (i = 0; i < k; i++) + ans[*idx][i] = data[i]; + (*idx)++; + return; + } + for (i = curr; i <= n - k + 1 + pos; i++) { + data[pos] = i; + process(ans, idx, data, n, k, pos + 1, i + 1); + } +} + +int **combine(int n, int k, int *return_size, int **return_colum_size) { + int i, j; + long long c = 0; + c = factorial(n) / factorial(k) * factorial(n - k); + *return_colum_size = (int *)malloc(c * sizeof(int)); + *return_size = c; + int **ans = (int **)malloc(c * sizeof(int *)); + for (i = 0; i < c; i++) { + ans[i] = (int *)calloc(k, sizeof(int)); + return_colum_size[0][i] = k; + } + int *data = (int *)malloc(k * sizeof(int)); + int *idx = (int *)malloc(sizeof(int)); + *idx = 0; + process(ans, idx, data, n, k, 0, 1); + free(data), free(idx); + return ans; +} + +int main() { + int **c1 = combine(4, 2, NULL, NULL); + int **c2 = combine(1, 1, NULL, NULL); + for (int i = 0; i < 6; i++) + for (int j = 0; j < 2; j++) + printf("%d", c1[i][j]); //[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]] + printf("\n"); + for (int i = 0; i < 1; i++) + for (int j = 0; j < 1; j++) + printf("%d", c2[i][j]); //[[1]] + printf("\n"); +} diff --git a/combinations.cpp b/combinations.cpp new file mode 100644 index 0000000..f524fc2 --- /dev/null +++ b/combinations.cpp @@ -0,0 +1,39 @@ +// 77. Combinations +#include "leetcode.h" + +/* + * given two integers 'n' and 'k', return all possible combinations of 'k' + * numbers chosen from the range '[1, n]'. you may return the answer in any + * order + */ + +class Solution { +public: + vvd(int) combine(int n, int k) { + vvd(int) ans; + int i = 0; + vector<int> p(k, 0); + while (i >= 0) { + p[i]++; + if (p[i] > n) + --i; + else if (i == k - 1) + ans.push_back(p); + else + i++, p[i] = p[i - 1]; + } + return ans; + } +}; + +int main() { + Solution obj; + for (auto i : obj.combine(4, 2)) + for (auto j : i) + printf("%d ", j); // expect: [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]] + printf("\n"); + for (auto i : obj.combine(1, 1)) + for (auto j : i) + printf("%d ", j); // expect: [[1]] + printf("\n"); +} diff --git a/compare_version_num.c b/compare_version_num.c new file mode 100644 index 0000000..eaa3fed --- /dev/null +++ b/compare_version_num.c @@ -0,0 +1,84 @@ +// 165. Compare Version Numbers +#include "leetcode.h" + +/* + * given two version numbers 'version1' and 'version2', compare them. version + * numbers consist of one or more revisions joined by a dot. each revision + * consists of digits and may contain leading zeros. every revision contains at + * least one character. revisions are 0-indexed from left to right, right the + * leftmost revision being revision 0, the next revision being revision 1, and + * so on. to compare version numbers, use the following rules. if 'version1 < + * version2' return -1, if 'version1 > version2' return 1, otherwise, return 0 + */ + +int count_dot(char *s, int n) { + int dot = 0; + for (int i = 0; i < n; i++) + if (s[i] == '.') + dot++; + return dot; +} + +void helper(char *s, int n, int *data) { + int val = 0, idx = 0; + for (int i = 0; i < n; i++) + if (s[i] == '.') { + data[idx] = val; + idx++; + val = 0; + } else { + val = val * 10 + s[i] - '0'; + } + data[idx] = val; +} + +int compareVersion(char *version1, char *version2) { + int n1 = strlen(version1), n2 = strlen(version2); + int p1 = 0, p2 = 0, ans = 0; + int item1 = count_dot(version1, n1) + 1; + int item2 = count_dot(version2, n2) + 1; + int *data1 = (int *)malloc(item1 * sizeof(int)); + int *data2 = (int *)malloc(item2 * sizeof(int)); + helper(version1, n1, data1); + helper(version2, n2, data2); + while (p1 < item1 || p2 < item2) { + if (p1 == item1) { + for (int i = p2; i < item2; i++) + if (!data2[i]) { + ans = -1; + goto exit; + } + ans = 0; + goto exit; + } else if (p2 == item2) { + for (int i = p1; i < item1; i++) + if (!data1[i]) { + ans = 1; + goto exit; + } + ans = 0; + goto exit; + } else { + if (data1[p1] > data2[p2]) { + ans = 1; + goto exit; + } + if (data1[p1] < data2[p2]) { + ans = -1; + goto exit; + } + p1++, p2++; + } + } +exit: + free(data1), free(data2); + return ans; +} + +int main() { + char *v11 = "1.01", *v21 = "1.001", *v12 = "1.0", *v22 = "1.0.0", + *v13 = "0.1", *v23 = "1.1"; + printf("%d\n", compareVersion(v11, v21)); // expect: 0 + printf("%d\n", compareVersion(v12, v22)); // expect: 0 + printf("%d\n", compareVersion(v13, v23)); // expect: -1 +} diff --git a/compare_version_num.py b/compare_version_num.py new file mode 100644 index 0000000..fe8616b --- /dev/null +++ b/compare_version_num.py @@ -0,0 +1,37 @@ +# 165. Compare Version Numbers + +""" +given two version numbers 'version1' and 'version2', compare them. version +numbers consist of one or more revisions joined by a dot. each revision +consists of digits and may contain leading zeros. every revision contains at +least one character. revisions are 0-indexed from left to right, right the +leftmost revision being revision 0, the next revision being revision 1, and +so on. to compare version numbers, use the following rules. if 'version1 < +version2' return -1, if 'version1 > version2' return 1, otherwise, return 0 +""" + + +class Solution(object): + def compareVersion(self, version1, version2): + """ + :type version1: str + :type version2: str + :rtype: int + """ + n1 = [int(v) for v in version1.split(".")] + n2 = [int(v) for v in version2.split(".")] + for i in range(max(len(n1), len(n2))): + v1 = n1[i] if i < len(n1) else 0 + v2 = n2[i] if i < len(n2) else 0 + if v1 > v2: + return 1 + elif v1 < v2: + return -1 + return 0 + + +if __name__ == "__main__": + obj = Solution() + print(obj.compareVersion(version1="1.01", version2="1.001")) + print(obj.compareVersion(version1="1.0", version2="1.0.0")) + print(obj.compareVersion(version1="0.1", version2="1.1")) diff --git a/concatenated_words.c b/concatenated_words.c new file mode 100644 index 0000000..2278e5c --- /dev/null +++ b/concatenated_words.c @@ -0,0 +1,79 @@ +// 472. Concatenated Words +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given an array of strings 'words' (without duplicates), return all the + * concatenated words in the given list of 'words'. a concatenated word is + * defined as as string that is comprised entirely of at least two shorter + * words in the given array. + */ + +static int letterStarts[26]; + +int cmp(const void *a, const void *b) { + char *wordA = *((char **)a); + char *wordB = *((char **)b); + if (wordA[0] != wordB[0]) + return wordA[0] - wordB[0]; + else + return strlen(wordB) - strlen(wordA); +} + +bool findWord(char **dict, int dictSize, char *word, int offset, int skipIdx) { + int restLen = strlen(word + offset); + if (restLen == 0) + return true; + char firstLetter = (word + offset)[0]; + int letterStartsIdx = firstLetter - 'a'; + int startDictIdx = letterStarts[letterStartsIdx]; + int endDictIdx = dictSize; + if (startDictIdx == -1) + return false; + while (letterStartsIdx < 25) { + letterStartsIdx++; + if (letterStarts[letterStartsIdx] != -1) + break; + } + if (firstLetter != 'z' && letterStarts[letterStartsIdx] != -1) + endDictIdx = letterStarts[letterStartsIdx]; + for (int i = endDictIdx - 1; i >= startDictIdx; i--) { + if (i == skipIdx) + continue; + int len = strlen(dict[i]); + if (len == 0) + continue; + if (strncmp(dict[i], word + offset, len) == 0) { + bool res = findWord(dict, dictSize, word, offset + len, skipIdx); + if (res) + return true; + } + } + return false; +} + +char **findAllConcatenatedWordsInADict(char **words, int wordsSize, + int *returnSize) { + char **ans = malloc(1000 * sizeof(char *)); + int ansCnt = 0; + qsort(words, wordsSize, sizeof(char *), cmp); + for (int i = 0; i < 26; i++) + letterStarts[i] = -1; + for (int i = 0; i < wordsSize; i++) { + if (strlen(words[i]) == 0) + continue; + if (letterStarts[words[i][0] - 'a'] == -1) + letterStarts[words[i][0] - 'a'] = i; + } + for (int i = 0; i < wordsSize; i++) { + int len = strlen(words[i]); + if (len && findWord(words, wordsSize, words[i], 0, i)) { + ans[ansCnt] = malloc(len + 1); + strcpy(ans[ansCnt++], words[i]); + } + } + *returnSize = ansCnt; + return ans; +} diff --git a/concatenated_words.cpp b/concatenated_words.cpp new file mode 100644 index 0000000..9263d87 --- /dev/null +++ b/concatenated_words.cpp @@ -0,0 +1,75 @@ +// 472. Concatenated Words +#include "leetcode.h" + +/* + * given an array of strings 'words' (without duplicates), return all the + * concatenated words in the given list of 'words'. a concatenated word is + * defined as as string that is comprised entirely of at least two shorter + * words in the given array. + */ + +class Solution { +private: + struct Trie { + struct Trie *arr[26]; + bool end = false; + Trie() { + memset(arr, 0, sizeof(arr)); + end = false; + } + }; + Trie *root; + void insert(string s) { + Trie *node = root; + for (int i = s.length() - 1; i >= 0; i--) { + char c = s[i]; + if (!node->arr[c - 'a']) + node->arr[c - 'a'] = new Trie(); + node = node->arr[c - 'a']; + } + node->end = true; + } + +public: + vector<string> findAllConcatenatedWordsInADict(vector<string> &words) { + sort(words.begin(), words.end(), + [](string &w1, string &w2) { return (w1.length() <= w2.length()); }); + vector<string> ans; + root = new Trie(); + for (string w : words) { + if (w.length() == 0) + continue; + vector<bool> dp(w.length() + 1, false); + dp[0] = true; + for (int i = 0; i < w.length(); i++) { + Trie *node = root; + for (int j = i; j >= 0; j--) { + if (node->arr[w[j] - 'a'] == NULL) + break; + node = node->arr[w[j] - 'a']; + if (dp[j] && node->end) { + dp[i + 1] = true; + break; + } + } + } + if (dp[w.length()]) + ans.push_back(w); + insert(w); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<string> words1 = {"cat", "cats", "catsdogcats", + "dog", "dogcatsdog", "hippopotamuses", + "rat", "ratcatdogcat"}; + vector<string> words2 = {"cat", "dog", "catdog"}; + for (auto i : obj.findAllConcatenatedWordsInADict(words1)) + cout << i << ' '; + cout << endl; + for (auto i : obj.findAllConcatenatedWordsInADict(words2)) + cout << i << ' '; +} diff --git a/concatenation_binary_num.cpp b/concatenation_binary_num.cpp new file mode 100644 index 0000000..b212c09 --- /dev/null +++ b/concatenation_binary_num.cpp @@ -0,0 +1,38 @@ +#include "leetcode.h" + +class Solution { +public: + int concatenatedBinary(int n) { + string s = decimalToBinary(n); + return binaryToDecimal(s); + } + +private: + int mod = 1000000007; + string decimalToBinary(int n) { + string str = ""; + for (int i = n; i >= 1; --i) { + int j = i; + while (j) { + str += (j % 2) + '0'; + j /= 2; + } + } + return str; + } + int binaryToDecimal(string n) { + long long ans = 0, p = 1; + for (int i = 0; i < n.size(); ++i) { + long long curr = (n[i] - '0') * p; + p *= 2; + p %= mod; + ans += curr; + } + return ans % mod; + } +}; + +int main() { + Solution obj; + cout << obj.concatenatedBinary(3); +} diff --git a/constrained_subseq_sum.c b/constrained_subseq_sum.c new file mode 100644 index 0000000..89434a6 --- /dev/null +++ b/constrained_subseq_sum.c @@ -0,0 +1,88 @@ +// 1425. Constrained Subsequence Sum +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array 'nums' and an integer 'k', return the maximum sum of a + * non-empty subsequnce of that array for every two consecutive integers in the + * subsequence 'nums[i] and 'nums[j] where 'i < j', the condition 'j - i <= k' + * is satisfied. a subsequence of an array is obtained by deleting some number + * of elements (can be zero) from the array, leaving the remaining elements in + * their original order. + */ + +int bfs(int *nums, int n, int val) { + int left = 0, right = n - 1, mid; + while (left < right) { + mid = left + (right - left) / 2; + if (nums[mid] >= val) + left = mid + 1; + else + right = mid; + } + return left; +} + +int constrainedSubsetSum(int *nums, int nums_size, int k) { + int n = nums_size, max = INT_MIN, head = 0, tail = 1; + int *queue = malloc((n + 1) * sizeof(int)); + int *dp = malloc((n + 1) * sizeof(int)); + dp[0] = 0; + queue[head] = 0; + for (int i = 1; i <= k; i++) { + dp[i] = nums[i - 1]; + if (queue[head]) + dp[i] += queue[head]; + max = fmax(max, dp[i]); + if (dp[i] < 0) + continue; + else if (dp[i] > queue[head]) { + queue[head] = dp[i]; + tail = head + 1; + } else if (dp[i] <= queue[tail - 1]) { + queue[tail] = dp[i]; + tail++; + } else { + int m = bfs(&queue[head], tail - head, dp[i]); + queue[head + m] = dp[i]; + tail = head + m + 1; + } + } + for (int i = k + 1; i <= n; i++) { + dp[i] = nums[i - 1]; + if (queue[head]) + dp[i] += queue[head]; + max = fmax(max, dp[i]); + if (queue[head] == dp[i - k] && dp[i - k]) { + head++; + if (head == tail) { + queue[head] = 0; + tail = head + 1; + } + } + if (dp[i] < 0) + continue; + else if (dp[i] > queue[head]) { + queue[head] = dp[i]; + tail = head + 1; + } else if (dp[i] <= queue[tail - 1]) { + queue[tail] = dp[i]; + tail++; + } else { + int m = bfs(&queue[head], tail - head, dp[i]); + queue[head + m] = dp[i]; + tail = head + m + 1; + } + } + return max; +} + +int main() { + int n1[] = {10, 2, -10, 5, 20}, n2[] = {-1, -2, -3}, + n3[] = {10, -2, -10, -5, 20}; + printf("%d\n", constrainedSubsetSum(n1, 5, 2)); // expect: 37 + printf("%d\n", constrainedSubsetSum(n2, 3, 1)); // expect: -1 + printf("%d\n", constrainedSubsetSum(n3, 5, 2)); // expect: 23 +} diff --git a/constrained_subseq_sum.py b/constrained_subseq_sum.py new file mode 100644 index 0000000..95305b7 --- /dev/null +++ b/constrained_subseq_sum.py @@ -0,0 +1,32 @@ +# 1425. Constrained Subsequence Sum +import collections + +""" +given an integer array 'nums' and an integer 'k', return the maximum sum of a +non-empty subsequnce of that array for every two consecutive integers in the +subsequence 'nums[i] and 'nums[j] where 'i < j', the condition 'j - i <= k' +is satisfied. a subsequence of an array is obtained by deleting some number +of elements (can be zero) from the array, leaving the remaining elements in +their original order. +""" + + +class Solution(object): + def constrainedSubsetSum(self, nums, k): + dq = collections.deque + for i in range(len(nums)): + nums[i] += dq[0] if dq else 0 + while len(dq) and nums[i] > dq[-1]: + dp.pop() + if nums[i] > 0: + dq.append(nums[i]) + if i >= k and dq and dq[0] == nums[i - k]: + dq.popleft() + return max(nums) + + +if __name__ == "__main__": + obj = Solution() + print(obj.constrainedSubsetSum(nums=[10, 2, -10, 5, 20], k=2)) # expect: 37 + print(obj.constrainedSubsetSum(nums=[-1, -2, -3], k=1)) # expect: -1 + print(obj.constrainedSubsetSum(nums=[10, -2, -10, -5, 20], k=2)) # expect: 23 diff --git a/construct_array_multiple_sum.cpp b/construct_array_multiple_sum.cpp new file mode 100644 index 0000000..5d2751d --- /dev/null +++ b/construct_array_multiple_sum.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + bool isPossible(vector<int> &target) { + long total = 0; + int i; + priority_queue<int> pq(target.begin(), target.end()); + for (int i : target) + total += i; + while (true) { + i = pq.top(); + pq.pop(); + total -= i; + if (i == 1 || total == 1) + return true; + if (i < total || total == 0 || i % total == 0) + return false; + i %= total; + total += i; + pq.push(i); + } + } +}; + +int main() { + Solution obj; + vector<int> target = {9, 3, 5}; + cout << obj.isPossible(target); +} diff --git a/construct_bt_io_po.c b/construct_bt_io_po.c new file mode 100644 index 0000000..9c145eb --- /dev/null +++ b/construct_bt_io_po.c @@ -0,0 +1,37 @@ +// 106. Construct Binary Tree from Inorder and Postorder Traversal +#include <stdint.h> +#include <stdlib.h> + +/* + * given two integer arrays 'inorder' and 'postorder', where 'inorder' is the + * inorder traversal of a binary tree, and 'postorder' is the postorder + * traversal of the same tree, construct and return the binary tree. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +struct TreeNode *buildTree(int *inorder, int inorder_size, int *postorder, + int postorder_size) { + if (inorder_size == 0) + return NULL; + struct TreeNode *root = (struct TreeNode *)malloc(sizeof(struct TreeNode)); + root->val = postorder[postorder_size - 1]; + root->left = NULL; + root->right = NULL; + if (postorder_size == 1) + return root; + uint16_t i; + for (i = 0; i < inorder_size; i++) + if (inorder[i] == root->val) + break; + int l_size = i; + root->left = buildTree(inorder, l_size, postorder, l_size); + int r_size = postorder_size - 1 - l_size; + root->right = + buildTree(&inorder[1 + l_size], r_size, &postorder[l_size], r_size); + return root; +} diff --git a/construct_bt_io_po.cpp b/construct_bt_io_po.cpp new file mode 100644 index 0000000..6fb9163 --- /dev/null +++ b/construct_bt_io_po.cpp @@ -0,0 +1,31 @@ +// 106. Construct Binary Tree from Inorder and Postorder Traversal +#include "leetcode.h" + +/* + * given two integer arrays 'inorder' and 'postorder', where 'inorder' is the + * inorder traversal of a binary tree, and 'postorder' is the postorder + * traversal of the same tree, construct and return the binary tree. + */ + +class Solution { +public: + TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder) { + int n = inorder.size(), po_idx = n - 1; + for (int i = 0; i < n; i++) + um[inorder[i]] = i; + return construct(inorder, postorder, 0, n - 1, po_idx); + } + +private: + unordered_map<int, int> um; + TreeNode *construct(vector<int> &inorder, vector<int> &postorder, + int io_start, int io_end, int po_idx) { + if (io_start > io_end) + return nullptr; + TreeNode *root = new TreeNode(postorder[po_idx--]); + int io_idx = um[root->val]; + root->right = construct(inorder, postorder, io_idx + 1, io_end, po_idx); + root->left = construct(inorder, postorder, io_start, io_idx - 1, po_idx); + return root; + } +}; diff --git a/construct_k_palindrome_str.c b/construct_k_palindrome_str.c new file mode 100644 index 0000000..843ebbb --- /dev/null +++ b/construct_k_palindrome_str.c @@ -0,0 +1,31 @@ +// 1400. Construct K Palindrome Strings +#include "leetcode.h" + +/* + * given a string 's' and an integer 'k', return true if you can use all the + * characters in 's' to constuct 'k' palindrome strings or false otherwise. + */ + +bool canConstruct(char *s, int k) { + int n = strlen(s); + if (n < k) + return 0; + int *c = calloc(26, sizeof(int)); + for (int i = 0; i < n; i++) + c[s[i] - 'a']++; + int odd = 0; + for (int i = 0; i < 26; i++) + if (c[i] % 2 == 1) + odd++; + free(c); + if (odd > k) + return 0; + return 1; +} + +int main() { + char *s1 = "annabelle", *s2 = "leetcode", *s3 = "true"; + printf("%d\n", canConstruct(s1, 2)); // expect: 1 + printf("%d\n", canConstruct(s2, 3)); // expect: 0 + printf("%d\n", canConstruct(s3, 4)); // expect: 1 +} diff --git a/construct_k_palindrome_str.py b/construct_k_palindrome_str.py new file mode 100644 index 0000000..bd5c209 --- /dev/null +++ b/construct_k_palindrome_str.py @@ -0,0 +1,24 @@ +# 1400. Construct K Palindrome Strings +from collections import Counter + +""" +given a string 's' and an integer 'k', return true if you can use all the +characters in 's' to constuct 'k' palindrome strings or false otherwise. +""" + + +class Solution(object): + def canConstruct(self, s, k): + """ + :type s: str + :type k: int + :rtype: bool + """ + return sum(i & 1 for i in Counter(s).values()) <= k <= len(s) + + +if __name__ == "__main__": + obj = Solution() + print(obj.canConstruct("annabelle", 2)) + print(obj.canConstruct("leetcode", 3)) + print(obj.canConstruct("true", 4)) diff --git a/construct_quad_tree.cpp b/construct_quad_tree.cpp new file mode 100644 index 0000000..3fdf395 --- /dev/null +++ b/construct_quad_tree.cpp @@ -0,0 +1,75 @@ +// 427. Construct Quad Tree +#include <bits/stdc++.h> +using namespace std; +#define vvd(data) vector<vector<data>> + +/* + * wtf this is right pants for a medium + */ + +class Node { +public: + bool val; + bool isLeaf; + Node *topLeft; + Node *topRight; + Node *bottomLeft; + Node *bottomRight; + Node() { + val = false; + isLeaf = false; + topLeft = NULL; + topRight = NULL; + bottomLeft = NULL; + bottomRight = NULL; + } + Node(bool _val, bool _isLeaf) { + val = _val; + isLeaf = _isLeaf; + topLeft = NULL; + topRight = NULL; + bottomLeft = NULL; + bottomRight = NULL; + } + Node(bool _val, bool _isLeaf, Node *_topLeft, Node *_topRight, + Node *_bottomLeft, Node *_bottomRight) { + val = _val; + isLeaf = _isLeaf; + topLeft = _topLeft; + topRight = _topRight; + bottomLeft = _bottomLeft; + bottomRight = _bottomRight; + } +}; + +class Solution { +public: + Node *construct(vvd(int) & grid) { + grid_v = move(grid); + leafNodes_a[0] = new Node(false, true, nullptr, nullptr, nullptr, nullptr); + leafNodes_a[1] = new Node(true, true, nullptr, nullptr, nullptr, nullptr); + return construct(0, 0, grid_v.size()); + } + +private: + vvd(int) grid_v; + array<Node *, 2> leafNodes_a; + Node *construct(int r, int c, int s) { + if (s == 1) + return leafNodes_a[grid_v[r][c]]; + s /= 2; + Node *tl = construct(r, c, s); + Node *tr = construct(r, c + s, s); + Node *bl = construct(r + s, c, s); + Node *br = construct(r + s, c + s, s); + if (tl == tr && tl == bl && tl == br) + return tl; + return new Node(false, false, tl, tr, bl, br); + } +}; + +int main() { + Solution obj; + vvd(int) grid = {{0, 1}, {1, 0}}; + cout << obj.construct(grid); // expect: [[0,1],[1,0],[1,1],[1,1],[1,0]] +} diff --git a/construct_string_binary_tree.c b/construct_string_binary_tree.c new file mode 100644 index 0000000..d061b40 --- /dev/null +++ b/construct_string_binary_tree.c @@ -0,0 +1,42 @@ +// 606. Construct String from Binary Tree +#include "leetcode.h" + +/* + * given the root of a binary tree, construct a string consisting of parenthesis + * and integers from a binary tree with the preorder traversal way, and return + * it. omit all the empty parenthesis pairs that do not affect the one-to-one + * mapping relationship between the string and the original binary tree + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +void helper(struct TreeNode *t, char *ans, int *count) { + if (!t) + return; + *count += sprintf(&ans[*count], "%d", t->val); + if (!(t->left) && !(t->right)) + return; + else { + *count += sprintf(&ans[*count], "("); + helper(t->left, ans, count); + *count += sprintf(&ans[*count], ")"); + if (t->right != NULL) { + *count += sprintf(&ans[*count], "("); + helper(t->right, ans, count); + *count += sprintf(&ans[*count], ")"); + } + return; + } +} + +char *tree2str(struct TreeNode *t) { + char *ans = calloc(30000, sizeof(char)); + int count = 0; + helper(t, ans, &count); + ans[count] = '\0'; + return ans; +} diff --git a/construct_string_binary_tree.cpp b/construct_string_binary_tree.cpp new file mode 100644 index 0000000..a63e3c9 --- /dev/null +++ b/construct_string_binary_tree.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + string tree2str(TreeNode *root) { + if (!root) + return ""; + string ans = to_string(root->val); + if (root->left || root->right) { + ans.push_back('('); + ans += tree2str(root->left); + ans.push_back(')'); + } + if (root->right) { + ans.push_back('('); + ans += tree2str(root->right); + ans.push_back(')'); + } + return ans; + } +}; diff --git a/construct_string_binary_tree.py b/construct_string_binary_tree.py new file mode 100644 index 0000000..012b569 --- /dev/null +++ b/construct_string_binary_tree.py @@ -0,0 +1,60 @@ +# 606. Construct String from Binary Tree + +""" +given the root of a binary tree, construct a string consisting of parenthesis +and integers from a binary tree with the preorder traversal way, and return +it. omit all the empty parenthesis pairs that do not affect the one-to-one +mapping relationship between the string and the original binary tree +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def tree2str(self, root): + """ + :type root: TreeNode + :rtype: str + """ + + def generate_paren_str(self, node): + if not node: + return "" + + left_str = generate_paren_str(node.left) + right_str = generate_paren_str(node.right) + level_str = f"{node.val}({left_str})({right_str})" + return level_str + + def strip_excessive_parenthesis(self, parenthesis_str): + final_str = [] + n = len(parenthesis_str) + i = 0 + while i < n: + if i + 4 <= n and parenthesis_str[i : i + 4] == "()()": + i += 4 + continue + + if i + 3 <= n and ( + parenthesis_str[i : i + 3] == "())" + or parenthesis_str[i : i + 3] == ")()" + ): + i += 2 + continue + + final_str.append(parenthesis_str[i]) + i += 1 + return "".join(final_str) + + return strip_excessive_parenthesis(generate_paren_str(root)) + + +if __name__ == "__main__": + obj = Solution() + print(obj.tree2str(root=[1, 2, 3, 4])) # expect: "1(2(4))(3)" diff --git a/contains_duplicate.cpp b/contains_duplicate.cpp new file mode 100644 index 0000000..5de86d2 --- /dev/null +++ b/contains_duplicate.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + bool containsDuplicate(vector<int> &nums) { + bool ans = false; + for (int i = 0; i < nums.size(); i++) + for (int j = i + 1; j < nums.size(); j++) + if (nums[i] == nums[j]) + ans = true; + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums1 = {1, 2, 3, 1}, nums2 = {1, 2, 3, 4}, + nums3 = {1, 1, 1, 3, 3, 4, 3, 2, 4, 2}; + cout << obj.containsDuplicate(nums1) << endl; // expect: 1 + cout << obj.containsDuplicate(nums2) << endl; // expect: 0 + cout << obj.containsDuplicate(nums3) << endl; // expect: 1 +} diff --git a/contains_duplicate2.cpp b/contains_duplicate2.cpp new file mode 100644 index 0000000..9af7758 --- /dev/null +++ b/contains_duplicate2.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + bool containsNearbyDuplicate(vector<int> &nums, int k) { + unordered_map<int, int> um; + for (int i = 0; i < nums.size(); i++) { + if (um.count(nums[i])) + if (abs(i - um[nums[i]]) <= k) + return true; + um[nums[i]] = i; + } + return false; + } +}; + +int main() { + Solution obj; + vector<int> nums = {1, 2, 3, 1}; + if (obj.containsNearbyDuplicate(nums, 3)) + cout << "true"; + else + cout << "false"; +} diff --git a/contains_duplicate2.rs b/contains_duplicate2.rs new file mode 100644 index 0000000..b016e21 --- /dev/null +++ b/contains_duplicate2.rs @@ -0,0 +1,21 @@ +use std::collections::HashMap; +struct Solution; + +impl Solution { + pub fn contains_nearby_duplicate(nums: Vec<i32>, k: i32) -> bool { + let mut hm = HashMap::new(); + for (i, n) in nums.iter().enumerate() { + if let Some(j) = hm.insert(n, i) { + if (i as i32) - (j as i32) <= k { + return true; + } + } + } + false + } +} + +fn main() { + let nums = vec![1,2,3,1]; + print!("{}", Solution::contains_nearby_duplicate(nums, 3)); +} diff --git a/contains_duplicate3.cpp b/contains_duplicate3.cpp new file mode 100644 index 0000000..6e1467c --- /dev/null +++ b/contains_duplicate3.cpp @@ -0,0 +1,52 @@ +// 220. Contains Duplicate III +#include "leetcode.h" + +/* + * given an integer array 'nums' and two integers 'index_diff' + * and 'value_diff'. find a pai of indices '(i, j)' such that: + * i != j + * abs(i - j) <= index_diff + * abs(num[i] - num[j]) <= value_diff + * return true if such pair exists or false otherwise + */ + +class Solution { +public: + bool containsNearbyAlmostDuplicate(vector<int> &nums, int index_diff, + int value_diff) { + int n = nums.size(); + if (n == 0 || index_diff < 0 || value_diff < 0) + return false; + unordered_map<int, int> buckets; + for (int i = 0; i < n; i++) { + int b = nums[i] / ((long)value_diff + 1); + if (nums[i] < 0) + --b; + if (buckets.find(b) != buckets.end()) + return true; + else { + buckets[b] = nums[i]; + if (buckets.find(b - 1) != buckets.end() && + (long)nums[i] - buckets[b - 1] <= value_diff) + return true; + if (buckets.find(b + 1) != buckets.end() && + (long)buckets[b + 1] - nums[i] <= value_diff) + return true; + if (buckets.size() > index_diff) { + int remove = nums[i - index_diff] / ((long)value_diff + 1); + if (nums[i - index_diff] < 0) + --remove; + buckets.erase(remove); + } + } + } + return false; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 2, 3, 1}, n2 = {1, 5, 9, 1, 5, 9}; + printf("%d\n", obj.containsNearbyAlmostDuplicate(n1, 3, 0)); // expect: 1 + printf("%d\n", obj.containsNearbyAlmostDuplicate(n2, 2, 3)); // expect: 0 +} diff --git a/contains_virus.cpp b/contains_virus.cpp new file mode 100644 index 0000000..4380995 --- /dev/null +++ b/contains_virus.cpp @@ -0,0 +1,77 @@ +// 749. Contain Virus +#include "leetcode.h" + +class Cluster { +public: + set<pair<int, int>> c; + set<pair<int, int>> uc; + int w_cnt = 0; +}; + +class Solution { +public: + int containsVirus(vvd(int) & isInfected) { + int n = isInfected.size(), m = isInfected[0].size(), ans = 0; + while (1) { + vvd(bool) vis(n, vector<bool>(m)); + auto cmp = [](const Cluster &A, const Cluster &B) { + return A.uc.size() < B.uc.size(); + }; + priority_queue<Cluster, vector<Cluster>, decltype(cmp)> pq(cmp); + for (int i = 0; i < n; i++) + for (int j = 0; j < m; j++) + if (!vis[i][j] && isInfected[i][j] == 1) { + Cluster c; + dfs(isInfected, i, j, vis, c); + pq.push(c); + } + if (pq.size() == 0) + break; + Cluster k = pq.top(); + pq.pop(); + for (auto x : k.c) + isInfected[x.first][x.second] = -1; + ans += k.w_cnt; + while (!pq.empty()) { + Cluster k1 = pq.top(); + pq.pop(); + for (auto x : k1.uc) + isInfected[x.first][x.second] = 1; + } + } + return ans; + } + +private: + void dfs(vvd(int) & grid, int i, int j, vvd(bool) & vis, Cluster &cl) { + if (i == grid.size() || i < 0 || j < 0 || j == grid[0].size() || + vis[i][j] || grid[i][j] == -1) + return; + if (grid[i][j] == 0) { + cl.w_cnt++; + cl.uc.insert({i, j}); + return; + } + cl.c.insert({i, j}); + vis[i][j] = true; + dfs(grid, i + 1, j, vis, cl); // above + dfs(grid, i - 1, j, vis, cl); // below + dfs(grid, i, j + 1, vis, cl); // right + dfs(grid, i, j - 1, vis, cl); // left + } +}; + +int main() { + Solution obj; + vvd(int) isInfected1 = {{0, 1, 0, 0, 0, 0, 0, 1}, + {0, 1, 0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 1}, + {0, 0, 0, 0, 0, 0, 0, 0}}; + vvd(int) isInfected2 = {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}}; + vvd(int) isInfected3 = {{1, 1, 1, 0, 0, 0, 0, 0, 0}, + {1, 0, 1, 0, 1, 1, 1, 1, 1}, + {1, 1, 1, 0, 0, 0, 0, 0, 0}}; + cout << obj.containsVirus(isInfected1) << endl; // expect: 10 + cout << obj.containsVirus(isInfected2) << endl; // expect: 4 + cout << obj.containsVirus(isInfected3) << endl; // expect: 13 +} diff --git a/contiguous_array.c b/contiguous_array.c new file mode 100644 index 0000000..fbd8c9a --- /dev/null +++ b/contiguous_array.c @@ -0,0 +1,27 @@ +// 525. Contiguous Array +#include "leetcode.h" + +/* + * given a binary array 'nums' return the maximum length of a contiguous + * subarray with an equal number of 0 and 1. + */ + +int findMaxLength(int *nums, int numsSize) { + int max = 0, bl = 0, arr[2 * numsSize + 1]; + for (int i = 0; i < 2 * numsSize + 1; i++) + arr[i] = -2; + arr[numsSize] = -1; + for (int i = 0; i < numsSize; i++) { + nums[i] ? bl++ : bl--; + if (arr[numsSize + bl] < -1) + arr[numsSize + bl] = i; + max = fmax(max, i - arr[numsSize + bl]); + } + return max; +} + +int main() { + int n1[] = {0, 1}, n2[] = {0, 1, 0}; + printf("%d\n", findMaxLength(n1, ARRAY_SIZE(n1))); // expect: 2 + printf("%d\n", findMaxLength(n2, ARRAY_SIZE(n2))); // expect: 2 +} diff --git a/contiguous_array.py b/contiguous_array.py new file mode 100644 index 0000000..8bd17a5 --- /dev/null +++ b/contiguous_array.py @@ -0,0 +1,32 @@ +# 525. Contiguous Array + +""" +given a binary array 'nums' return the maximum length of a contiguous +subarray with an equal number of 0 and 1. +""" + + +class Solution(object): + def findMaxLength(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + cnt, max_length = 0, 0 + table = {0: 0} + for idx, n in enumerate(nums, 1): + if n == 0: + cnt -= 1 + else: + cnt += 1 + if cnt in table: + max_length = max(max_length, idx - table[cnt]) + else: + table[cnt] = idx + return max_length + + +if __name__ == "__main__": + obj = Solution() + print(obj.findMaxLength([0, 1])) + print(obj.findMaxLength([0, 1, 0])) diff --git a/continuous_subarr_sum.c b/continuous_subarr_sum.c new file mode 100644 index 0000000..06879a3 --- /dev/null +++ b/continuous_subarr_sum.c @@ -0,0 +1,76 @@ +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +struct node { + int key; + int val; + struct node *next; +}; + +struct table { + int size; + struct node **list; +}; + +struct table *createTable(int size) { + struct table *t = (struct table *)malloc(sizeof(struct table)); + t->size = size; + t->list = (struct node **)malloc(sizeof(struct node *) * size); + for (int i = 0; i < size; i++) + t->list[i] = NULL; + return t; +} + +int hashCode(struct table *t, int key) { + if (key < 0) + return -(key % t->size); + return key % t->size; +} + +void insert(struct table *t, int key, int val) { + int pos = hashCode(t, key); + struct node *list = t->list[pos]; + struct node *newNode = (struct node *)malloc(sizeof(struct node)); + newNode->key = key; + newNode->val = val; + newNode->next = list; + t->list[pos] = newNode; +} + +int lut(struct table *t, int key) { + int pos = hashCode(t, key); + struct node *list = t->list[pos]; + struct node *tmp = list; + while (tmp) { + if (tmp->key == key) + return tmp->val; + tmp = tmp->next; + } + return INT_MAX; +} + +bool checkSubarraySum(int *nums, int numsSize, int k) { + struct table *t = createTable(10); + int sum = 0; + insert(t, 0, -1); + for (int i = 0; i < numsSize; i++) { + sum += nums[i]; + if (k) + sum %= k; + if (lut(t, sum) != INT_MAX) { + if (i - lut(t, sum) > 1) + return true; + } else + insert(t, sum, i); + } + return false; +} + +int main() { + int nums1[] = {23, 2, 4, 6, 7}, nums2[] = {23, 2, 6, 4, 7}; + printf("%d\n", checkSubarraySum(nums1, 5, 6)); // expect: 1 + printf("%d\n", checkSubarraySum(nums2, 5, 6)); // expect: 1 + printf("%d\n", checkSubarraySum(nums2, 5, 13)); // expect: 0 +} diff --git a/continuous_subarr_sum.cpp b/continuous_subarr_sum.cpp new file mode 100644 index 0000000..ceaf3ce --- /dev/null +++ b/continuous_subarr_sum.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + bool checkSubarraySum(vector<int> &nums, int k) { + unordered_map<int, int> um; + int s = 0; + um[0] = -1; + for (int i = 0; i < nums.size(); i++) { + s += nums[i]; + if (k != 0) + s %= k; + if (um.find(s) != um.end()) { + if (i - um[s] > 1) + return true; + } else + um[s] = i; + } + return false; + } +}; + +int main() { + Solution obj; + vector<int> nums = {23, 2, 4, 6, 7}; + int k = 6; + if (obj.checkSubarraySum(nums, k)) + cout << "true"; + else + cout << "false"; +} diff --git a/continuous_subarr_sum.py b/continuous_subarr_sum.py new file mode 100644 index 0000000..06c6b13 --- /dev/null +++ b/continuous_subarr_sum.py @@ -0,0 +1,29 @@ +# 523. Continuous Subarray Sum + + +class Solution(object): + def checkSubarraySum(self, nums, k): + """ + :type nums: List[int] + :type k: int + :rtype: bool + """ + dic, sum = {0: -1}, 0 + for i, n in enumerate(nums): + if k != 0: + sum = (sum + n) % k + else: + sum += n + if sum not in dic: + dic[sum] = i + else: + if i - dic[sum] >= 2: + return True + return False + + +if __name__ == "__main__": + obj = Solution() + print(obj.checkSubarraySum(nums=[23, 2, 4, 6, 7], k=6)) + print(obj.checkSubarraySum(nums=[23, 2, 6, 4, 7], k=6)) + print(obj.checkSubarraySum(nums=[23, 2, 6, 4, 7], k=13)) diff --git a/continuous_subarr_sum.rs b/continuous_subarr_sum.rs new file mode 100644 index 0000000..2e1567e --- /dev/null +++ b/continuous_subarr_sum.rs @@ -0,0 +1,24 @@ +use std::collections::HashSet; +struct Solution; + +impl Solution { + pub fn check_subarray_sum(nums: Vec<i32>, k: i32) -> bool { + let mut mod_k_val = HashSet::<i32>::from([0]); + let mut prefix_sum = nums[0] % k; + for val in nums.into_iter().skip(1) { + let tba = prefix_sum; + prefix_sum = (prefix_sum + val) % k; + if mod_k_val.contains(&prefix_sum) { + return true; + } + mod_k_val.insert(tba); + } + false + } +} + +fn main() { + let nums = vec![18,84,4,38,11,248]; + let k = 6; + print!("{}", Solution::check_subarray_sum(nums, k)); +} diff --git a/convert_arr_2d_cond.c b/convert_arr_2d_cond.c new file mode 100644 index 0000000..9e3effc --- /dev/null +++ b/convert_arr_2d_cond.c @@ -0,0 +1,35 @@ +// 2610. Convert an Array Into a 2D Array With Conditions +#include "leetcode.h" + +/* + * given an integer array 'nums', you should create a 2d array from 'nums' + * satisfying the following conditions. the 2d array should contain only the + * elements of the array 'nums'. each row in the 2d array contains distinct + * integers. the number of rows in the 2d array should be minimal. return the + * resulting array. if there are multiple answers, return any of them. note that + * the 2d array can have a different number of elements on each row. + */ + +int **findMatrix(int *nums, int nums_size, int *return_size, + int **return_column_sizes) { + int *table = calloc(201, sizeof(int)); + *return_size = 0; + for (int i = 0; i < nums_size; i++) { + table[nums[i]]++; + *return_size = fmax(*return_size, table[nums[i]]); + } + int **ans = malloc(sizeof(int *) * *return_size); + *return_column_sizes = calloc(*return_size, sizeof(int)); + for (int i = 0; i < *return_size; i++) + ans[i] = calloc(nums_size, sizeof(int)); + for (int i = 0; i <= 200; i++) { + int row = 0; + while (table[i]) { + ans[row][*return_column_sizes[row]++] = i; + table--; + row++; + } + } + free(table); + return ans; +} diff --git a/convert_arr_2d_cond.py b/convert_arr_2d_cond.py new file mode 100644 index 0000000..94c4648 --- /dev/null +++ b/convert_arr_2d_cond.py @@ -0,0 +1,39 @@ +# 2610. Convert an Array Into a 2D Array With Conditions + +""" +given an integer array 'nums', you should create a 2d array from 'nums' +satisfying the following conditions. the 2d array should contain only the +elements of the array 'nums'. each row in the 2d array contains distinct +integers. the number of rows in the 2d array should be minimal. return the +resulting array. if there are multiple answers, return any of them. note that +the 2d array can have a different number of elements on each row. +""" + +class Solution(object): + def findMatrix(self, nums): + """ + :type nums: List[int] + :rtype: List[List[int]] + """ + um = {} + ans = [] + for i in nums: + um[i] = um.get(i, 0) + 1 + while um: + tmp = [] + to_erase = [] + for f, s in um.items(): + tmp.append(f) + s -= 1 + if s == 0: + to_erase.append(f) + um[f] = s + ans.append(tmp) + for i in to_erase: + del um[i] + return ans + +if __name__ == "__main__": + obj = Solution() + print(obj.findMatrix(nums = [1,3,4,1,2,3,1])) # expect: [[1,3,4,2],[1,3],[1]] + print(obj.findMatrix(nums = [1,2,3,4])) # expect: [[4,3,2,1]] diff --git a/convert_sorted_bst.c b/convert_sorted_bst.c new file mode 100644 index 0000000..8e710c1 --- /dev/null +++ b/convert_sorted_bst.c @@ -0,0 +1,56 @@ +// 109. Convert Sorted List to Binary Search Tree +#include <stdlib.h> + +/* + * given 'head' of a singly linked list where elements are sorted in ascending + * order convert it to a height balanced binary search tree. meaning the depth + * of two sub- trees of every node never differs by more than one. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int list_len(struct ListNode *head) { + struct ListNode *tmp = head; + int cnt = 0; + while (tmp) + cnt++, tmp = tmp->next; + return cnt; +} + +struct TreeNode *sortedArrayToBST(int *nums, int n) { + if (n <= 0) + return NULL; + struct TreeNode *root = malloc(sizeof(struct TreeNode)); + if (n == 1) { + root->val = nums[0]; + root->left = NULL; + root->right = NULL; + } else { + root->val = nums[n / 2]; + root->left = sortedArrayToBST(nums, n / 2); + root->right = sortedArrayToBST(&nums[n / 2 + 1], n - 1 - n / 2); + } + return root; +} + +struct TreeNode *sortedListToBST(struct ListNode *head) { + int n = list_len(head); + if (n == 0) + return NULL; + int *nums = malloc(n * sizeof(int)); + struct ListNode *tmp = head; + for (int i = 0; i < n; i++) { + nums[i] = tmp->val; + tmp = tmp->next; + } + return sortedArrayToBST(nums, n); +} diff --git a/convert_sorted_bst.cpp b/convert_sorted_bst.cpp new file mode 100644 index 0000000..8b5b656 --- /dev/null +++ b/convert_sorted_bst.cpp @@ -0,0 +1,29 @@ +// 109. Convert Sorted List to Binary Search Tree +#include "leetcode.h" + +/* + * given 'head' of a singly linked list where elements are sorted in ascending + * order convert it to a height balanced binary search tree. meaning the depth + * of two sub- trees of every node never differs by more than one. + */ + +class Solution { +public: + TreeNode *sortedListToBST(ListNode *head) { + if (!head) + return NULL; + if (!head->next) + return new TreeNode(head->val); + auto slow = head, fast = head, pre = head; + while (fast && fast->next) { + pre = slow; + slow = slow->next; + fast = fast->next->next; + } + pre->next = 0; + TreeNode *root = new TreeNode(slow->val); + root->left = sortedListToBST(head); + root->right = sortedListToBST(slow->next); + return root; + } +}; diff --git a/copy_list_rand_ptr.c b/copy_list_rand_ptr.c new file mode 100644 index 0000000..544ba3d --- /dev/null +++ b/copy_list_rand_ptr.c @@ -0,0 +1,94 @@ +// 138. Copy List with Random Pointer +#include <stdlib.h> + +/* + A linked list of length n is given such that each node contains an additional + random pointer, which could point to any node in the list, or null. + + Construct a deep copy of the list. The deep copy should consist of exactly n + brand new nodes, where each new node has its value set to the value of its + corresponding original node. Both the next and random pointer of the new nodes + should point to new nodes in the copied list such that the pointers in the + original list and copied list represent the same list state. None of the + pointers in the new list should point to nodes in the original list. + + For example, if there are two nodes X and Y in the original list, where + X.random + --> Y, then for the corresponding two nodes x and y in the copied list, + x.random + --> y. + + Return the head of the copied linked list. + + The linked list is represented in the input/output as a list of n nodes. Each + node is represented as a pair of [val, random_index] where: + + val: an integer representing Node.val + random_index: the index of the node (range from 0 to n-1) that the random + pointer points to, or null if it does not point to any node. + + Your code will only be given the head of the original linked list. +*/ + +struct Node { + int val; + struct Node *next; + struct Node *random; +}; + +int find_position(struct Node *head, struct Node *random) { + if (!random) + return -1; + struct Node *tmp = head; + int idx = 0; + while (tmp) { + if (tmp == random) + return idx; + idx++; + tmp = tmp->next; + } + return -1; +} + +struct Node *copy_step(struct Node *head, struct Node *new_table) { + struct Node *new_head = malloc(sizeof(struct Node)); + int cnt = 0; + new_head->val = head->val; + new_head->next = NULL; + struct Node *ptr = new_head, *tmp = head->next; + new_table[cnt] = ptr; + cnt++; + while (tmp) { + struct Node *n = malloc(sizeof(struct Node)); + n->val = tmp->val; + ptr->next = n; + ptr = n; + tmp = tmp->next; + new_table[cnt] = ptr; + cnt++; + } + ptr->next = NULL; + return new_head; +} + +struct Node *copyRandomList(struct Node *head) { + if (!head) + return NULL; + int random_idx[1000], cnt = 0; + struct Node *new_table[1000], *tmp = head; + while (tmp) { + random_idx[cnt] = find_position(head, tmp->random); + tmp = tmp->next; + cnt++; + } + struct Node *new_head = copy_step(head, new_table); + struct Node *new_tmp = new_head; + for (int i = 0; i < cnt; i++) { + if (random_idx[i] == -1) + new_tmp->random = NULL; + else + new_tmp->random = new_table[random_idx[i]]; + new_tmp = new_tmp->next; + } + return new_head; +} diff --git a/copy_list_rand_ptr.py b/copy_list_rand_ptr.py new file mode 100644 index 0000000..7909c0e --- /dev/null +++ b/copy_list_rand_ptr.py @@ -0,0 +1,60 @@ +# 138. Copy List with Random Pointer + +""" +A linked list of length n is given such that each node contains an additional +random pointer, which could point to any node in the list, or null. + +Construct a deep copy of the list. The deep copy should consist of exactly n +brand new nodes, where each new node has its value set to the value of its +corresponding original node. Both the next and random pointer of the new nodes +should point to new nodes in the copied list such that the pointers in the +original list and copied list represent the same list state. None of the +pointers in the new list should point to nodes in the original list. + +For example, if there are two nodes X and Y in the original list, where +X.random +--> Y, then for the corresponding two nodes x and y in the copied list, +x.random +--> y. + +Return the head of the copied linked list. + +The linked list is represented in the input/output as a list of n nodes. Each +node is represented as a pair of [val, random_index] where: + + val: an integer representing Node.val + random_index: the index of the node (range from 0 to n-1) that the random +pointer points to, or null if it does not point to any node. + +Your code will only be given the head of the original linked list. +""" + + +class Node: + def __init__(self, x, next=None, random=None): + self.val = int(x) + self.next = next + self.random = random + + +class Solution: + def copyRandomList(self, head): + cache = {} + new_ptr = curr = Node(-1) + while head: + if head in cache: + newnode = cache[head] + else: + newnode = Node(head.val) + cache[head] = newnode + new_ptr.next = newnode + new_ptr = new_ptr.next + if head.random: + if head.random in cache: + new_random = cache[head.random] + else: + new_random = Node(head.random.val) + cache[head.random] = new_random + new_ptr.random = new_random + head = head.next + return curr.next diff --git a/corresponding_node.cpp b/corresponding_node.cpp new file mode 100644 index 0000000..a5d758e --- /dev/null +++ b/corresponding_node.cpp @@ -0,0 +1,9 @@ +#include "leetcode.h" + +class Solution { +public: + TreeNode *getTargetCopy(TreeNode *original, TreeNode *clone, + TreeNode *target) {} +}; + +int main() {} diff --git a/cost_hire_k_worker.c b/cost_hire_k_worker.c new file mode 100644 index 0000000..bd1ba3c --- /dev/null +++ b/cost_hire_k_worker.c @@ -0,0 +1,195 @@ +// 2462. Total Cost to Hire K Workers +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given a 0-indexed integer array 'costs' where 'costs[i]' is the cost of + * hiring the i'th worker. you are also given two integers 'k, candidates'. we + * want to hire exactly 'k' workders according to the following rules: + * - you will run 'k' sessions and hire exactly one worker in each session + * - in each hiring session, choose the worker with the lowest cost from either + * the first 'candidates' workers or the last 'candidates' workers. break the + * tie by the smallest index. + * - if there are fewer than candidates workers remaining, choose the workder + * with the lowest cost among them. break the tie by the smallest index. + * - a worker can only be chosen once + * return the total cost to hire eactly 'k' workers. + */ + +typedef struct { + int val; + int idx; +} node; + +int cmp(const void *a, const void *b) { + node *A = *(node **)a; + node *B = *(node **)b; + return A->val - B->val; +} +void swap(node **a, node **b) { + node *tmp = *a; + *a = *b; + *b = tmp; +} +void modifyHeap(node **heap, int n) { + int f = 0; + while (1) { + int c1 = 2 * f + 1; + int c2 = 2 * f + 2; + if (c2 < n) { + if (heap[c1]->val <= heap[c2]->val) { + if (heap[c1]->val < heap[f]->val) { + swap(&heap[f], &heap[c1]); + f = c1; + } else + break; + } else { + if (heap[c2]->val < heap[f]->val) { + swap(&heap[f], &heap[c2]); + f = c2; + } else + break; + } + } else if (c1 < n) { + if (heap[c1]->val < heap[f]->val) { + swap(&heap[f], &heap[c1]); + f = c1; + } else + break; + } else + break; + } +} +int heapPop(node **heap, int *n) { + int ans = heap[0]->val; + *n = *n - 1; + heap[0] = heap[*n]; + + int f = 0; + int N = *n; + while (1) { + int c1 = 2 * f + 1; + int c2 = 2 * f + 2; + if (c2 < N) { + if (heap[c1]->val <= heap[c2]->val) { + if (heap[f]->val > heap[c1]->val) { + swap(&heap[f], &heap[c1]); + f = c1; + continue; + } else + break; + } else { + if (heap[f]->val > heap[c2]->val) { + swap(&heap[f], &heap[c2]); + f = c2; + continue; + } else + break; + } + } else if (c1 < N) { + if (heap[f]->val > heap[c1]->val) { + swap(&heap[f], &heap[c1]); + f = c1; + continue; + } else + break; + } else + break; + } + return ans; +} +long long totalCost(int *costs, int costsSize, int k, int candidates) { + int n = costsSize; + int left_cn = candidates; + int right_cn = candidates; + + if ((left_cn + right_cn) > n) { + left_cn = n / 2; + right_cn = n - n / 2; + } + + long long ans = 0; + if (k == costsSize) { + for (int i = 0; i < costsSize; i++) { + ans = ans + costs[i]; + } + return ans; + } + + bool *used = calloc(n, sizeof(bool)); + node **left = malloc(left_cn * sizeof(node *)); + node **right = malloc(right_cn * sizeof(node *)); + for (int i = 0; i < left_cn; i++) { + left[i] = malloc(sizeof(node)); + left[i]->val = costs[i]; + left[i]->idx = i; + used[i] = true; + } + for (int i = 0; i < right_cn; i++) { + right[i] = malloc(sizeof(node)); + right[i]->val = costs[n - 1 - i]; + right[i]->idx = n - 1 - i; + used[n - 1 - i] = true; + } + qsort(left, left_cn, sizeof(node *), cmp); + qsort(right, right_cn, sizeof(node *), cmp); + int l_idx = left_cn; + int r_idx = n - 1 - right_cn; + + int item = 0; + while (item < k) { + if (left_cn == 0) { + ans += heapPop(right, &right_cn); + item++; + continue; + } + if (right_cn == 0) { + ans += heapPop(left, &left_cn); + item++; + continue; + } + if (left[0]->val == right[0]->val && left[0]->idx == right[0]->idx) { + ans += left[0]->val; + heapPop(left, &left_cn); + heapPop(right, &right_cn); + } else if (left[0]->val <= right[0]->val) { + ans += left[0]->val; + if (used[l_idx]) + heapPop(left, &left_cn); + else { + left[0]->val = costs[l_idx]; + left[0]->idx = l_idx; + used[l_idx] = true; + l_idx++; + modifyHeap(left, left_cn); + } + } else { + ans += right[0]->val; + if (used[r_idx]) { + heapPop(right, &right_cn); + } else { + right[0]->val = costs[r_idx]; + right[0]->idx = r_idx; + used[r_idx] = true; + r_idx--; + modifyHeap(right, right_cn); + } + } + item++; + } + free(used); + for (int i = 0; i < right_cn; i++) + free(right[i]); + for (int i = 0; i < left_cn; i++) + free(left[i]); + free(left); + free(right); + return ans; +} + +int main() { + int c1[] = {17, 12, 10, 2, 7, 2, 11, 20, 8}, c2[] = {1, 2, 4, 1}; + printf("%lld\n", totalCost(c1, 9, 3, 4)); // expect: 11 + printf("%lld\n", totalCost(c2, 4, 3, 3)); // expect: 4 +} diff --git a/cost_hire_k_worker.cpp b/cost_hire_k_worker.cpp new file mode 100644 index 0000000..5bb0860 --- /dev/null +++ b/cost_hire_k_worker.cpp @@ -0,0 +1,48 @@ +// 2462. Total Cost to Hire K Workers +#include "leetcode.h" + +/* + * given a 0-indexed integer array 'costs' where 'costs[i]' is the cost of + * hiring the i'th worker. you are also given two integers 'k, candidates'. we + * want to hire exactly 'k' workders according to the following rules: + * - you will run 'k' sessions and hire exactly one worker in each session + * - in each hiring session, choose the worker with the lowest cost from either + * the first 'candidates' workers or the last 'candidates' workers. break the + * tie by the smallest index. + * - if there are fewer than candidates workers remaining, choose the workder + * with the lowest cost among them. break the tie by the smallest index. + * - a worker can only be chosen once + * return the total cost to hire eactly 'k' workers. + */ + +class Solution { +public: + long long totalCost(vector<int> &costs, int k, int candidates) { + int i = 0, j = costs.size() - 1; + priority_queue<int, vector<int>, greater<int>> pq1, pq2; + long long ans; + while (k--) { + while (pq1.size() < candidates && i <= j) + pq1.push(costs[i++]); + while (pq2.size() < candidates && i <= j) + pq2.push(costs[j--]); + int t1 = pq1.size() > 0 ? pq1.top() : INT_MAX; + int t2 = pq2.size() > 0 ? pq2.top() : INT_MAX; + if (t1 <= t2) { + ans += t1; + pq1.pop(); + } else { + ans += t2; + pq2.pop(); + } + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> c1 = {17, 12, 10, 2, 7, 2, 11, 20, 8}, c2 = {1, 2, 4, 1}; + printf("%lld\n", obj.totalCost(c1, 3, 4)); // expect: 11 + printf("%lld\n", obj.totalCost(c2, 3, 3)); // expect: 4 +} diff --git a/count_all_pickup_delivery.cpp b/count_all_pickup_delivery.cpp new file mode 100644 index 0000000..0d82d5a --- /dev/null +++ b/count_all_pickup_delivery.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" +#define lli long long int + +class Solution { +public: + int countOrders(int n) { + lli mod = 1e9 + 7; + vector<lli> dp(n + 2); + dp[1] = 1; + dp[2] = 6; + for (lli i = 3; i <= n; i++) { + lli x = 2 * i - 1; + lli combs = x * (x + 1) / 2; + dp[i] = (dp[i - 1] * combs) % mod; + } + return dp[n]; + } +}; + +int main() { + Solution obj; + cout << obj.countOrders(2); +} diff --git a/count_and_say.c b/count_and_say.c new file mode 100644 index 0000000..8d186fc --- /dev/null +++ b/count_and_say.c @@ -0,0 +1,68 @@ +// 38. Count and Say +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * the count-and-say sequence is a sequence of digit strings defined by the + * recursive formula: + * - countAndSay(1) = "1" + * - countAndSay(n) is the way you would "say" the digit string from + * 'countAndSay(n - 1)', which is then converted into a different digit string + * to determine how you "say" a digit string, split it into minimal number of + * substrings such that each substring contains exactly one unique digit. then + * for each substring, say the number of digits, then say the digit, finally, + * concatenate every said digit. given a positive integer 'n', return the n'th + * term of the count and say sequence. + */ + +char *int_to_char(int n) { + char *res = malloc(11); + res[10] = '\0'; + int idx = 9; + while (n) { + res[idx] = '0' + n % 10; + n /= 10; + idx--; + } + return &res[idx + 1]; +} + +char *countAndSay(int n) { + char *curr = malloc(5000), *post = malloc(5000); + curr[0] = '1'; + curr[1] = '\0'; + if (n == 1) + return curr; + for (int i = 2; i <= n; i++) { + int curr_len = strlen(curr), idx = 0, cnt = 1, pos = 0; + char *tmp; + for (int j = 1; j < curr_len; j++) { + if (curr[j] == curr[j - 1]) + cnt++; + else { + tmp = int_to_char(cnt); + strncpy(&post[pos], tmp, strlen(tmp)); + pos += strlen(tmp); + post[pos] = curr[j - 1]; + pos++; + cnt = 1; + } + } + tmp = int_to_char(cnt); + strncpy(&post[pos], tmp, strlen(tmp)); + pos += strlen(tmp); + post[pos] = curr[curr_len - 1]; + pos++; + post[pos] = '\0'; + tmp = curr; + curr = post; + post = tmp; + } + return curr; +} + +int main() { + printf("%s\n", countAndSay(1)); // expect: 1 + printf("%s\n", countAndSay(4)); // expect: 1211 +} diff --git a/count_and_say.cpp b/count_and_say.cpp new file mode 100644 index 0000000..a1086b4 --- /dev/null +++ b/count_and_say.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + string countAndSay(int n) { + if (n == 0) + return ""; + string ans = "1"; + while (--n) { + string curr = ""; + for (int i = 0; i < ans.size(); i++) { + int count = 1; + while ((i + 1 < ans.size()) && (ans[i] == ans[i + 1])) + count++, i++; + curr += to_string(count) + ans[i]; + } + ans = curr; + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.countAndSay(4); +} diff --git a/count_and_say.rs b/count_and_say.rs new file mode 100644 index 0000000..55a1fec --- /dev/null +++ b/count_and_say.rs @@ -0,0 +1,32 @@ +struct Solution; + +impl Solution { + pub fn count_and_say(n: i32) -> String { + if n == 1 { + return "1".to_string(); + } + let mut output: Vec<char> = vec![]; + let mut last_char = ' '; + let mut count: u8 = '0' as u8; + for char in Solution::count_and_say(n - 1).chars().into_iter() { + if last_char == ' ' { + last_char = char; + count = '1' as u8; + } else if char == last_char { + count += 1; + } else { + output.push(count as char); + output.push(last_char); + last_char = char; + count = '1' as u8; + } + } + output.push(count as char); + output.push(last_char); + output.into_iter().collect() + } +} + +fn main() { + print!("{}", Solution::count_and_say(4)); +} diff --git a/count_complete_tree_node.cpp b/count_complete_tree_node.cpp new file mode 100644 index 0000000..5929110 --- /dev/null +++ b/count_complete_tree_node.cpp @@ -0,0 +1,18 @@ +#include "leetcode.h" + +class Solution { +public: + int countNodes(TreeNode *root) { + if (!root) + return 0; + int l = 1, r = 1; + TreeNode *ptr_r = root, *ptr_l = root; + while (ptr_l = ptr_l->left) + l++; + while (ptr_r = ptr_r->right) + r++; + if (l == r) + return pow(2, l) - 1; + return 1 + countNodes(root->left) + countNodes(root->right); + } +}; diff --git a/count_complete_tree_node.rs b/count_complete_tree_node.rs new file mode 100644 index 0000000..4859862 --- /dev/null +++ b/count_complete_tree_node.rs @@ -0,0 +1,51 @@ +#[derive(Debug, PartialEq, Eq)] +pub struct TreeNode { + pub val: i32, + pub left: Option<RC<RefCell<TreeNode>>>, + pub right: Option<RC<RefCell<TreeNode>>> +} + +impl TreeNode { + #[inline] + pub fn new(val: i32) -> Self { + TreeNode { + val, + left: None, + right: None + } + } +} + +use std::rc::Rc; +use std::cell::RefCell; +impl Solution { + pub fn count_nodes(root: Option<Rc<RefCell<TreeNode>>>) -> i32 { + if let Some(r) = root { + let ld = { + let mut h = 1; + let mut node = r.borrow().left.clone(); + while let Some(n) = node { + h += 1; + node = n.borrow().left.clone(); + } + h + }; + let rd = { + let mut h = 1; + let mut node = r.borrow().right.clone(); + while let Some(n) = node { + h += 1; + node = n.borrow().right.clone(); + } + h + }; + if ld == rd { + 2i32.pow(ld) - 1 + } else { + 1 + Solution::count_nodes(r.borrow().left.clone()) + Solution::count_nodes(r.borrow().right.clone()) + } + } else { + 0 + } + } +} diff --git a/count_distinct_int.cpp b/count_distinct_int.cpp new file mode 100644 index 0000000..ff5c1d6 --- /dev/null +++ b/count_distinct_int.cpp @@ -0,0 +1,40 @@ +// 2442. Count Number of Distinct Integers After Reverse Operations +#include "leetcode.h" + +/* + * array nums contains positive integers + * take each integer in array and reverse its digits (eg. 13 -> 31) + * then *add* it to end of array. return number of distinct integers. + * [1,13,10,12,31] becomes [1,13,10,12,31,1,31,1,21,13] + * and total num of distinct ints = 6 + */ + +class Solution { +public: + int countDistinctIntegers(vector<int> &nums) { + // unordered set constructor to insert 'nums' + // note: a set only maintains unique values in it + unordered_set<int> us(nums.begin(), nums.end()); + // find reverse of every num + for (auto i : nums) { + int n = 0; + while (i) { + int rem = i % 10; + n = n * 10 + rem; + i /= 10; + } + // insert (to end) reverse + us.insert(n); + } + // we can simply return the size since + // every element in a set is unique + return us.size(); + } +}; + +int main() { + Solution obj; + vector<int> nums1 = {1, 13, 10, 12, 31}, nums2 = {2, 2, 2}; + cout << obj.countDistinctIntegers(nums1) << endl; // expect: 6 + cout << obj.countDistinctIntegers(nums2) << endl; // expect: 1 +} diff --git a/count_distinct_int.rs b/count_distinct_int.rs new file mode 100644 index 0000000..32ce622 --- /dev/null +++ b/count_distinct_int.rs @@ -0,0 +1,35 @@ +//2442. Count Number of Distinct Integers After Reverse Operations +use std::collections::HashSet; +struct Solution; + +/* + * array nums contains positive integers + * take each integer in array and reverse its digits (eg. 13 -> 31) + * then *add* it to end of array. return number of distinct integers. + * [1,13,10,12,31] becomes [1,13,10,12,31,1,31,1,21,13] + * and total num of distinct ints = 6 + */ + +impl Solution { + pub fn count_distinct_integers(nums: Vec<i32>) -> i32 { + let mut hs: HashSet<i32> = nums.iter().map(|&n| Self::reverse(n)).collect(); + hs.extend(nums.iter()); + hs.len() as i32 + } + fn reverse(mut n: i32) -> i32 { + let mut rev: i32 = 0; + while n > 0 { + rev *= 10; + rev += n % 10; + n /= 10; + } + rev + } +} + +fn main() { + let nums1 = vec![1,13,10,12,31]; + let nums2 = vec![2,2,2]; + println!("{}", Solution::count_distinct_integers(nums1)); //expect: 6 + println!("{}", Solution::count_distinct_integers(nums2)); //expect: 1 +} diff --git a/count_element_max_freq.c b/count_element_max_freq.c new file mode 100644 index 0000000..92f0128 --- /dev/null +++ b/count_element_max_freq.c @@ -0,0 +1,29 @@ +// 3005. Count Elements With Maximum Frequency +#include "leetcode.h" + +/* + * given an array 'nums' consisting of positive integers. return the total + * frequencies of elements in 'nums' such that those elements all have the + * maximum frequency. the frequency of an element is the number of occurences of + * that in the array + */ + +int maxFrequencyElements(int *nums, int nums_size) { + int *u_map = (int *)calloc(101, sizeof(int)), max_freq = 0, cnt = 0; + for (int i = 0; i < nums_size; i++) + u_map[nums[i]]++; + for (int i = 0; i < 101; ++i) + if (u_map[i] > max_freq) + max_freq = u_map[i]; + for (int i = 0; i < 101; i++) + if (u_map[i] == max_freq) + cnt += u_map[i]; + free(u_map); + return cnt; +} + +int main() { + int n1[] = {1, 2, 2, 3, 1, 4}, n2[] = {1, 2, 3, 4, 5}; + printf("%d\n", maxFrequencyElements(n1, ARRAY_SIZE(n1))); // expect: 4 + printf("%d\n", maxFrequencyElements(n2, ARRAY_SIZE(n2))); // expect: 5 +} diff --git a/count_element_max_freq.py b/count_element_max_freq.py new file mode 100644 index 0000000..5c8e6b2 --- /dev/null +++ b/count_element_max_freq.py @@ -0,0 +1,33 @@ +# 3005. Count Elements With Maximum Frequency + +""" +given an array 'nums' consisting of positive integers. return the total +frequencies of elements in 'nums' such that those elements all have the +maximum frequency. the frequency of an element is the number of occurences of +that in the array +""" + + +class Solution(object): + def maxFrequencyElements(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + u_map = {} + for i in nums: + u_map[i] = u_map.get(i, 0) + 1 + max_i = 0 + for key, val in u_map.items(): + max_i = max(max_i, val) + ans = 0 + for key, val in u_map.items(): + if val == max_i: + ans += val + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxFrequencyElements([1, 2, 2, 3, 1, 4])) + print(obj.maxFrequencyElements([1, 2, 3, 4, 5])) diff --git a/count_element_smaller_great.c b/count_element_smaller_great.c new file mode 100644 index 0000000..2c21fbd --- /dev/null +++ b/count_element_smaller_great.c @@ -0,0 +1,37 @@ +// 2148. Count Elements With Strictly Smaller and Greater Elements +#include <stdio.h> +#include <stdlib.h> + +/* + * given integer array 'nums', return number of elements that have both a + * strictly smaller and strictly greater element appear in 'nums' + */ + +int cmp(const void *a, const void *b) { + return *(const int *)a - *(const int *)b; +} + +int countElements(int *nums, int numsSize) { + if (numsSize == 1) + return 0; + qsort(nums, numsSize, sizeof(int), cmp); + int ans = 0; + for (int i = 1; i + 1 < numsSize; i++) { + int front = i + 1, back = i - 1; + if (nums[i] == nums[back]) + while (back > 0 && nums[i] == nums[back]) + back--; + if (nums[i] == nums[front]) + while (front < numsSize - 1 && nums[i] == nums[front]) + front++; + if (nums[i] < nums[front] && nums[i] > nums[back]) + ans++; + } + return ans; +} + +int main() { + int nums1[] = {11, 7, 2, 15}, nums2[] = {-3, 3, 3, 90}; + printf("%d\n", countElements(nums1, 4)); // expect: 2 + printf("%d\n", countElements(nums2, 4)); // expect: 2 +} diff --git a/count_good_nodes_bst.cpp b/count_good_nodes_bst.cpp new file mode 100644 index 0000000..b6b9b3e --- /dev/null +++ b/count_good_nodes_bst.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + int goodNodes(TreeNode *root) { + dfs(root, root->val); + return count; + } + +private: + int count = 0; + void dfs(TreeNode *node, int currMax) { + if (!node) + return; + if (node->val >= currMax) { + count++; + currMax = node->val; + } + dfs(node->left, currMax); + dfs(node->right, currMax); + } +}; diff --git a/count_good_numbers.c b/count_good_numbers.c new file mode 100644 index 0000000..86432c4 --- /dev/null +++ b/count_good_numbers.c @@ -0,0 +1,32 @@ +// 1922. Count Good Numbers +#include "leetcode.h" + +/* + * a digit string is good if the digits (0-indexed) at even indices are even and + * the digits at odd indices are prime (2,3,5,or 7). for example 2582 is good + * because the digits 2 and 8 at even positions are even and the digits 5 and 2 + * at odd positions are prime. however, 3245 is not good because 3 is at an even + * index, but is not even. given an integer 'n', return the total number of good + * digit strings of length 'n'. since the answer may be large, return it modulo + * 1e9+7. a digit string is a string consisting of digits 0 through 9 that may + * contain leading zeros. + */ + +const int MOD = 1e9 + 7; + +long long _pow(long long a, long long b) { + if (!b) + return 1; + return b % 2 ? a * _pow(a, b - 1) % MOD : _pow((a * a) % MOD, b / 2); +} + +int countGoodNumbers(long long n) { + long long odd = n / 2, even = n - odd; + return _pow(20, odd) * ((n % 2) ? 5 : 1) % MOD; +} + +int main() { + printf("%d\n", countGoodNumbers(1)); // expect: 5 + printf("%d\n", countGoodNumbers(4)); // expect: 400 + printf("%d\n", countGoodNumbers(50)); // expect: 564908303 +} diff --git a/count_good_numbers.py b/count_good_numbers.py new file mode 100644 index 0000000..93455c9 --- /dev/null +++ b/count_good_numbers.py @@ -0,0 +1,31 @@ +# 1922. Count Good Numbers + +""" +a digit string is good if the digits (0-indexed) at even indices are even and +the digits at odd indices are prime (2,3,5,or 7). for example 2582 is good +because the digits 2 and 8 at even positions are even and the digits 5 and 2 +at odd positions are prime. however, 3245 is not good because 3 is at an even +index, but is not even. given an integer 'n', return the total number of good +digit strings of length 'n'. since the answer may be large, return it modulo +1e9+7. a digit string is a string consisting of digits 0 through 9 that may +contain leading zeros. +""" + + +class Solution(object): + def countGoodNumbers(self, n): + """ + :type n: int + :rtype: int + """ + cnt, x = 5 ** (n % 2), 20 + for _ in range(n // 2): + cnt = cnt * x % (10**9 + 7) + return cnt + + +if __name__ == "__main__": + obj = Solution() + print(obj.countGoodNumbers(1)) + print(obj.countGoodNumbers(4)) + print(obj.countGoodNumbers(50)) diff --git a/count_interest_subarr.c b/count_interest_subarr.c new file mode 100644 index 0000000..bcea6ca --- /dev/null +++ b/count_interest_subarr.c @@ -0,0 +1,22 @@ +// 2845. Count of Interesting Subarrays +#include <stdio.h> +#include <stdlib.h> + +/* + * given a 0-indexed integer array 'nums' an integer 'modulo' and an integer + * 'k'. your task is to find the count of subarrays that are interesting. a + * subarray 'nums[l...r]' is interesting if the following condition holds: let + * 'cnt' be the number of indices 'i' in the range '[l, r]' such that 'nums[i] + * % modulo == k'. then 'cnt % modulo == k'. return an integer denoting thecount + * of interesting subarrays. note a subarray is contiguous non-empty sequence of + * elements within an array. + */ + +long long countInterestingSubarrays(int *nums, int nums_size, int modulo, + int k) {} + +int main() { + int n1[] = {3, 2, 4}, n2[] = {3, 1, 9, 6}; + printf("%lld\n", countInterestingSubarrays(n1, 3, 2, 1)); // expect: 3 + printf("%lld\n", countInterestingSubarrays(n2, 4, 3, 0)); // expect: 2 +} diff --git a/count_interest_subarr.py b/count_interest_subarr.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/count_interest_subarr.py diff --git a/count_ints_even_sum.c b/count_ints_even_sum.c new file mode 100644 index 0000000..237c840 --- /dev/null +++ b/count_ints_even_sum.c @@ -0,0 +1,27 @@ +// 2180. Count Integers With Even Digit Sum +#include <stdio.h> + +/* + * given a positive integer 'num', return the number of positive integersless + * than or equal to 'num' whose digit sums are event. the digitsum of a positive + * integer is the sum of all of its digits. + */ + +int countEven(int num) { + int ans = 0; + for (int i = 1; i <= num; i++) { + int val = i, d = 0; + while (val) { + d += val % 10; + val /= 10; + } + if (d % 2 == 0) + ans++; + } + return ans; +} + +int main() { + printf("%d\n", countEven(4)); // expect: 2 + printf("%d\n", countEven(30)); // expect: 14 +} diff --git a/count_ints_even_sum.cpp b/count_ints_even_sum.cpp new file mode 100644 index 0000000..83070c6 --- /dev/null +++ b/count_ints_even_sum.cpp @@ -0,0 +1,26 @@ +// 2180. Count Integers With Even Digit Sum +#include "leetcode.h" + +/* + * given a positive integer 'num', return the number of positive integersless + * than or equal to 'num' whose digit sums are event. the digitsum of a positive + * integer is the sum of all of its digits. + */ + +class Solution { +public: + int countEven(int num) { + int tmp = num, sum = 0; + while (num > 0) { + sum += num % 10; + num /= 10; + } + return sum % 2 == 0 ? tmp / 2 : (tmp - 1) / 2; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.countEven(4)); // expect: 2 + printf("%d\n", obj.countEven(30)); // expect: 14 +} diff --git a/count_matches_tournament.c b/count_matches_tournament.c new file mode 100644 index 0000000..ea10103 --- /dev/null +++ b/count_matches_tournament.c @@ -0,0 +1,30 @@ +// 1688. Count of Matches in Tournament +#include "leetcode.h" +#include <stdio.h> + +/* + * given an integer 'n', the number of teams in a tournament that has strange + * rules: if the current number of teams is even, each team get paired with + * another team. a total of 'n / 2' matches are played, and 'n / 2' teams + * advance to the next round. if the current number of teams is odd, one team + * randomly advances in the tournament and the rest gets paired. a total of '(n + * - 1) / 2' matches are played, and '(n - 1) / 2 + 1' teams advance to the next + * round. return the number of matches played in the tournament until a winner + * is decided + */ + +int numberOfMatches(int n) { + int ans = 0; + while (n > 1) { + int tmp = !(n % 2) ? n / 2 : (n - 1) / 2; + ans += tmp; + n -= tmp; + } + return ans; +} + +int main() { + printf("%d\n", numberOfMatches(7)); // expect: 6 + printf("%d\n", numberOfMatches(14)); // expect: 13 + printf("%d\n", numberOfMatches(28)); // expect: 27 +} diff --git a/count_matches_tournament.py b/count_matches_tournament.py new file mode 100644 index 0000000..124f5c3 --- /dev/null +++ b/count_matches_tournament.py @@ -0,0 +1,32 @@ +# 1688. Count of Matches in Tournament + +""" +given an integer 'n', the number of teams in a tournament that has strange +rules: if the current number of teams is even, each team get paired with +another team. a total of 'n / 2' matches are played, and 'n / 2' teams +advance to the next round. if the current number of teams is odd, one team +randomly advances in the tournament and the rest gets paired. a total of '(n +- 1) / 2' matches are played, and '(n - 1) / 2 + 1' teams advance to the next +round. return the number of matches played in the tournament until a winner +is decided +""" + + +class Solution(object): + def numberOfMatches(self, n): + """ + :type n: int + :rtype: int + """ + ans = 0 + while n > 1: + ans += n // 2 + n = (n + 1) // 2 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.numberOfMatches(7)) # expect: 6 + print(obj.numberOfMatches(14)) # expect: 13 + print(obj.numberOfMatches(672)) # expect: 671 diff --git a/count_negative_num_matrix.c b/count_negative_num_matrix.c new file mode 100644 index 0000000..e91de57 --- /dev/null +++ b/count_negative_num_matrix.c @@ -0,0 +1,49 @@ +// 1351. Count Negative Numbers in a Sorted Matrix +#include <stdio.h> + +// given an 'm x n' matrix 'grid' which is sorted in non-increasing order both +// row-wise and column-wise, return the number of negative numbers in 'grid' + +void search(int **grid, int grid_size, int row, int start, int end, int *ans) { + while (start < end) { + int mid = start + (end - start) / 2; + if (grid[row][mid] >= 0) { + start = mid + 1; + if (grid[row][start] < 0) { + (*ans) += grid_size - start; + return; + } + } else { + end = mid; + } + } +} + +int countNegatives(int **grid, int grid_size, int *grid_col_size) { + if (grid_size == 1 && grid_col_size[0] == 1) + return grid[0][0] < 0 ? 1 : 0; + int r_size = grid_size, c_size = grid_col_size[0], r_idx = 0, ans = 0; + for (int r = r_size - 1; r >= 0; r--) { + if (grid[r][0] >= 0) { + r_idx = r; + ans = (r_size - r_idx - 1) * c_size; + break; + } + } + for (int r = 0; r <= r_idx; r++) { + if (grid[r][c_size - 1] >= 0) + continue; + search(grid, c_size, r, 0, c_size - 1, &ans); + } + return ans; +} + +int main() { + int g1[4][4] = { + {4, 3, 2, -1}, {3, 2, 1, -1}, {1, 1, -1, -2}, {-1, -1, -2, -3}}; + int g2[2][2] = {{3, 2}, {1, 0}}; + int gs1 = 4, gs2 = 2; + int *gcs1, *gcs2; + printf("%d\n", countNegatives(g1, gs1, gcs1)); // expect: 8 + printf("%d\n", countNegatives(g2, gs2, gcs2)); // expect: 0 +} diff --git a/count_negative_num_matrix.cpp b/count_negative_num_matrix.cpp new file mode 100644 index 0000000..2496cf8 --- /dev/null +++ b/count_negative_num_matrix.cpp @@ -0,0 +1,37 @@ +// 1351. Count Negative Numbers in a Sorted Matrix +#include "leetcode.h" + +// given an 'm x n' matrix 'grid' which is sorted in non-increasing order both +// row-wise and column-wise, return the number of negative numbers in 'grid' + +class Solution { +public: + int countNegatives(vvd(int) & grid) { + int ans = 0; + for (vector<int> row : grid) + for (int i : row) + if (i < 0) + ans++; + return ans; + for (vector<int> row : grid) + ans += upper_bound(row.rbegin(), row.rend(), -1) - row.rbegin(); + return ans; + int m = grid.size(), n = grid[0].size(), r = 0, c = n - 1; + while (r < m) { + while (c >= 0 && grid[r][c] < 0) + c--; + ans += n - c - 1; + r++; + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) + g1 = {{4, 3, 2, -1}, {3, 2, 1, -1}, {1, 1, -1, -2}, {-1, -1, -2, -3}}; + vvd(int) g2 = {{3, 2}, {1, 0}}; + printf("%d\n", obj.countNegatives(g1)); // expect: 8 + printf("%d\n", obj.countNegatives(g2)); // expect: 0 +} diff --git a/count_nice_pair.c b/count_nice_pair.c new file mode 100644 index 0000000..6a335c0 --- /dev/null +++ b/count_nice_pair.c @@ -0,0 +1,53 @@ +// 1814. Count Nice Pairs in an Array +#include "leetcode.h" + +/* + * given an array 'nums' that consists of non-negative integers. let us define + * 'rev(x)' as the reverse of the non-negative integer 'x'. for example, + * 'rev(123) = 321' and 'rev(120) = 21'. a pair of indices '(i, j)' is nice if + * it satisfies all of the following conditions: '0 <= i < j < nums.length' and + * 'nums[i] + rev(nums[j]) == nums[j] + rev(nums[i])'. return the number of nice + * pairs of indices. since that number be very large, return it modulo 1e9+7 + */ + +int reverse(int val) { + int res = 0; + while (val) { + res *= (10 + val % 10); + val /= 10; + } + return res; +} + +int countNicePairs(int *nums, int nums_size) { + int n = nums_size, mod = 1e9 + 7, ans = 0; + int **hash = calloc(n, sizeof(int *)); + for (int i = 0; i < n; i++) { + int r = reverse(nums[i]); + int diff = r - nums[i]; + int d = abs(diff); + while (1) { + if (!hash[d % n]) { + hash[d % n] = malloc(2 * sizeof(int)); + hash[d % n][0] = diff; + hash[d % n][1] = 1; + break; + } else { + if (hash[d % n][0] == diff) { + ans = (ans + hash[d % n][1]) % mod; + hash[d % n][1]++; + break; + } else { + d++; + } + } + } + } + return ans; +} + +int main() { + int n1[] = {42, 11, 1, 97}, n2[] = {13, 10, 35, 24, 76}; + printf("%d\n", countNicePairs(n1, ARRAY_SIZE(n1))); // expect: 2 + printf("%d\n", countNicePairs(n2, ARRAY_SIZE(n2))); // expect: 2 +} diff --git a/count_nice_pair.py b/count_nice_pair.py new file mode 100644 index 0000000..e3d7ecf --- /dev/null +++ b/count_nice_pair.py @@ -0,0 +1,32 @@ +# 1814. Count Nice Pairs in an Array +import collections + +""" +given an array 'nums' that consists of non-negative integers. let us define +'rev(x)' as the reverse of the non-negative integer 'x'. for example, +'rev(123) = 321' and 'rev(120) = 21'. a pair of indices '(i, j)' is nice if +it satisfies all of the following conditions: '0 <= i < j < nums.length' and +'nums[i] + rev(nums[j]) == nums[j] + rev(nums[i])'. return the number of nice +pairs of indices. since that number be very large, return it modulo 1e9+7 +""" + + +class Solution(object): + def countNicePairs(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + ans = 0 + cnt = collections.Counter() + for i in nums: + b = int(str(i)[::-1]) + ans += cnt[i - b] + cnt[i - b] += 1 + return ans % (10**9 + 7) + + +if __name__ == "__main__": + obj = Solution() + print(obj.countNicePairs([42, 11, 1, 97])) # expect: 2 + print(obj.countNicePairs([13, 10, 35, 24, 76])) # expect: 4 diff --git a/count_num_fair_pairs.c b/count_num_fair_pairs.c new file mode 100644 index 0000000..80d26f1 --- /dev/null +++ b/count_num_fair_pairs.c @@ -0,0 +1,57 @@ +// 2563. Count the Number of Fair Pairs +#include "leetcode.h" + +/* + * given a 0 indexed integer array 'nums' of size 'n', and two integers 'lower' + * and 'upper', return the number of fair pairs. pair '(i, j)' is fair is '0 <= + * i < j < n' and 'lower <= nums[i] + nums[j] <= upper' + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int bs_lower(int *nums, int n, int left, int right, int lower) { + int l = left, r = right; + if (nums[r] < lower) + return -1; + while (l < r) { + int m = l + (r - l) / 2; + if (nums[m] < lower) + l = m + 1; + else + r = m; + } + return l; +} + +int bs_upper(int *nums, int n, int left, int right, int upper) { + int l = left, r = right; + if (nums[l] > upper) + return -1; + while (l < r) { + int m = r - (r - l) / 2; + if (nums[m] > upper) + r = m - 1; + else + l = m; + } + return l; +} + +long long countFairPairs(int *nums, int numsSize, int lower, int upper) { + int n = numsSize; + long long ans = 0; + qsort(nums, n, sizeof(int), cmp); + for (int i = 0; i < n - 1; i++) { + int left = bs_lower(nums, n, i + 1, n - 1, lower - nums[i]); + int right = bs_upper(nums, n, i + 1, n - 1, upper - nums[i]); + if (left != -1 && right != -1) + ans += right - left + 1; + } + return ans; +} + +int main() { + int n1[] = {0, 1, 7, 4, 4, 5}, n2[] = {1, 7, 9, 2, 5}; + printf("%lld\n", countFairPairs(n1, ARRAY_SIZE(n1), 3, 6)); // expect: 6 + printf("%lld\n", countFairPairs(n2, ARRAY_SIZE(n2), 11, 11)); // expect: 1 +} diff --git a/count_num_fair_pairs.py b/count_num_fair_pairs.py new file mode 100644 index 0000000..5933dbd --- /dev/null +++ b/count_num_fair_pairs.py @@ -0,0 +1,32 @@ +# 2563. Count the Number of Fair Pairs +import bisect + +""" +given a 0 indexed integer array 'nums' of size 'n', and two integers 'lower' +and 'upper', return the number of fair pairs. pair '(i, j)' is fair is '0 <= +i < j < n' and 'lower <= nums[i] + nums[j] <= upper' +""" + + +class Solution(object): + def countFairPairs(self, nums, lower, upper): + """ + :type nums: List[int] + :type lower: int + :type upper: int + :rtype: int + """ + nums.sort() + ans = 0 + for i in range(len(nums) - 1, -1, -1): + v = nums[i] + a = bisect.bisect_left(nums, lower - v, lo=0, hi=i) + b = bisect.bisect_right(nums, upper - v, lo=0, hi=i) + ans += b - a + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.countFairPairs(nums=[0, 1, 7, 4, 4, 5], lower=3, upper=6)) + print(obj.countFairPairs(nums=[1, 7, 9, 2, 5], lower=11, upper=11)) diff --git a/count_num_homogenous_substrings.c b/count_num_homogenous_substrings.c new file mode 100644 index 0000000..1c66ae2 --- /dev/null +++ b/count_num_homogenous_substrings.c @@ -0,0 +1,32 @@ +// 1759. Count Number of Homogenous Substrings +#include "leetcode.h" + +/* + * given a string 's', return the number of homogenous substrings of 's'. since + * thhe answer may be very large, return it modulo 10^9+7. a string is + * homogenous if all the characters of the string are the same. a substring is a + * continuous sequence of chharacters within a string. + */ + +int countHomogenous(char *s) { + int ans = 0, mod = 1e9 + 7, n = strlen(s), cnt = 1; + for (int i = 1; i < n; i++) { + if (s[i] == s[i - 1]) + cnt++; + else { + long val = (1 + cnt) * cnt / 2; + ans = (ans + val % mod) % mod; + cnt = 1; + } + } + long long val = (long long)(1 + cnt) * cnt / 2; + ans = (ans + val % mod) % mod; + return ans; +} + +int main() { + char s1[] = {"abbcccaa"}, s2[] = {"xy"}, s3[] = {"zzzzz"}; + printf("%d\n", countHomogenous(s1)); // expect: 13 + printf("%d\n", countHomogenous(s2)); // expect: 2 + printf("%d\n", countHomogenous(s3)); // expect: 15 +} diff --git a/count_num_homogenous_substrings.py b/count_num_homogenous_substrings.py new file mode 100644 index 0000000..7d2b7eb --- /dev/null +++ b/count_num_homogenous_substrings.py @@ -0,0 +1,24 @@ +# 1759. Count Number of Homogenous Substrings + +""" +given a string 's', return the number of homogenous substrings of 's'. since +thhe answer may be very large, return it modulo 10^9+7. a string is +homogenous if all the characters of the string are the same. a substring is a +continuous sequence of chharacters within a string. +""" + + +class Solution(object): + def countHomogenous(self, s): + ans = 0 + for c, s in groupby(s): + n = len(list(s)) + ans += n * (n + 1) / 2 + return ans % (10**9 + 7) + + +if __name__ == "__main__": + obj = Solution() + print(obj.countHomogenous("abbcccaa")) # expect: 13 + print(obj.countHomogenous("xy")) # expect: 2 + print(obj.countHomogenous("zzzzz")) # expect: 15 diff --git a/count_num_nice_subarr.c b/count_num_nice_subarr.c new file mode 100644 index 0000000..33482c3 --- /dev/null +++ b/count_num_nice_subarr.c @@ -0,0 +1,35 @@ +// 1248. Count Number of Nice Subarrays +#include "leetcode.h" + +/* + * given an array of integers 'nums' and an integers 'k'. a continuous subarray + * is called nice if there are 'k' odd numbers on it. return the number of nice + * subarrays. + */ + +int process(int *nums, int numsSize, int k) { + int odd_cnt = 0, r = 0, l = 0, ans = 0; + for (; r < numsSize; r++) { + if (nums[r] % 2) + odd_cnt++; + while (odd_cnt > k) { + if (nums[l] % 2) + odd_cnt--; + l++; + } + ans += r - l + 1; + } + return ans; +} + +int numberOfSubarrays(int *nums, int numsSize, int k) { + return process(nums, numsSize, k) - process(nums, numsSize, k - 1); +} + +int main() { + int n1[] = {1, 1, 2, 1, 1}, n2[] = {2, 4, 6}, + n3[] = {2, 2, 2, 1, 2, 2, 1, 2, 2, 2}; + printf("%d\n", numberOfSubarrays(n1, ARRAY_SIZE(n1), 3)); // expect: 2 + printf("%d\n", numberOfSubarrays(n2, ARRAY_SIZE(n2), 1)); // expect: 0 + printf("%d\n", numberOfSubarrays(n3, ARRAY_SIZE(n3), 2)); // expect: 16 +} diff --git a/count_num_nice_subarr.py b/count_num_nice_subarr.py new file mode 100644 index 0000000..de30423 --- /dev/null +++ b/count_num_nice_subarr.py @@ -0,0 +1,34 @@ +# 1248. Count Number of Nice Subarrays + +""" +given an array of integers 'nums' and an integers 'k'. a continuous subarray +is called nice if there are 'k' odd numbers on it. return the number of nice +subarrays. +""" + + +class Solution(object): + def numberOfSubarrays(self, nums, k): + """ + :type nums: List[int] + :type k: int + :rtype: int + """ + i, cnt, ans = 0, 0, 0 + for j in range(len(nums)): + if nums[j] & 1: + k -= 1 + cnt = 0 + while k == 0: + k += nums[i] & 1 + i += 1 + cnt += 1 + ans += cnt + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.numberOfSubarrays(nums=[1, 1, 2, 1, 1], k=3)) + print(obj.numberOfSubarrays(nums=[2, 4, 6], k=1)) + print(obj.numberOfSubarrays(nums=[2, 2, 2, 1, 2, 2, 1, 2, 2, 2], k=2)) diff --git a/count_num_teams.c b/count_num_teams.c new file mode 100644 index 0000000..f8853d5 --- /dev/null +++ b/count_num_teams.c @@ -0,0 +1,38 @@ +// 1395. Count Number of Teams +#include <stdio.h> +#include <stdlib.h> + +/* + * there are 'n' soldiers standing in a line. each soldier is assigned a unique + * 'rating' value. you have to form a team of 3 soldiers amongst them under the + * following rules + * - choose 3 soldiers with index '(i, j, k)' with rating '(rating[i], + * rating[j], rating[k])' + * - a team is valid if '(rating[i] < rating[j] < rating[k])' or '(rating[i] > + * rating[j] > rating[k])' where '(0 <= i < j < k < n))' return the number of + * teams you can form given the conditions (soldiers can be part of multiple + * teams) + */ + +int numTeams(int *rating, int rating_size) { + int ans = 0, la, lb, ra, rb; + for (int i = 1; i < rating_size - 1; i++) { + la = 0, ra = 0; + for (int j = 0; j < i; j++) + if (rating[j] < rating[i]) + la++; + lb = i - la; + for (int k = i + 1; k < rating_size; k++) + if (rating[i] < rating[k]) + ra++; + rb = rating_size - 1 - i - ra; + ans = ans + la * ra + lb * rb; + } + return ans; +} + +int main() { + int r1[] = {2, 5, 3, 4, 1}, r2[] = {2, 1, 3}; + printf("%d\n", numTeams(r1, 5)); // expect: 3 + printf("%d\n", numTeams(r2, 3)); // expect: 0 +} diff --git a/count_odd_num_interval_range.c b/count_odd_num_interval_range.c new file mode 100644 index 0000000..e8a80f3 --- /dev/null +++ b/count_odd_num_interval_range.c @@ -0,0 +1,21 @@ +// 1523. Count Odd Numbers in an Interval Range +#include <math.h> +#include <stdio.h> + +// given two non-negative integers 'low' and 'high' return the +// count of odd numbers * between 'low' and 'high' (incusively) + +int countOdds(int low, int high) { + int ans = 0; + if (low % 2) { + ans += (high - low) / 2; + ans++; + } else + ans += (double)ceil((high - low) / 2.0); + return ans; +} + +int main() { + printf("%d\n", countOdds(3, 7)); // expect: 3 + printf("%d\n", countOdds(8, 10)); // expect: 1 +} diff --git a/count_odd_num_interval_range.cpp b/count_odd_num_interval_range.cpp new file mode 100644 index 0000000..f690d01 --- /dev/null +++ b/count_odd_num_interval_range.cpp @@ -0,0 +1,24 @@ +// 1523. Count Odd Numbers in an Interval Range +#include "leetcode.h" + +// given two non-negative integers 'low' and 'high' return the +// count of odd numbers * between 'low' and 'high' (incusively) + +class Solution { +public: + int countOdds(int low, int high) { + int ans = 0; + if (low % 2) { + ans += (high - low) / 2; + ans++; + } else + ans += ceil(double(high - low) / 2.0); + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.countOdds(3, 7) << endl; // expect: 3 + cout << obj.countOdds(8, 10) << endl; // expect: 1 +} diff --git a/count_possible_routes.c b/count_possible_routes.c new file mode 100644 index 0000000..59ae340 --- /dev/null +++ b/count_possible_routes.c @@ -0,0 +1,52 @@ +// 1575. Count All Possible Routes +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array of disticnt positive integers locations where 'locations[i]' + * represents the position of city 'i'. you are lso given integers 'start, + * finish, fuel' representing the starting city, ending city, and the initial + * amount of fuel you have, respectively. at each step if you are in city 'i', + * you can pick any city 'j' such that 'j != i' and '0 <= j < locations.length' + * and move to city 'j'. moving city 'i' to 'j' reduces the amount of fuel you + * have by |locations[i] - locations[j]|. Please notice that |x| denotes the + * absolute value of x. notice that fuel cannot become negative at any point in + * time. and that are allowed to visit any city more than once (including + * 'start' and 'finish'). return the count of all possible routes from 'start' + * to 'finish'. since the answer may be large, return it modulo 10^9+7. + */ + +#define MOD 1000000007 + +int solve(int *locations, int locations_size, int start, int finish, int fuel, + int **memo) { + if (fuel < 0) + return 0; + if (memo[start][fuel] != -1) + return memo[start][fuel]; + int ans = start == finish ? 1 : 0; + for (int i = 0; i < locations_size; i++) + if (start != i) + ans = (ans + solve(locations, locations_size, i, finish, + fuel - abs(locations[i] - locations[start]), memo)) % + MOD; + return memo[start][fuel] = ans; +} + +int countRoutes(int *locations, int locations_size, int start, int finish, + int fuel) { + int ans = 0; + int **memo = (int **)malloc(sizeof(int *) * locations_size); + for (int i = 0; i < locations_size; i++) { + memo[i] = (int *)malloc(sizeof(int) * (fuel + 1)); + for (int j = 0; j <= fuel; j++) + memo[i][j] = -1; + } + return solve(locations, locations_size, start, finish, fuel, memo); +} + +int main() { + int l1[] = {2, 3, 6, 8, 4}, l2[] = {4, 3, 1}; + printf("%d\n", countRoutes(l1, 5, 1, 3, 5)); // expect: 4 + printf("%d\n", countRoutes(l2, 3, 1, 0, 6)); // expect: 5 +} diff --git a/count_possible_routes.cpp b/count_possible_routes.cpp new file mode 100644 index 0000000..3ab5f17 --- /dev/null +++ b/count_possible_routes.cpp @@ -0,0 +1,42 @@ +// 1575. Count All Possible Routes +#include "leetcode.h" + +/* + * given an array of disticnt positive integers locations where 'locations[i]' + * represents the position of city 'i'. you are lso given integers 'start, + * finish, fuel' representing the starting city, ending city, and the initial + * amount of fuel you have, respectively. at each step if you are in city 'i', + * you can pick any city 'j' such that 'j != i' and '0 <= j < locations.length' + * and move to city 'j'. moving city 'i' to 'j' reduces the amount of fuel you + * have by |locations[i] - locations[j]|. Please notice that |x| denotes the + * absolute value of x. notice that fuel cannot become negative at any point in + * time. and that are allowed to visit any city more than once (including + * 'start' and 'finish'). return the count of all possible routes from 'start' + * to 'finish'. since the answer may be large, return it modulo 10^9+7. + */ + +class Solution { +public: + int countRoutes(vector<int> &locations, int start, int finish, int fuel) { + int n = locations.size(), mod = 1e9 + 7, ans = 0; + vvd(int) dp(n, vector<int>(fuel + 1)); + dp[start][fuel] = 1; + for (int f = fuel; f >= 0; f--) + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) { + int diff = abs(locations[i] - locations[j]); + if (i != j && f >= diff) + dp[j][f - diff] = (dp[j][f - diff] % mod + dp[i][f] % mod) % mod; + } + for (int i = 0; i <= fuel; i++) + ans = (ans % mod + dp[finish][i] % mod) % mod; + return ans; + } +}; + +int main() { + Solution obj; + vector<int> l1 = {2, 3, 6, 8, 4}, l2 = {4, 3, 1}; + printf("%d\n", obj.countRoutes(l1, 1, 3, 5)); // expect: 4 + printf("%d\n", obj.countRoutes(l2, 1, 0, 6)); // expect: 5 +} diff --git a/count_primes.c b/count_primes.c new file mode 100644 index 0000000..7d02add --- /dev/null +++ b/count_primes.c @@ -0,0 +1,34 @@ +// 204. Count Primes +#include "leetcode.h" + +/* + * given an integer 'n', return the number of prime numbers that are strictly + * less than 'n'. + */ + +int countPrimes(int n) { + if (n < 2) + return 0; + if (n == 3) + return 1; + bool *table = (bool *)calloc(n, sizeof(bool)); + table[0] = table[1] = 1; + for (int i = 2; i <= sqrt(n); i++) { + if (table[i]) + continue; + for (int j = i * i; j < n; j += i) + table[j] = 1; + } + int ans = 0; + for (int i = 2; i < n; i++) + if (!table[i]) + ans++; + free(table); + return ans; +} + +int main() { + printf("%d\n", countPrimes(10)); // expect: 4 + printf("%d\n", countPrimes(0)); // expect: 0 + printf("%d\n", countPrimes(1)); // expect: 0 +} diff --git a/count_primes.py b/count_primes.py new file mode 100644 index 0000000..e0d496a --- /dev/null +++ b/count_primes.py @@ -0,0 +1,29 @@ +# 204. Count Primes + +""" +given an integer 'n', return the number of prime numbers that are strictly +less than 'n'. +""" + + +class Solution(object): + def countPrimes(self, n): + """ + :type n: int + :rtype: int + """ + if n < 3: + return 0 + primes = [True] * n + primes[0] = primes[1] = False + for i in range(2, int(n**0.5) + 1): + if primes[i]: + primes[i * i : n : i] = [False] * len(primes[i * i : n : i]) + return sum(primes) + + +if __name__ == "__main__": + obj = Solution() + print(obj.countPrimes(10)) + print(obj.countPrimes(1)) + print(obj.countPrimes(0)) diff --git a/count_sorted_vowel.cpp b/count_sorted_vowel.cpp new file mode 100644 index 0000000..e113311 --- /dev/null +++ b/count_sorted_vowel.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + int countVowelStrings(int n) { + int a = 1, e = 1, i = 1, o = 1, u = 1; + while (--n) { + o += u; + i += o; + e += i; + a += e; + } + return a + e + i + o + u; + } +}; + +int main() { + Solution obj; + cout << obj.countVowelStrings(1); +} diff --git a/count_special_integers.c b/count_special_integers.c new file mode 100644 index 0000000..ff73d94 --- /dev/null +++ b/count_special_integers.c @@ -0,0 +1,59 @@ +// 2376. Count Special Integers + +#include "leetcode.h" + +/* + * we call a positive integer special if all of its digits are distinct. given a + * positive integer 'n', return the number of special integers that belong to + * the interval '[1, n]' + */ + +int countSpecialNumbers(int n) { + if (n <= 10) + return n; + int ans = 0, k = 9, choose = 9, list[10], curr = 0; + list[curr] = n % 10; + n /= 10; + while (n) { + curr++; + ans += k; + k *= choose; + choose--; + list[curr] = n % 10; + n /= 10; + } + k /= 9; + bool used[10] = {0}; + choose = 9; + if (curr) { + used[list[curr]] = 1; + ans += k * (list[curr] - 1); + k /= choose; + curr--; + } + while (curr) { + int first_choose = 0; + for (int i = 0; i < list[curr]; i++) + if (!used[i]) + first_choose++; + curr--; + ans += first_choose * k; + choose--; + k /= choose; + if (used[list[curr + 1]]) + return ans; + else + used[list[curr + 1]] = 1; + ; + } + for (int i = 0; i <= list[curr]; i++) + if (!used[i]) + ans++; + return ans; +} + +int main() { + printf("%d\n", countSpecialNumbers(20)); // expect: 19 + printf("%d\n", countSpecialNumbers(5)); // expect: 5 + printf("%d\n", countSpecialNumbers(135)); // expect: 110 +} diff --git a/count_special_integers.py b/count_special_integers.py new file mode 100644 index 0000000..b4a6d4d --- /dev/null +++ b/count_special_integers.py @@ -0,0 +1,35 @@ +# 2376. Count Special Integers +from math import perm + +""" +we call a positive integer special if all of its digits are distinct. given a +positive integer 'n', return the number of special integers that belong to +the interval '[1, n]' +""" + + +class Solution(object): + def countSpecialNumbers(self, n): + """ + :type n: int + :rtype: int + """ + l = list(map(int, str(n + 1))) + m = len(l) + ans = sum(9 * perm(9, i) for i in range(m - 1)) + s = set() + for i, x in enumerate(l): + for y in range(i == 0, x): + if y not in s: + ans += perm(9 - i, m - i - 1) + if x in s: + break + s.add(x) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.countSpecialNumbers(20)) + print(obj.countSpecialNumbers(5)) + print(obj.countSpecialNumbers(135)) diff --git a/count_subarr_fixed_bound.c b/count_subarr_fixed_bound.c new file mode 100644 index 0000000..569fac4 --- /dev/null +++ b/count_subarr_fixed_bound.c @@ -0,0 +1,34 @@ +// 2444. Count Subarrays With Fixed Bounds +#include "leetcode.h" + +/* + * given an integer array 'nums' and two integer 'mink' and 'maxk'. a fixed + * bound subarray of 'nums' is a subarray that satisfies the following + * conditions. the minimum value in the subarray is equal to 'mink' and the + * maximum value in the subarray is equal to 'maxk'. return the number of fixed + * bound subarrays. a subarray is a contiguous part of an array. + */ + +long long countSubarrays(int *nums, int numsSize, int minK, int maxK) { + long long ans = 0; + int last_min = -1, last_max = -1, start = 0; + for (int i = 0; i < numsSize; i++) { + if (nums[i] > maxK || nums[i] < minK) + start = i + 1; + if (nums[i] == maxK) + last_max = i; + if (nums[i] == minK) + last_min = i; + int pos = fmin(last_max, last_min); + if (start > pos) + continue; + ans += pos - start + 1; + } + return ans; +} + +int main() { + int n1[] = {1, 3, 5, 2, 7, 5}, n2[] = {1, 1, 1, 1}; + printf("%lld\n", countSubarrays(n1, ARRAY_SIZE(n1), 1, 5)); // expect: 2 + printf("%lld\n", countSubarrays(n2, ARRAY_SIZE(n2), 1, 1)); // expect: 10 +} diff --git a/count_subarr_fixed_bound.py b/count_subarr_fixed_bound.py new file mode 100644 index 0000000..44fd99c --- /dev/null +++ b/count_subarr_fixed_bound.py @@ -0,0 +1,35 @@ +# 2444. Count Subarrays With Fixed Bounds + +""" +given an integer array 'nums' and two integer 'mink' and 'maxk'. a fixed +bound subarray of 'nums' is a subarray that satisfies the following +conditions. the minimum value in the subarray is equal to 'mink' and the +maximum value in the subarray is equal to 'maxk'. return the number of fixed +bound subarrays. a subarray is a contiguous part of an array. +""" + + +class Solution(object): + def countSubarrays(self, nums, minK, maxK): + """ + :type nums: List[int] + :type minK: int + :type maxK: int + :rtype: int + """ + ans, last_min, last_max, bad = 0, -1, -1, -1 + for i, a in enumerate(nums): + if not minK <= a <= maxK: + bad = i + if a == minK: + last_min = i + if a == maxK: + last_max = i + ans += max(0, min(last_min, last_max) - bad) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.countSubarrays(nums=[1, 3, 5, 2, 7, 5], minK=1, maxK=5)) # expect: 2 + print(obj.countSubarrays(nums=[1, 1, 1, 1], minK=1, maxK=1)) # expect: 10 diff --git a/count_subarr_les_k.c b/count_subarr_les_k.c new file mode 100644 index 0000000..c75300b --- /dev/null +++ b/count_subarr_les_k.c @@ -0,0 +1,11 @@ +#include <stdio.h> +#include <stdlib.h> + +long long countSubarrays(int *nums, int nums_size, long long k) {} + +int main() { + int n1[] = {2, 1, 4, 3, 5}, ns1 = 5, k1 = 10; + int n2[] = {1, 1, 1}, ns2 = 3, k2 = 5; + printf("%lld\n", countSubarrays(n1, ns1, k1)); // expect: 6 + printf("%lld\n", countSubarrays(n2, ns2, k2)); // expect: 5 +} diff --git a/count_subarr_max_elem_k.c b/count_subarr_max_elem_k.c new file mode 100644 index 0000000..e6bf5ad --- /dev/null +++ b/count_subarr_max_elem_k.c @@ -0,0 +1,33 @@ +// 2962. Count Subarrays Where Max Element Appears at Least K Times +#include "leetcode.h" + +/* + * given an integer array 'nums' and a positive integer 'k'. return the number + * of subarrays where the maximum element of 'nums' appears at least 'k' times + * in that subarray. a subarray is a contiguous sequence of elements within an + * array. + */ + +long long countSubarrays(int *nums, int numsSize, int k) { + int max = 0, cnt = 0, idx[numsSize]; + long long ans = 0; + for (int i = 0; i < numsSize; i++) + max = max > nums[i]; + for (int i = 0; i < numsSize; i++) + if (nums[i] == max) + idx[cnt++] = i; + for (int i = 0; i <= cnt - k; i++) { + long long left = idx[i], right = idx[i + k - 1], + bound = i - 1 >= 0 ? idx[i - 1] : -1; + if (!i) + bound = -1; + ans += (left - bound) * (numsSize - right); + } + return ans; +} + +int main() { + int n1[] = {1, 3, 2, 3, 3}, n2[] = {1, 4, 2, 1}; + printf("%lld\n", countSubarrays(n1, ARRAY_SIZE(n1), 2)); // expect: 6 + printf("%lld\n", countSubarrays(n2, ARRAY_SIZE(n2), 3)); // expect: 0 +} diff --git a/count_subarr_max_elem_k.py b/count_subarr_max_elem_k.py new file mode 100644 index 0000000..8f734f2 --- /dev/null +++ b/count_subarr_max_elem_k.py @@ -0,0 +1,32 @@ +# 2962. Count Subarrays Where Max Element Appears at Least K Times + +""" +given an integer array 'nums' and a positive integer 'k'. return the number +of subarrays where the maximum element of 'nums' appears at least 'k' times +in that subarray. a subarray is a contiguous sequence of elements within an +array. +""" + + +class Solution(object): + def countSubarrays(self, nums, k): + """ + :type nums: List[int] + :type k: int + :rtype: int + """ + m = max(nums) + ans, curr, i = 0, 0, 0 + for j in range(len(nums)): + curr += nums[j] == m + while curr >= k: + curr -= nums[i] == m + i += 1 + ans += i + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.countSubarrays(nums=[1, 3, 2, 3, 3], k=2)) # expect: 6 + print(obj.countSubarrays(nums=[1, 4, 2, 1], k=3)) # expect: 0 diff --git a/count_triplets_form_arr_xor.c b/count_triplets_form_arr_xor.c new file mode 100644 index 0000000..cfb7493 --- /dev/null +++ b/count_triplets_form_arr_xor.c @@ -0,0 +1,31 @@ +// 1442. Count Triplets That Can Form Two Arrays of Equal XOR +#include "leetcode.h" + +/* + * given an array of integers 'arr'. we want to select three indices 'i', 'j', + * and 'k' where '(0 <= i < j <= k < arr.length)'. lets define 'a' and 'b' as + * follows. 'a = arr[i] ^ arr[i + 1] ^ ... ^ arr[j - 1]', 'b = arr[j] ^ arr[j + + * 1] ^ ... ^ arr[k]'. note that '^' denotes the bitwise xor operation. return + * the number of triplets (i, j, and k) where 'a == b' + */ + +int countTriplets(int *arr, int arrSize) { + if (arrSize < 2) + return 0; + int ans = 0; + for (int i = 0; i < arrSize; i++) { + int tmp = arr[i]; + for (int j = i + 1; j < arrSize; j++) { + tmp ^= arr[j]; + if (!tmp) + ans += j - i; + } + } + return ans; +} + +int main() { + int a1[] = {2, 3, 1, 6, 7}, a2[] = {1, 1, 1, 1, 1}; + printf("%d\n", countTriplets(a1, ARRAY_SIZE(a1))); // expect: 4 + printf("%d\n", countTriplets(a2, ARRAY_SIZE(a2))); // expect: 10 +} diff --git a/count_triplets_form_arr_xor.py b/count_triplets_form_arr_xor.py new file mode 100644 index 0000000..2ba6a59 --- /dev/null +++ b/count_triplets_form_arr_xor.py @@ -0,0 +1,32 @@ +# 1442. Count Triplets That Can Form Two Arrays of Equal XOR + +""" +given an array of integers 'arr'. we want to select three indices 'i', 'j', +and 'k' where '(0 <= i < j <= k < arr.length)'. lets define 'a' and 'b' as +follows. 'a = arr[i] ^ arr[i + 1] ^ ... ^ arr[j - 1]', 'b = arr[j] ^ arr[j + +1] ^ ... ^ arr[k]'. note that '^' denotes the bitwise xor operation. return +the number of triplets (i, j, and k) where 'a == b' +""" + + +class Solution(object): + def countTriplets(self, arr): + """ + :type arr: List[int] + :rtype: int + """ + arr.insert(0, 0) + n, ans = len(arr), 0 + for i in range(n - 1): + arr[i + 1] ^= arr[i] + for i in range(n): + for j in range(i + 1, n): + if arr[i] == arr[j]: + ans += j - i - 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.countTriplets([2, 3, 1, 6, 7])) + print(obj.countTriplets([1, 1, 1, 1, 1])) diff --git a/count_unreach_node.c b/count_unreach_node.c new file mode 100644 index 0000000..51367fb --- /dev/null +++ b/count_unreach_node.c @@ -0,0 +1,53 @@ +// 2316. Count Unreachable Pairs of Nodes in an Undirected Graph +#include <stdio.h> +#include <stdlib.h> + +/* + * given integer 'n', there is undirected graph with 'n' nodes, numbered 0 to 'n + * - 1' given 2d integer array 'edges' where 'edges[i] = [ai bi]' denotes that + * there exists an undirected edge connecting nodes ai and bi. return number of + * pairs of different nodes that are unreachable from each other + */ + +int union_find(int *u, int val) { + if (u[val] == val) + return val; + else + return union_find(u, u[val]); +} + +void union_set(int *u, int *u_size, int a, int b) { + a = union_find(u, a); + b = union_find(u, b); + if (a == b) + return; + if (u_size[a] > u_size[b]) { + u[b] = u[a]; + u_size[a] += u_size[b]; + } else { + u[a] = u[b]; + u_size[b] += u_size[a]; + } +} + +long long countPairs(int n, int **edges, int edges_size, int *edges_col_size) { + int *u = malloc(n * sizeof(int)), *u_size = malloc(n * sizeof(int)); + for (int i = 0; i < n; i++) { + u[i] = i; + u_size[i] = 1; + } + for (int i = 0; i < edges_size; i++) + union_set(u, u_size, edges[i][0], edges[i][1]); + long long ans = 0; + for (int i = 0; i < n; i++) + ans += n - u_size[union_find(u, i)]; + return ans / 2; +} + +int main() { + int n1 = 3, e1[][3] = {{0, 1}, {0, 2}, {1, 2}}, es1 = 3, ecs1[] = {3}; + int n2 = 7, e2[][5] = {{0, 2}, {0, 5}, {2, 4}, {1, 6}, {5, 4}}, es2 = 5, + ecs2[] = {5}; + printf("%lld\n", countPairs(n1, e1, es1, ecs1)); // expect: 0 + printf("%lld\n", countPairs(n2, e2, es2, ecs2)); // expect: 0 +} diff --git a/count_unreach_node.cpp b/count_unreach_node.cpp new file mode 100644 index 0000000..6dba88e --- /dev/null +++ b/count_unreach_node.cpp @@ -0,0 +1,48 @@ +// 2316. Count Unreachable Pairs of Nodes in an Undirected Graph +#include "leetcode.h" + +/* + * given integer 'n', there is undirected graph with 'n' nodes, numbered 0 to 'n + * - 1' given 2d integer array 'edges' where 'edges[i] = [ai bi]' denotes that + * there exists an undirected edge connecting nodes ai and bi. return number of + * pairs of different nodes that are unreachable from each other + */ + +class Solution { +public: + long long countPairs(int n, vvd(int) & edges) { + unordered_map<int, vector<int>> m; + for (int i = 0; i < edges.size(); i++) { + m[edges[i][0]].push_back(edges[i][0]); + m[edges[i][1]].push_back(edges[i][1]); + } + long long ans = ((long long)n * (n - 1)) / 2; + vector<int> vis(n, 0); + for (int i = 0; i < n; i++) { + if (vis[i] == 0) { + long long cnt = 0; + dfs(i, m, cnt, vis); + ans -= (cnt * (cnt - 1)) / 2; + } + } + return ans; + } + +private: + void dfs(int n, unordered_map<int, vector<int>> m, long long cnt, + vector<int> vis) { + vis[n] = 1; + cnt++; + for (auto i : m[n]) + if (vis[i] == 0) + dfs(i, m, cnt, vis); + } +}; + +int main() { + Solution obj; + vvd(int) e1 = {{0, 1}, {0, 2}, {1, 2}}; + vvd(int) e2 = {{0, 2}, {0, 5}, {2, 4}}; + printf("%lld\n", obj.countPairs(3, e1)); // expect: 0 + printf("%lld\n", obj.countPairs(7, e2)); // expect: 14 +} diff --git a/count_valid_pickup_delivery.c b/count_valid_pickup_delivery.c new file mode 100644 index 0000000..f4f65d4 --- /dev/null +++ b/count_valid_pickup_delivery.c @@ -0,0 +1,25 @@ +// 1359. Count All Valid Pickup and Delivery Options +#include <stdio.h> +#include <stdlib.h> + +/* + * given 'n' orders, each order consists in pickup and delivery services. count + * all valid pickup/delivery possible sequences such that 'delivery[i]' is + * always after 'pickup[i]'. since the answer may be too large, return it modulo + * 10^9+7 + */ + +int countOrders(int n) { + if (n < 1) + return 0; + long combinations = 1L, mod = 1e9 + 7; + for (int i = 2; i <= n; i++) + combinations = (combinations * i * (2 * i - 1)) % mod; + return (int)combinations; +} + +int main() { + printf("%d\n", countOrders(1)); // expect: 1 + printf("%d\n", countOrders(2)); // expect: 6 + printf("%d\n", countOrders(3)); // expect: 90 +} diff --git a/count_valid_pickup_delivery.py b/count_valid_pickup_delivery.py new file mode 100644 index 0000000..84ad800 --- /dev/null +++ b/count_valid_pickup_delivery.py @@ -0,0 +1,24 @@ +# 1359. Count All Valid Pickup and Delivery Options + +""" +given 'n' orders, each order consists in pickup and delivery services. count +all valid pickup/delivery possible sequences such that 'delivery[i]' is +always after 'pickup[i]'. since the answer may be too large, return it modulo +10^9+7 +""" + + +class Solution(object): + def countOrders(self, n): + dp = [0] * (n + 1) + dp[1] = 1 + for i in range(2, n + 1): + dp[i] = (i * dp[i - 1] * (2 * i - 1)) % (10**9 + 7) + return dp[n] + + +if __name__ == "__main__": + obj = Solution + print(obj.countOrders(1)) # expect: 1 + print(obj.countOrders(2)) # expect: 6 + print(obj.countOrders(3)) # expect: 90 diff --git a/count_vowels_permutation.c b/count_vowels_permutation.c new file mode 100644 index 0000000..6ca1cd1 --- /dev/null +++ b/count_vowels_permutation.c @@ -0,0 +1,26 @@ +// 1220. Count Vowels Permutation +#include <stdio.h> +#include <stdlib.h> + +int countVowelPermutation(int n) { + int mod = 1e9 + 7, ans = 0; + long long int dp[n + 1][5]; + for (int i = 0; i < 5; i++) + dp[1][i] = 1; + for (int i = 2; i < n + 1; i++) { + dp[i][0] = (dp[i - 1][1] + dp[i - 1][2] + dp[i - 1][4]) % mod; + dp[i][1] = (dp[i - 1][0] + dp[i - 1][2]) % mod; + dp[i][2] = (dp[i - 1][1] + dp[i - 1][3]) % mod; + dp[i][3] = dp[i - 1][2]; + dp[i][4] = (dp[i - 1][2] + dp[i - 1][3]) % mod; + } + for (int i = 0; i < 5; i++) + ans = (ans + dp[n][i]) % mod; + return ans; +} + +int main() { + printf("%d\n", countVowelPermutation(1)); // expect: 5 + printf("%d\n", countVowelPermutation(2)); // expect: 10 + printf("%d\n", countVowelPermutation(5)); // expect: 68 +} diff --git a/count_vowels_permutation.cpp b/count_vowels_permutation.cpp new file mode 100644 index 0000000..807a1f4 --- /dev/null +++ b/count_vowels_permutation.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" +class Solution { +public: + int countVowelPermutation(int n) { + int ans = 0; + memo.resize(n + 1, vector<int>(5, -1)); + for (int i = 0; i < 5; i++) + ans += dp(n, i), ans %= mod; + return ans; + } + +private: + int mod = 1e9 + 7; + vector<vector<int>> relation = {{1}, {0, 2}, {0, 1, 3, 4}, {2, 4}, {0}}, memo; + int dp(int n, int v) { + if (n == 1) + return 1; + if (memo[n][v] != -1) + return memo[n][v]; + memo[n][v] = 0; + for (int &i : relation[v]) + memo[n][v] += dp(n - 1, i), memo[n][v] %= mod; + return memo[n][v]; + } +}; + +int main() { + Solution obj; + cout << obj.countVowelPermutation(1); +} diff --git a/count_vowels_permutation.py b/count_vowels_permutation.py new file mode 100644 index 0000000..f6f1b29 --- /dev/null +++ b/count_vowels_permutation.py @@ -0,0 +1,16 @@ +# 1220. Count Vowels Permutation + + +class Solution(object): + def countVowelPermutation(self, n): + a, e, i, o, u = 1, 1, 1, 1, 1 + for _ in range(n - 1): + a, e, i, o, u = e + i + u, a + i, e + o, i, i + o + return (a + e + i + o + u) % (10**9 + 7) + + +if __name__ == "__main__": + obj = Solution() + print(obj.countVowelPermutation(1)) # expect: 5 + print(obj.countVowelPermutation(2)) # expect: 10 + print(obj.countVowelPermutation(5)) # expect: 68 diff --git a/count_ways_build_strs.c b/count_ways_build_strs.c new file mode 100644 index 0000000..3a357eb --- /dev/null +++ b/count_ways_build_strs.c @@ -0,0 +1,36 @@ +// 2466. Count Ways To Build Good Strings +#include <stdio.h> +#include <stdlib.h> + +/* + * given the integers 'zero, one, low, and high', we can construct a string by + * starting with an empty string, and then at each step perform either of the + * following opperations: + * - append the character 0 'zero' times + * - append the character 1 'one' times + * this can be performed any number of times. a good string is a string + * constructed by the above process having a length between 'low' and 'high' + * (inclusive). return the number of different good strings that can be + * constructed. return modulo 10^9+7. + */ + +int countGoodStrings(int low, int high, int zero, int one) { + int mod = 1e9 + 7; + int *dp = calloc(high + 1, sizeof(int)); + long long ans = 0; + dp[0] = 1; + for (int i = 1; i <= high; i++) { + if (i >= one) + dp[i] = (dp[i] + dp[i - one]) % mod; + if (i >= zero) + dp[i] = (dp[i] + dp[i - zero]) % mod; + if (i >= low) + ans = (ans + dp[i]) % mod; + } + return ans; +} + +int main() { + printf("%d\n", countGoodStrings(3, 3, 1, 1)); // expect: 8 + printf("%d\n", countGoodStrings(2, 3, 1, 2)); // expect: 5 +} diff --git a/count_ways_build_strs.cpp b/count_ways_build_strs.cpp new file mode 100644 index 0000000..7600fa3 --- /dev/null +++ b/count_ways_build_strs.cpp @@ -0,0 +1,39 @@ +// 2466. Count Ways To Build Good Strings +#include "leetcode.h" + +/* + * given the integers 'zero, one, low, and high', we can construct a string by + * starting with an empty string, and then at each step perform either of the + * following opperations: + * - append the character 0 'zero' times + * - append the character 1 'one' times + * this can be performed any number of times. a good string is a string + * constructed by the above process having a length between 'low' and 'high' + * (inclusive). return the number of different good strings that can be + * constructed. return modulo 10^9+7. + */ + +class Solution { +public: + int countGoodStrings(int low, int high, int zero, int one) { + vector<int> dp(high + 1, 0); + dp[0] = 1; + int mod = 1000000007; + for (int i = 1; i <= high; ++i) { + if (i >= zero) + dp[i] += dp[i - zero] % mod; + if (i >= one) + dp[i] += dp[i - one] % mod; + } + long long cnt = 0; + for (int i = low; i <= high; ++i) + cnt = (cnt + dp[i]) % mod; + return cnt; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.countGoodStrings(3, 3, 1, 1)); // expect: 8 + printf("%d\n", obj.countGoodStrings(2, 3, 1, 2)); // expect: 5 +} diff --git a/counting_bits.c b/counting_bits.c new file mode 100644 index 0000000..359d3a9 --- /dev/null +++ b/counting_bits.c @@ -0,0 +1,62 @@ +// 338. Counting Bits +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer 'n', return an array 'ans' of length 'n + 1' such that for + * each 'i (0 <= i <= n)', 'ans[i]' is the number of 1's inthe binary + * representation of 'i' + */ + +int *countBits(int n, int *return_size) { + *return_size = n + 1; + int *ans = (int *)malloc((n + 1) * sizeof(int)); + int org = 1, dis = 1, ptr = 2, post = 3, idx = 4; + ans[0] = 0; + if (!n) + return ans; + ans[1] = 1; + if (n == 1) + return ans; + ans[2] = 1; + if (n == 2) + return ans; + ans[3] = 2; + if (n == 3) + return ans; + while (idx <= n) { + dis = org = org * 2; + while (ptr != post) { + for (int i = ptr; i <= post; i++) { + ans[idx] = ans[i]; + if (idx == n) + return ans; + idx++; + } + dis /= 2; + ptr += dis; + } + ans[idx] = ans[idx - 1]; + if (idx == n) + break; + idx++; + ans[idx] = ans[idx - 1] + 1; + if (idx == n) + break; + idx++; + ptr = post + 1; + post = idx - 1; + } + return ans; +} + +int main() { + int rs1[] = {}, rs2[] = {}; + int *cb1 = countBits(2, rs1), *cb2 = countBits(5, rs2); + for (int i = 0; i < 3; i++) + printf("%d ", cb1[i]); // expect: 0 1 1 + printf("\n"); + for (int i = 0; i < 6; i++) + printf("%d ", cb2[i]); // expect: 0 1 1 2 1 2 + printf("\n"); +} diff --git a/counting_bits.py b/counting_bits.py new file mode 100644 index 0000000..d9053ef --- /dev/null +++ b/counting_bits.py @@ -0,0 +1,20 @@ +# 338. Counting Bits + +""" +given an integer 'n', return an array 'ans' of length 'n + 1' such that for +each 'i (0 <= i <= n)', 'ans[i]' is the number of 1's inthe binary +representation of 'i' +""" + + +class Solution(object): + def countBits(self, n): + cnt = [0] + for i in range(1, n + 1): + cnt.append(cnt[i >> 1] + i % 2) + return cnt + +if __name__ == "__main__": + obj = Solution() + print(obj.countBits(2)) # expect: 0 1 1 + print(obj.countBits(5)) # expect: 0 1 1 2 1 2 diff --git a/couples_holding_hands.c b/couples_holding_hands.c new file mode 100644 index 0000000..05be711 --- /dev/null +++ b/couples_holding_hands.c @@ -0,0 +1,41 @@ +// 765. Couples Holding Hands +#include <stdio.h> +#include <stdlib.h> + +/* + * there are 'n' couples sitting '2n' seats arranged in a row and want to hold + * hands. the people and seats are represented by an integer array 'row' where + * 'row[i]' is the id of the person sitting in the i'th seat. the couples are + * numbered in order, the first couple being '(0, 1)', the second couple being + * '(2, 3)', and so on with the last couple being '(2n -2, 2n -1)'. return the + * minimum number of swaps so that every couple is sitting side by side. a swap + * consists of choosing any two people then they stand up and switch seats. + */ + +int minSwapsCouples(int *row, int row_size) { + int pair[60], position[60], cnt = 0; + for (int i = 0; i < 60; i += 2) { + pair[i] = i + 1; + pair[i + 1] = i; + } + for (int i = 0; i < row_size; i++) + position[row[i]] = i; + for (int i = 0; i < row_size; i += 2) { + if (row[i + 1] != pair[row[i]]) { + cnt++; + int pos = position[pair[row[i]]]; + position[row[i + 1]] = pos; + int tmp = row[pos]; + row[pos] = row[i + 1]; + row[i + 1] = tmp; + position[pair[row[i]]] = i + 1; + } + } + return cnt; +} + +int main() { + int r1[] = {0, 2, 1, 3}, r2[] = {3, 2, 0, 1}; + printf("%d\n", minSwapsCouples(r1, 4)); // expect: 1 + printf("%d\n", minSwapsCouples(r2, 4)); // expect: 0 +} diff --git a/couples_holding_hands.cpp b/couples_holding_hands.cpp new file mode 100644 index 0000000..7c3069a --- /dev/null +++ b/couples_holding_hands.cpp @@ -0,0 +1,38 @@ +// 765. Couples Holding Hands +#include "leetcode.h" + +/* + * there are 'n' couples sitting '2n' seats arranged in a row and want to hold + * hands. the people and seats are represented by an integer array 'row' where + * 'row[i]' is the id of the person sitting in the i'th seat. the couples are + * numbered in order, the first couple being '(0, 1)', the second couple being + * '(2, 3)', and so on with the last couple being '(2n -2, 2n -1)'. return the + * minimum number of swaps so that every couple is sitting side by side. a swap + * consists of choosing any two people then they stand up and switch seats. + */ + +class Solution { +public: + int minSwapsCouples(vector<int> &row) { + int ans = 0, n = row.size(); + vector<int> ptn(n, 0), pos(n, 0); + for (int i = 0; i < n; i++) { + ptn[i] = (!(i % 2) ? i + 1 : i - 1); + pos[row[i]] = i; + } + for (int i = 0; i < n; i++) + for (int j = ptn[pos[ptn[row[i]]]]; i != j; j = ptn[pos[ptn[row[i]]]]) { + swap(row[i], row[j]); + swap(pos[row[i]], pos[row[j]]); + ans++; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> r1 = {0, 2, 1, 3}, r2 = {3, 2, 0, 1}; + printf("%d\n", obj.minSwapsCouples(r1)); // expect: 1 + printf("%d\n", obj.minSwapsCouples(r2)); // expect: 0 +} diff --git a/course_schedule.c b/course_schedule.c new file mode 100644 index 0000000..81a64a9 --- /dev/null +++ b/course_schedule.c @@ -0,0 +1,69 @@ +// 207. Course Schedule +#include <stdbool.h> +#include <stdlib.h> + +/* + * there are a total of 'num_courses' courses you have to take labeled from 0 to + * 'num_courses - 1'. you are given an array 'prerequisites' where + * 'prerequisites[i] = [ai, bi]' indicates that you must take course 'bi' first + * if you want to take course 'ai'. return true if you can finish all courses, + * otherwise, return false + */ + +int cmp(const void *a, const void *b) { + int *arr1 = *(int **)a; + int *arr2 = *(int **)b; + return arr1[1] - arr2[1]; +} + +int bts(int **arr, int arr_size, int val) { + int left = 0, right = arr_size - 1, mid; + while (left < right) { + mid = left + (right - left) / 2; + if (arr[mid][1] >= val) + right = mid; + else + left = mid + 1; + } + if (arr[left][1] == val) + return left; + else + return -1; +} + +bool canFinish(int num_courses, int **prerequisites, int prerequisites_size, + int *prerequisites_col_size) { + int *pre_cnt = calloc(num_courses, sizeof(int)); + for (int i = 0; i < prerequisites_size; i++) + pre_cnt[prerequisites[i][0]]++; + int *queue = malloc(1000 * sizeof(int)), queue_idx = 0; + for (int i = 0; i < num_courses; i++) + if (!pre_cnt[i]) { + queue[queue_idx] = i; + queue_idx++; + } + if (prerequisites_size) + qsort(prerequisites, prerequisites_size, sizeof(int *), cmp); + int course_seq = 0; + while (queue_idx) { + queue_idx--; + int val = queue[queue_idx]; + course_seq++; + if (prerequisites_size) { + int k = bts(prerequisites, prerequisites_size, val); + if (k != -1) + while (k < prerequisites_size && prerequisites[k][1] == val) { + pre_cnt[prerequisites[k][0]]--; + if (!pre_cnt[prerequisites[k][0]]) { + queue[queue_idx] = prerequisites[k][0]; + queue_idx++; + } + k++; + } + } + } + if (course_seq != num_courses) + return false; + else + return true; +} diff --git a/course_schedule.cpp b/course_schedule.cpp new file mode 100644 index 0000000..610ab88 --- /dev/null +++ b/course_schedule.cpp @@ -0,0 +1,44 @@ +// 207. Course Schedule +#include "leetcode.h" + +/* + * there are a total of 'num_courses' courses you have to take labeled from 0 to + * 'num_courses - 1'. you are given an array 'prerequisites' where + * 'prerequisites[i] = [ai, bi]' indicates that you must take course 'bi' first + * if you want to take course 'ai'. return true if you can finish all courses, + * otherwise, return false + */ + +class Solution { + bool is_cycle(vector<int> adj[], vector<int> &vis, int id) { + if (vis[id] == 1) + return true; + if (!vis[id]) { + vis[id] = 1; + for (auto edge : adj[id]) + if (is_cycle(adj, vis, edge)) + return true; + } + vis[id] = 2; + return false; + } + +public: + bool canFinish(int num_courses, vvd(int) & prerequisites) { + vector<int> adj[num_courses]; + for (auto edge : prerequisites) + adj[edge[1]].push_back(edge[0]); + vector<int> vis(num_courses, 0); + for (int i = 0; i < num_courses; i++) + if (is_cycle(adj, vis, i)) + return false; + return true; + } +}; + +int main() { + Solution obj; + vvd(int) p1 = {{1, 0}}, p2 = {{1, 0}, {0, 1}}; + printf("%d\n", obj.canFinish(2, p1)); // expect: 1 + printf("%d\n", obj.canFinish(2, p2)); // expect: 0 +} diff --git a/course_schedule_3.cpp b/course_schedule_3.cpp new file mode 100644 index 0000000..e13d2ca --- /dev/null +++ b/course_schedule_3.cpp @@ -0,0 +1,27 @@ +#include "leetcode.h" + +class Solution { +public: + int scheduleCourse(vector<vector<int>> &courses) { + int time = 0; + priority_queue<int> pq; + sort(courses.begin(), courses.end(), compare); + for (int i = 0; i < courses.size(); i++) { + if (time + courses[i][0] <= courses[i][1]) { + time += courses[i][0]; + pq.push(courses[i][0]); + } else { + if (!pq.empty() && pq.top() > courses[i][0]) { + pq.pop(); + time -= pq.top(); + time += courses[i][0]; + pq.push(courses[i][0]); + } + } + } + return pq.size(); + } + +private: + static bool compare(vector<int> a, vector<int> b) { return a[1] < b[1]; } +}; diff --git a/critical_connection_network.cpp b/critical_connection_network.cpp new file mode 100644 index 0000000..eeb5f82 --- /dev/null +++ b/critical_connection_network.cpp @@ -0,0 +1,42 @@ +#include "leetcode.h" + +class Solution { +public: + vector<vector<int>> criticalConnections(int n, + vector<vector<int>> &connections) { + vector<bool> vi(n, false); + vector<int> disc(n, 0), low(n, 0), parent(n, -1); + vector<vector<int>> g(n, vector<int>()), ans; + for (auto &p : connections) { + g[p.front()].push_back(p.back()); + g[p.back()].push_back(p.front()); + } + for (int i = 0; i < n; ++i) { + if (vi[i]) + continue; + helper(i, vi, disc, low, parent, g, ans); + } + return ans; + } + +private: + void helper(int u, vector<bool> &vi, vector<int> &disc, vector<int> &low, + vector<int> &parent, vector<vector<int>> &g, + vector<vector<int>> &ans) { + static int time = 0; + vi[u] = true; + disc[u] = low[u] = ++time; + for (int i : g[u]) { + if (!vi[i]) { + parent[i] = u; + helper(i, vi, disc, low, parent, g, ans); + low[u] = min(low[u], low[i]); + if (low[i] > disc[u]) + ans.push_back({u, i}); + } else if (i != parent[u]) + low[u] = min(low[u], disc[i]); + } + } +}; + +int main() {} diff --git a/custom_sort_string.c b/custom_sort_string.c new file mode 100644 index 0000000..0d13319 --- /dev/null +++ b/custom_sort_string.c @@ -0,0 +1,32 @@ +// 791. Custom Sort String +#include "leetcode.h" + +/* + * given two strings 'order' and 's'. all the characters of 'order' are unique + * and were sorted in some custom order previously. permute the characters of + * 's' so that they atch the order that 'order' was sorted. more specifically, + * if a character 'x' occurs before character 'y' in 'order', then 'x' should + * occur before 'y' in permuted string. return any permutation of 's' that + * satisfies this property. + */ + +static char pattern[26] = {0}; + +int cmp(const void *a, const void *b) { + return pattern[*(char *)a - 'a'] - pattern[*(char *)b - 'a']; +} + +char *customSortString(char *order, char *s) { + for (int i = 0; i < 26; i++) + pattern[i] = 0; + for (int i = 0; i < strlen(order); i++) + pattern[order[i] - 'a'] = i + 1; + qsort(s, strlen(s), sizeof(char), cmp); + return s; +} + +int main() { + char *o1 = "cba", *s1 = "abcd", *o2 = "bcafg", *s2 = "abcd"; + printf("%s\n", customSortString(o1, s1)); // expect: + printf("%s\n", customSortString(o2, s2)); // expect: +} diff --git a/custom_sort_string.py b/custom_sort_string.py new file mode 100644 index 0000000..07de305 --- /dev/null +++ b/custom_sort_string.py @@ -0,0 +1,31 @@ +# 791. Custom Sort String +from collections import Counter + +""" +given two strings 'order' and 's'. all the characters of 'order' are unique +and were sorted in some custom order previously. permute the characters of +'s' so that they atch the order that 'order' was sorted. more specifically, +if a character 'x' occurs before character 'y' in 'order', then 'x' should +occur before 'y' in permuted string. return any permutation of 's' that +satisfies this property. +""" + + +class Solution(object): + def customSortString(self, order, s): + """ + :type order: str + :type s: str + :rtype: str + """ + cnt = Counter(s) + ans = [cnt.pop(c, 0) * c for c in order] + for c, v in cnt.items(): + ans.append(c * v) + return "".join(ans) + + +if __name__ == "__main__": + obj = Solution() + print(obj.customSortString("cba", "abcd")) + print(obj.customSortString("bcafg", "abcd")) diff --git a/daily_temps.c b/daily_temps.c new file mode 100644 index 0000000..b85dad6 --- /dev/null +++ b/daily_temps.c @@ -0,0 +1,47 @@ +// 739. Daily Temperatures +#include "leetcode.h" + +/* + * given an array of integers 'temperatures' represents the daily temperatures + * return an array 'answer' such that 'answer[i]' is the number of days you have + * to wait after the i'th day to get a warmer temperature. if there is no future + * day for which this is possible, keep 'answer[i] == 0' instead. + */ + +int *dailyTemperatures(int *temperatures, int temperatures_size, + int *return_size) { + *return_size = temperatures_size; + int tmp = 0, cnt = temperatures_size - 2; + int *ans = (int *)malloc(sizeof(int) * temperatures_size); + ans[temperatures_size - 1] = 0; + for (int i = temperatures_size - 2; i >= 0; i--) + for (int j = 1; j + i < temperatures_size; j += tmp) { + if (temperatures[i] < temperatures[i + j]) { + ans[cnt--] = j; + break; + } else if (!ans[i + j]) { + ans[cnt--] = 0; + break; + } + tmp = ans[i + j]; + } + return ans; +} + +int main() { + int t1[] = {73, 74, 75, 71, 69, 72, 76, 73}, t2[] = {30, 40, 50, 60}, + t3[] = {30, 60, 90}; + int rs1[] = {}, rs2[] = {}, rs3[] = {}; + int *dt1 = dailyTemperatures(t1, ARRAY_SIZE(t1), rs1); + int *dt2 = dailyTemperatures(t2, ARRAY_SIZE(t2), rs2); + int *dt3 = dailyTemperatures(t3, ARRAY_SIZE(t3), rs3); + for (int i = 0; i < ARRAY_SIZE(t1); i++) + printf("%d ", dt1[i]); // expect: 1,1,4,2,1,1,0,0 + printf("\n"); + for (int i = 0; i < ARRAY_SIZE(t2); i++) + printf("%d ", dt2[i]); // expect: 1 1 1 0 + printf("\n"); + for (int i = 0; i < ARRAY_SIZE(t3); i++) + printf("%d ", dt2[i]); // expect: 1 1 0 + printf("\n"); +} diff --git a/daily_temps.cpp b/daily_temps.cpp new file mode 100644 index 0000000..e244252 --- /dev/null +++ b/daily_temps.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> dailyTemperatures(vector<int> &temperatures) { + int n = temperatures.size(); + vector<int> nge(n, 0); + stack<int> stk{}; + for (int i = n - 1; i >= 0; --i) { + while (!stk.empty() && temperatures[stk.top()] <= temperatures[i]) + stk.pop(); + if (!stk.empty()) + nge[i] = stk.top() - i; + stk.push(i); + } + return nge; + } +}; + +int main() { + Solution obj; + vector<int> t1 = {73, 74, 75, 71, 69, 72, 76, 73}; + vector<int> t2 = {30, 40, 50, 60}; + vector<int> t3 = {30, 60, 90}; + obj.dailyTemperatures(t1); // expect 1,1,4,2,1,1,0,0 + obj.dailyTemperatures(t2); // expect 1,1,1,0 + obj.dailyTemperatures(t3); // expect 1,1,0 +} diff --git a/daily_temps.py b/daily_temps.py new file mode 100644 index 0000000..f96e9ec --- /dev/null +++ b/daily_temps.py @@ -0,0 +1,31 @@ +# 739. Daily Temperatures + +""" +given an array of integers 'temperatures' represents the daily temperatures +return an array 'answer' such that 'answer[i]' is the number of days you have +to wait after the i'th day to get a warmer temperature. if there is no future +day for which this is possible, keep 'answer[i] == 0' instead. +""" + + +class Solution(object): + def dailyTemperatures(self, temperatures): + """ + :type temperatures: List[int] + :rtype: List[int] + """ + ans = [0] * len(temperatures) + stack = [] + for i, t in enumerate(temperatures): + while stack and temperatures[stack[-1]] < t: + curr = stack.pop() + ans[curr] = i - curr + stack.append(i) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.dailyTemperatures(temperatures=[73, 74, 75, 71, 69, 72, 76, 73])) + print(obj.dailyTemperatures(temperatures=[30, 40, 50, 60])) + print(obj.dailyTemperatures(temperatures=[30, 60, 90])) diff --git a/daily_temps.rs b/daily_temps.rs new file mode 100644 index 0000000..63b1f2b --- /dev/null +++ b/daily_temps.rs @@ -0,0 +1,28 @@ +struct Solution; + +impl Solution { + pub fn daily_temperatures(temperatures: Vec<i32>) -> Vec<i32> { + let n = temperatures.len(); + let mut ans: Vec<i32> = vec![0; n]; + let mut stk: Vec<usize> = Vec::new(); + for i in 0..n { + while stk.last().map_or(false, |&v| { temperatures[v] < temperatures[i]}) { + match stk.pop() { + None => break, + Some(idx) => ans[idx] = (i - idx) as i32 + } + } + stk.push(i); + } + ans + } +} + +fn main() { + let t1 = vec![73,74,75,71,69,72,76,73]; + let t2 = vec![30,40,50,60]; + let t3 = vec![30,60,90]; + println!("{:?}", Solution::daily_temperatures(t1)); + println!("{:?}", Solution::daily_temperatures(t2)); + println!("{:?}", Solution::daily_temperatures(t3)); +} diff --git a/data_stream_disjoint_interval.cpp b/data_stream_disjoint_interval.cpp new file mode 100644 index 0000000..7abbdeb --- /dev/null +++ b/data_stream_disjoint_interval.cpp @@ -0,0 +1,45 @@ +// 352. Data Stream as Disjoint Intervals +#include "leetcode.h" + +/* + * given a data stream input of non-negative integers 'a1, a2, ..., an', + * summarize the numbers seen so far as a list of disjoint intervals. implement + * 'SummaryRanges': SummaryRanges() initialises the object with an empty stream + * void addNum(int value) adds the integer 'value' to the stream + * int[][] getIntervals() returns a summary of the integers in the stream + * currently as a list of disjoint intervals '[starti, endi]'. sort answer by + * 'starti' + */ + +class SummaryRanges { +public: + map<int, int> m; + void addNum(int value) { + if (m.count(value)) + return; + m[value] = value; + int mn = value, mx = value; + if (m.count(value - 1)) + mn = m[value - 1]; + if (m.count(value + 1)) + mx = m[value + 1]; + m[mn] = mx; + m[mx] = mn; + } + vvd(int) getIntervals() { + vvd(int) ans; + auto it = m.begin(); + while (it != m.end()) { + ans.push_back({it->first, it->second}); + it = m.upper_bound(it->second); + } + return ans; + } +}; + +int main() { + SummaryRanges *obj = new SummaryRanges(); + int value; + obj->addNum(value); + vvd(int) param_2 = obj->getIntervals(); +} diff --git a/decode_ways.c b/decode_ways.c new file mode 100644 index 0000000..705e495 --- /dev/null +++ b/decode_ways.c @@ -0,0 +1,59 @@ +// 91. Decode Ways +#include "leetcode.h" + +/* + * a message containing letters from a - z can be encoded into numbers using the + * following mapping: a -> 1, b -> 2, ..., z -> 26. to decode an encoded + * message, all the digits must be grouped then mapped back into letters using + * the reverse of the mapping above (there may be multiple ways). for example, + * "11106" can be mapped into: "aajf" with the grouping ' 1 1 10 6', "kjf" with + * the grouping '11 10 6'. note that the grouping '(1 11 06)' because '06' + * cannot be mapped into "f" because '6' is different from '06'. given a string + * 's' containing only digits, return the number of ways to decode it. the test + * cases are generated so that the answer fits in a 32-bit integer + */ + +int char_to_int(char *s) { return (s[0] - '0') * 10 + s[1] - '0'; } + +int numDecodings(char *s) { + int n = strlen(s), a = 1, b, tmp = char_to_int(s), c; + if (s[0] == '0') + return 0; + if (!n || n == 1) + return 1; + if (tmp == 10 || tmp == 20) + b = 1; + else if (!(tmp % 10)) + return 0; + else if (tmp > 26) + b = 1; + else + b = 2; + if (n == 2) + return b; + for (int i = 2; i < n; i++) { + tmp = char_to_int(&s[i - 1]); + if (!tmp) + return 0; + else if (tmp && tmp < 10) + c = b; + else if (tmp == 10 || tmp == 20) + c = a; + else if (!(tmp % 10)) + return 0; + else if (tmp > 26) + c = b; + else + c = a + b; + a = b; + b = c; + } + return c; +} + +int main() { + char *s1 = "12", *s2 = "226", *s3 = "06"; + printf("%d\n", numDecodings(s1)); // expepct: 2 + printf("%d\n", numDecodings(s2)); // expepct: 3 + printf("%d\n", numDecodings(s3)); // expepct: 0 +} diff --git a/decode_ways.cpp b/decode_ways.cpp new file mode 100644 index 0000000..c03bd67 --- /dev/null +++ b/decode_ways.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + int numDecodings(string s) { + int n = s.size(); + vector<int> dp(n + 1, 0); + dp[0] = 1; + for (int i = 0; i < n; ++i) { + if (s[i] != '0') + dp[i + 1] += dp[i]; + if (i >= 1 && + (s[i - 1] == '1' || (s[i - 1] == '2' && s[i] >= '0' && s[i] <= '6'))) + dp[i + 1] += dp[i - 1]; + } + return dp[n]; + } +}; + +int main() { + Solution obj; + cout << obj.numDecodings("226"); +} diff --git a/decode_ways.py b/decode_ways.py new file mode 100644 index 0000000..0689aed --- /dev/null +++ b/decode_ways.py @@ -0,0 +1,43 @@ +# 91. Decode Ways + +""" +a message containing letters from a - z can be encoded into numbers using the +following mapping: a -> 1, b -> 2, ..., z -> 26. to decode an encoded +message, all the digits must be grouped then mapped back into letters using +the reverse of the mapping above (there may be multiple ways). for example, +"11106" can be mapped into: "aajf" with the grouping ' 1 1 10 6', "kjf" with +the grouping '11 10 6'. note that the grouping '(1 11 06)' because '06' +cannot be mapped into "f" because '6' is different from '06'. given a string +'s' containing only digits, return the number of ways to decode it. the test +cases are generated so that the answer fits in a 32-bit integer +""" + + +class Solution(object): + def numDecodings(self, s): + """ + :type s: str + :rtype: int + """ + if s == "0": + return 0 + dp1 = int(s[-1] != "0") + dp2 = 1 + i = len(s) - 2 + while i >= 0: + if s[i] == "0": + dp0 = 0 + else: + dp0 = dp1 + if (s[i] == "1") or (s[i] == "2" and eval(s[i + 1]) < 7): + dp0 += dp2 + i -= 1 + dp0, dp1, dp2 = 0, dp0, dp1 + return dp1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.numDecodings("12")) + print(obj.numDecodings("226")) + print(obj.numDecodings("06")) diff --git a/decode_xor_array.c b/decode_xor_array.c new file mode 100644 index 0000000..d709fbf --- /dev/null +++ b/decode_xor_array.c @@ -0,0 +1,35 @@ +// 720. Decode XORed Array +#include <stdio.h> +#include <stdlib.h> + +/* + * there is a hidden integer array 'arr' that consists of 'n' non-negative + * integers. it was encoded into another integer array 'encoded' of length 'n - + * 1' such that 'encoded[i] = arr[i] ^ arr[i + 1]'. for example, if 'arr = + * [1,0,2,1]', then 'encoded = [1,2,3]'. you are given the 'encoded' array. you + * are also given an integer 'first', that is the first element of 'arr'. ie. of + * 'arr[0]'. return the original array 'arr'. it can be proved that the answer + * exists and is unique. + */ + +int *decode(int *encoded, int encoded_size, int first, int *return_size) { + *return_size = encoded_size + 1; + int *arr = (int *)malloc(*return_size * sizeof(int)); + arr[0] = first; + for (int i = 0; i < encoded_size; i++) + arr[i + 1] = arr[i] ^ encoded[i]; + return arr; +} + +int main() { + int e1[] = {1, 2, 3}, es1 = 3, f1 = 1, rs1[] = {}; + int e2[] = {6, 2, 7, 3}, es2 = 4, f2 = 4, rs2[] = {}; + int *d1 = decode(e1, es1, f1, rs1); + int *d2 = decode(e2, es2, f2, rs2); + for (int i = 0; i < es1 + 1; i++) + printf("%d ", d1[i]); // expect: 1 0 2 1 + printf("\n"); + for (int i = 0; i < es2 + 1; i++) + printf("%d ", d2[i]); // expect: 4 2 0 7 4 + printf("\n"); +} diff --git a/decode_xor_array.cpp b/decode_xor_array.cpp new file mode 100644 index 0000000..7ee4139 --- /dev/null +++ b/decode_xor_array.cpp @@ -0,0 +1,35 @@ +// 720. Decode XORed Array +#include "leetcode.h" + +/* + * there is a hidden integer array 'arr' that consists of 'n' non-negative + * integers. it was encoded into another integer array 'encoded' of length 'n - + * 1' such that 'encoded[i] = arr[i] ^ arr[i + 1]'. for example, if 'arr = + * [1,0,2,1]', then 'encoded = [1,2,3]'. you are given the 'encoded' array. you + * are also given an integer 'first', that is the first element of 'arr'. ie. of + * 'arr[0]'. return the original array 'arr'. it can be proved that the answer + * exists and is unique. + */ + +class Solution { +public: + vector<int> decode(vector<int> encoded, int first) { + for (int &i : encoded) { + swap(i, first); + first ^= i; + } + encoded.push_back(first); + return encoded; + } +}; + +int main() { + Solution obj; + vector<int> e1 = {1, 2, 3}, e2 = {6, 2, 7, 3}; + for (auto i : obj.decode(e1, 1)) + printf("%d ", i); // expect: 1 0 2 1 + printf("\n"); + for (auto i : obj.decode(e2, 4)) + printf("%d ", i); // expect: 4 2 0 7 4 + printf("\n"); +} diff --git a/decoded_string_idx.c b/decoded_string_idx.c new file mode 100644 index 0000000..8515bd0 --- /dev/null +++ b/decoded_string_idx.c @@ -0,0 +1,54 @@ +// 880. Decoded String at Index +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given an encoded string 's'. to decode the string to a tape, the encoded + * string is read one character at a time at a time the following steps are + * taken. if the character read is a letter, that letter is written onto the + * tape. if the character read is a digit 'd', the entire current tape is + * repeatedly written 'd - 1' more times in total. given an integer 'k', return + * the k'th letter (1-indexed) in the decoded string. + */ + +char *decodeAtIndex(char *s, int k) { + long long cnt = 0; + int n = strlen(s); + for (int i = 0; i < n; i++) { + char ptr; + if (isalpha(s[i])) { + cnt++; + ptr = s[i]; + if (cnt == k) { + char *ans = malloc(2); + ans[0] = s[i]; + ans[1] = '\0'; + return ans; + } + } else { + int times = s[i] - '0'; + if (cnt * times < k) + cnt *= times; + else if (!(k % cnt)) { + char *ans = malloc(2); + ans[0] = ptr; + ans[1] = '\0'; + return ans; + } else { + s[i] = '\0'; + return decodeAtIndex(s, k % cnt); + } + } + } + return ""; +} + +int main() { + char s1[] = {"leet2code3"}, s2[] = {"ha22"}, + s3[] = {"a2345678999999999999999"}; + printf("%s\n", decodeAtIndex(s1, 10)); // expect: o + printf("%s\n", decodeAtIndex(s2, 5)); // expect: h + printf("%s\n", decodeAtIndex(s3, 1)); // expect: a +} diff --git a/decoded_string_idx.py b/decoded_string_idx.py new file mode 100644 index 0000000..04e9021 --- /dev/null +++ b/decoded_string_idx.py @@ -0,0 +1,38 @@ +# 880. Decoded String at Index + +""" +given an encoded string 's'. to decode the string to a tape, the encoded +string is read one character at a time at a time the following steps are +taken. if the character read is a letter, that letter is written onto the +tape. if the character read is a digit 'd', the entire current tape is +repeatedly written 'd - 1' more times in total. given an integer 'k', return +the k'th letter (1-indexed) in the decoded string. +""" + + +class Solution(object): + def decodeAtIndex(self, s, k): + length = 0 + i = 0 + while length < k: + if s[i].isdigit(): + length *= int(s[i]) + else: + length += 1 + i += 1 + for j in range(i - 1, -1, -1): + char = s[j] + if char.isdigit(): + length //= int(char) + k %= length + else: + if k == 0 or k == length: + return char + length -= 1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.decodeAtIndex("leet2code3", 10)) # expect: o + print(obj.decodeAtIndex("ha22", 5)) # expect: h + print(obj.decodeAtIndex("a2345678999999999999999", 10)) # expect: a diff --git a/deepest_leaves_sum.cpp b/deepest_leaves_sum.cpp new file mode 100644 index 0000000..bb84f4c --- /dev/null +++ b/deepest_leaves_sum.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + int deepestLeavesSum(TreeNode *root) { + int ans = 0, i; + queue<TreeNode *> q; + q.push(root); + while (q.size()) { + for (i = q.size() - 1, ans = 0; i >= 0; --i) { + TreeNode *node = q.front(); + q.pop(); + ans += node->val; + if (node->right) + q.push(node->right); + if (node->left) + q.push(node->left); + } + } + return ans; + } +}; + +int main() {} diff --git a/delete_col_sorted.cpp b/delete_col_sorted.cpp new file mode 100644 index 0000000..4954032 --- /dev/null +++ b/delete_col_sorted.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + int minDeletionSize(vector<string> &strs) { + int ans = 0; + if (strs.empty()) + return ans; + for (auto i = 0; i < strs[0].size(); ++i) + for (auto j = 1; j < strs.size(); ++j) + if (strs[j - 1][i] > strs[j][i]) { + ++ans; + break; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<string> strs1 = {"cba", "daf", "ghi"}, strs2 = {"a", "b"}, + strs3 = {"zyx", "wvu", "tsr"}; + cout << obj.minDeletionSize(strs1) << endl; + cout << obj.minDeletionSize(strs2) << endl; + cout << obj.minDeletionSize(strs3) << endl; +} diff --git a/delete_col_sorted.rs b/delete_col_sorted.rs new file mode 100644 index 0000000..1b7d24a --- /dev/null +++ b/delete_col_sorted.rs @@ -0,0 +1,25 @@ +struct Solution; + +impl Solution { + pub fn min_deletion_size(strs: Vec<String>) -> i32 { + let mut ans = 0; + let mut new_strs: Vec<Vec<char>> = Vec::new(); + for i in 0..strs.len() { + new_strs.push(strs[i].chars().collect::<Vec<char>>()); + } + for i in 0..new_strs[0].len() { + for j in 1..new_strs.len() { + if new_strs[j - 1][i] > new_strs[j][i] { + ans += 1; + break + } + } + } + ans + } +} + +fn main() { + let strs = vec![String::from("cba"), String::from("daf"), String::from("ghi")]; + print!("{}", Solution::min_deletion_size(strs)); +} diff --git a/delete_leaves_given_value.c b/delete_leaves_given_value.c new file mode 100644 index 0000000..1ad048e --- /dev/null +++ b/delete_leaves_given_value.c @@ -0,0 +1,25 @@ +// 1325. Delete Leaves With a Given Value +#include "leetcode.h" + +/* + * given a binary tree 'root' and an integer 'target', delete all the leaf nodes + * with value 'target'. note that once you delete a leaf node with value + * 'target', if its parent node becomes a leaf node and has the value 'target', + * it should also be deleted (you need to continue doing that until you cannot) + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +struct TreeNode *removeLeafNodes(struct TreeNode *root, int target) { + if (!root) + return NULL; + root->left = removeLeafNodes(root->left, target); + root->right = removeLeafNodes(root->right, target); + if (!root->left && !root->right && root->val == target) + return NULL; + return root; +} diff --git a/delete_leaves_given_value.py b/delete_leaves_given_value.py new file mode 100644 index 0000000..e5c6be7 --- /dev/null +++ b/delete_leaves_given_value.py @@ -0,0 +1,30 @@ +# 1325. Delete Leaves With a Given Value + +""" +given a binary tree 'root' and an integer 'target', delete all the leaf nodes +with value 'target'. note that once you delete a leaf node with value +'target', if its parent node becomes a leaf node and has the value 'target', +it should also be deleted (you need to continue doing that until you cannot) +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def removeLeafNodes(self, root, target): + """ + :type root: TreeNode + :type target: int + :rtype: TreeNode + """ + if root.left: + root.left = self.removeLeafNodes(root.left, target) + if root.right: + root.right = self.removeLeafNodes(root.right, target) + return None if root.left == root.right and root.val == target else root diff --git a/delete_middle_node.cpp b/delete_middle_node.cpp new file mode 100644 index 0000000..1493046 --- /dev/null +++ b/delete_middle_node.cpp @@ -0,0 +1,16 @@ +#include "leetcode.h" + +class Solution { +public: + ListNode *deleteMiddle(ListNode *head) { + if (head->next == nullptr) + return nullptr; + auto slow = head, fast = head->next->next; + while (fast != nullptr && fast->next != nullptr) { + fast = fast->next->next; + slow = slow->next; + } + slow->next = slow->next->next; + return head; + } +}; diff --git a/delete_middle_node.rs b/delete_middle_node.rs new file mode 100644 index 0000000..289d8dd --- /dev/null +++ b/delete_middle_node.rs @@ -0,0 +1,52 @@ +pub struct Solution; +pub struct ListNode { + pub val: i32, + pub next: Option<Box<ListNode>> +} + +impl ListNode { + #[inline] + fn new(val: i32) -> self { + ListNode { + next: None, + val + } + } +} + +impl Solution { + pub fn delete_middle(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> { + let mut slowPtr = &head; + let mut fastPtr = &head; + let mut fakeHead = Box::new(ListNode::new(-1)); + let mut fakeTmp = &mut *fakeHead as *mut ListNode; + let mut slowPrevPtr = &mut *fakeHead as *mut ListNode; + while fastPtr.is_some() && (fastPtr).as_ref().unwrap().next.is_some() { + unsafe { + let mut next = Box::new(ListNode::new((slowPtr).as_ref().unwrap().val)); + let nextPtr = &mut *next as *mut ListNode; + (*fakeTmp).next = Some(next); + slowPrevPtr = fakeTmp; + fakeTmp = nextPtr; + slowPtr = &(slowPtr).as_ref().unwrap().next; + fastPtr = &(fastPtr).as_ref().unwrap().next; + if fastPtr.is_some() { + fastPtr = &(fastPtr).as_ref().unwrap().next; + } + } + } + slowPtr = &(slowPtr).as_ref().unwrap().next; + while slowPtr.is_some() { + unsafe { + let mut next = Box::new(ListNode::new((slowPtr).as_ref().unwrap().val)); + let nextPtr = &mut *next as *mut ListNode; + (*fakeTmp).next = Some(next); + fakeTmp = nextPtr; + slowPtr = &(slowPtr).as_ref().unwrap().next; + } + } + fakeHead.next + } +} + +fn main() {} diff --git a/delete_node_link_list.c b/delete_node_link_list.c new file mode 100644 index 0000000..71eab91 --- /dev/null +++ b/delete_node_link_list.c @@ -0,0 +1,27 @@ +// 237. Delete Node in a Linked List +#include "leetcode.h" + +/* + * there is a singly linked list 'head' and we want to delete a node 'node' in + * it. you are given the node to be deleted 'node'. you will not be given access + * to the first node of 'head'. all the values of the linked list are unique and + * it is guaranteed that the given node 'node' is not the last node in the + * linked list. delete the given node. note that by deleting the node, we do not + * mean removing it from memory. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +void deleteNode(struct ListNode *node) { + struct ListNode *tmp = node, *q = NULL; + while (tmp->next) { + q = tmp; + tmp->val = tmp->next->val; + tmp = tmp->next; + } + q->next = NULL; + free(tmp); +} diff --git a/delete_node_link_list.cpp b/delete_node_link_list.cpp new file mode 100644 index 0000000..cefe915 --- /dev/null +++ b/delete_node_link_list.cpp @@ -0,0 +1,10 @@ +#include "leetcode.h" + +class Solution { +public: + void deleteNode(ListNode *node) { + auto next = node->next; + *node = *next; + delete next; + } +}; diff --git a/delete_node_link_list.py b/delete_node_link_list.py new file mode 100644 index 0000000..6bc4c7f --- /dev/null +++ b/delete_node_link_list.py @@ -0,0 +1,27 @@ +# 237. Delete Node in a Linked List + +""" +there is a singy linked list 'head' and we want to delete a node 'node' in +it. you are given the node to be deleted 'node'. you will not be given access +to the first node of 'head'. all the values of the linked list are unique and +it is guaranteed that the given node 'node' is not the last node in the +linked list. delete the given node. note that by deleting the node, we do not +mean removing it from memory. +""" + + +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, x): + self.val = x + self.next = None + + +class Solution(object): + def deleteNode(self, node): + """ + :type node: ListNode + :rtype: void Do not return anything, modify node in-place instead. + """ + node.val = node.next.val + node.next = node.next.next diff --git a/delete_operation_2string.cpp b/delete_operation_2string.cpp new file mode 100644 index 0000000..b6e38e4 --- /dev/null +++ b/delete_operation_2string.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + int minDistance(string word1, string word2) { + int m = word1.size(), n = word2.size(); + if (m < n) { + swap(word1, word2); + swap(n, m); + } + vector<int> last(n + 1, 0), curr(n + 1, 0); + for (char char1 : word1) { + for (int i = 0; i < n; i++) + curr[i + 1] = + char1 == word2[i] ? last[i] + 1 : max(curr[i], last[i + 1]); + swap(last, curr); + } + return m + n - 2 * last[n]; + } +}; + +int main() { + Solution obj; + string word1 = "sea", word2 = "eat"; + cout << obj.minDistance(word1, word2); +} diff --git a/design_circular_queue.cpp b/design_circular_queue.cpp new file mode 100644 index 0000000..697e17b --- /dev/null +++ b/design_circular_queue.cpp @@ -0,0 +1,53 @@ +struct Node { +public: + int value; + Node *next; + Node(int v, Node *n = nullptr) { + value = v; + next = n; + } +}; + +class MyCircularQueue { +public: + MyCircularQueue(int k) { maxSize = k; } + bool enQueue(int value) { + if (isFull()) + return false; + Node *newNode = new Node(value); + if (isEmpty()) + head = newNode, tail = newNode; + else + tail->next = newNode, tail = tail->next; + size++; + return true; + } + bool deQueue() { + if (isEmpty()) + return false; + Node *rem = head; + head = head->next; + delete rem; + size--; + return true; + } + int Front() { return isEmpty() ? -1 : head->value; } + int Rear() { return isEmpty() ? -1 : tail->value; } + bool isEmpty() { return size == 0; } + bool isFull() { return size == maxSize; } + +private: + int maxSize, size = 0; + Node *head = new Node(0), *tail = new Node(0); +}; + +int main() { + int k, value; + MyCircularQueue *obj = new MyCircularQueue(k); + bool param_1 = obj->enQueue(value); + bool param_2 = obj->deQueue(); + int param_3 = obj->Front(); + int param_4 = obj->Rear(); + bool param_5 = obj->isEmpty(); + bool param_6 = obj->isFull(); +} diff --git a/design_food_rating_sys.cpp b/design_food_rating_sys.cpp new file mode 100644 index 0000000..bdfef0c --- /dev/null +++ b/design_food_rating_sys.cpp @@ -0,0 +1,40 @@ +// 2353. Design a Food Rating System +#include "leetcode.h" + +/* + * design a food rating system that can do the following: + * - modify the rating of a food item listed in the system + * - return the highest rated food item for a type of cuisine in the system + * implement the 'FoodRatings' class. note that a string 'x' is + * lexicographically smaller than string 'y' if 'x' comes before 'y' in + * dictionary order, that is, either 'x' is a prefix of 'y' or if 'i' is the + * first position such that 'x[i] != y[i], then x[i] comes beofre y[i] in + * alpabetic order + */ + +class FoodRatings { +private: + unordered_map<string_view, string_view> f2c; + unordered_map<string_view, int> f2r; + unordered_map<string_view, set<pair<int, string>>> c2r; + +public: + FoodRatings(vector<string> &foods, vector<string> &cuisines, + vector<int> &ratings) { + for (int i = 0; i < foods.size(); i++) { + f2c[foods[i]] = cuisines[i]; + f2r[foods[i]] = ratings[i]; + c2r[cuisines[i]].emplace(-ratings[i], foods[i]); + } + } + + void changeRating(string food, int newRating) { + int r = exchange(f2r[food], newRating); + auto &c = f2c[food]; + auto it = c2r.find(c); + it->second.erase({-r, food}); + it->second.emplace(-newRating, food); + } + + string highestRated(string cuisine) { return begin(c2r[cuisine])->second; } +}; diff --git a/design_food_rating_sys.py b/design_food_rating_sys.py new file mode 100644 index 0000000..4c9268c --- /dev/null +++ b/design_food_rating_sys.py @@ -0,0 +1,50 @@ +# 2353. Design a Food Rating System +from sortedcontainers import SortedSet + +""" +design a food rating system that can do the following: +- modify the rating of a food item listed in the system +- return the highest rated food item for a type of cuisine in the system +implement the 'FoodRatings' class. note that a string 'x' is +lexicographically smaller than string 'y' if 'x' comes before 'y' in +dictionary order, that is, either 'x' is a prefix of 'y' or if 'i' is the +first position such that 'x[i] != y[i], then x[i] comes beofre y[i] in +alpabetic order +""" + + +class FoodRatings(object): + def __init__(self, foods, cuisines, ratings): + """ + :type foods: List[str] + :type cuisines: List[str] + :type ratings: List[int] + """ + self.food_rating_map = {} + self.food_cuisine_map = {} + self.cuisine_food_map = defaultdict(SortedSet) + + for i in range(len(foods)): + self.food_rating_map[foods[i]] = ratings[i] + self.food_cuisine_map[foods[i]] = cuisines[i] + self.cuisine_food_map[cuisines[i]].add((-ratings[i], foods[i])) + + def changeRating(self, food, newRating): + """ + :type food: str + :type newRating: int + :rtype: None + """ + cuisine_name = self.food_cuisine_map[food] + old_element = (-self.food_rating_map[food], food) + self.cuisine_food_map[cuisine_name].remove(old_element) + self.food_rating_map[food] = newRating + self.cuisine_food_map[cuisine_name].add((-newRating, food)) + + def highestRated(self, cuisine): + """ + :type cuisine: str + :rtype: str + """ + highest_rated = self.cuisine_food_map[cuisine][0] + return highest_rated[1] diff --git a/design_graph_short_path.c b/design_graph_short_path.c new file mode 100644 index 0000000..4503785 --- /dev/null +++ b/design_graph_short_path.c @@ -0,0 +1,64 @@ +// 2642. Design Graph With Shortest Path Calculator +#include "leetcode.h" + +/* + * there is a directed weighted graph that consists of 'n' nodes numbered from 0 + * to 'n - 1'. the edges of the graph are initially represented by the given + * array 'edges' where 'edges[i] = [from[i], to[i], edge_cost[i]]' meaning that + * there is an edge from 'from[i]' to 'to[i]' with the cost 'edge_cost[i]'. + */ + +typedef struct { + int **g; + int v; +} Graph; + +Graph *graphCreate(int n, int **edges, int edges_size, int *edges_col_size) { + Graph *graph = (Graph *)malloc(sizeof(Graph)); + graph->g = (int **)malloc(n * sizeof(int *)); + for (int i = 0; i < n; i++) { + graph->g[i] = (int *)malloc(n * sizeof(int)); + for (int j = 0; j < n; j++) + graph->g[i][j] = 0; + } + for (int i = 0; i < edges_size; i++) { + int *edge = edges[i]; + graph->g[edge[0]][edge[1]] = edge[2]; + } + graph->v = n; + return graph; +} + +void graphAddEdge(Graph *obj, int *edge, int edge_size) { + obj->g[edge[0]][edge[1]] = edge[2]; +} + +int graphShortestPath(Graph *obj, int node1, int node2) { + int *dist = (int *)malloc(obj->v * sizeof(int)); + for (int i = 0; i < obj->v; i++) + dist[i] = 1000000000; + dist[node1] = 0; + bool *vis = (bool *)malloc(obj->v * sizeof(bool)); + for (int i = 0; i < obj->v; i++) + vis[i] = false; + for (int i = 0; i < obj->v - 1; i++) { + int u = -1; + for (int k = 0; obj->v; k++) + if (!vis[k] && (u == -1 || dist[k] < dist[u])) + u = k; + vis[u] = true; + for (int j = 0; j < obj->v; j++) + if (obj->g[u][j] && !vis[j]) + dist[j] = (dist[j] < dist[u] + obj->g[u][i]) ? dist[j] + : dist[u] + obj->g[u][j]; + } + int res = (dist[node2] == 1000000000) ? -1 : dist[node2]; + free(dist), free(vis); + return res; +} + +void graphFree(Graph *obj) { + for (int i = 0; i < obj->v; i++) + free(obj->g[i]); + free(obj->g), free(obj); +} diff --git a/design_graph_short_path.py b/design_graph_short_path.py new file mode 100644 index 0000000..d41a51d --- /dev/null +++ b/design_graph_short_path.py @@ -0,0 +1,51 @@ +# 2642. Design Graph With Shortest Path Calculator + +""" +there is a directed weighted graph that consists of 'n' nodes numbered from 0 +to 'n - 1'. the edges of the graph are initially represented by the given +array 'edges' where 'edges[i] = [from[i], to[i], edge_cost[i]]' meaning that +there is an edge from 'from[i]' to 'to[i]' with the cost 'edge_cost[i]'. +""" + + +class Graph(object): + def __init__(self, n, edges): + """ + :type n: int + :type edges: List[List[int]] + """ + self.N = n + self.INF = 10**19 + adj_list = collections.defaultdict(list) + for u, v, wt in edges: + adj_list[u].append((v, wt)) + self.adj_list = adj_list + + def addEdge(self, edge): + """ + :type edge: List[int] + :rtype: None + """ + self.adj_list[edge[0]].append((edge[1], edge[2])) + + def shortestPath(self, node1, node2): + """ + :type node1: int + :type node2: int + :rtype: int + """ + h = [] + heapq.heappush(h, (0, node1)) + dist = [self.INF] * self.N + dist[node1] = 0 + while len(h): + d, u = heapq.heappop(h) + if u == node2: + return d + if dist[u] < d: + continue + for v, wt in self.adj_list[u]: + if dist[v] > dist[u] + wt: + dist[v] = dist[u] + wt + heapq.heappush(h, (dist[v], v)) + return -1 diff --git a/design_hashmap.c b/design_hashmap.c new file mode 100644 index 0000000..0b3d50a --- /dev/null +++ b/design_hashmap.c @@ -0,0 +1,92 @@ +// 706. Design HashMap +#include <stdio.h> +#include <stdlib.h> + +/* + * design a hashmap without usin any built-in hash table libraries. implement + * the 'MyHashMap' class: + * - myHashMapCreate() initialises the object with an empty map + * - put() inserts a key, value pair into the hashmap. if the key already exists + * in the map, update the corresponding value + * - get() returns the value to which the specified key is mapped, or -1 if this + * map contains no mapping for the key + * - remove() removes the key and its corresponding value if the map contains + * the mapping for the key + */ + +typedef struct { + int **map; + int size; +} MyHashMap; + +MyHashMap *myHashMapCreate() { + MyHashMap *res = malloc(sizeof(MyHashMap)); + res->size = 10000; + res->map = calloc((res->size), sizeof(int *)); + return res; +} + +void myHashMapPut(MyHashMap *obj, int key, int val) { + int d = key, n = obj->size; + while (1) { + if (!obj->map[d % n]) { + obj->map[d % n] = malloc(2 * sizeof(int)); + obj->map[d % n][0] = key; + obj->map[d % n][1] = val; + break; + } else if (obj->map[d % n][0] == key) { + obj->map[d % n][1] = val; + break; + } else { + d++; + } + } +} + +int myHashMapGet(MyHashMap *obj, int key) { + int d = key, n = obj->size; + while (1) { + if (!obj->map[d % n]) + return -1; + else if (obj->map[d % n][0] == key) + return obj->map[d % n][1]; + else + d++; + } + return -1; +} + +void myHashMapRemove(MyHashMap *obj, int key) { + int d = key, n = obj->size; + while (1) { + if (!obj->map[d % n]) + break; + else if (obj->map[d % n][0] == key) { + obj->map[d % n][0] = -1; + break; + } else { + d++; + } + } +} + +void myHashMapFree(MyHashMap *obj) { + int n = obj->size; + for (int i = 0; i < n; i++) + if (obj->map[i]) + free(obj->map[i]); + free(obj->map); + free(obj); +} + +int main() { + MyHashMap *obj = myHashMapCreate(); + myHashMapPut(obj, 1, 1); + myHashMapPut(obj, 2, 2); + printf("%d\n", myHashMapGet(obj, 1)); // expect: 1 + printf("%d\n", myHashMapGet(obj, 3)); // expect: -1 + myHashMapPut(obj, 2, 1); + printf("%d\n", myHashMapGet(obj, 2)); // expect: 1 + myHashMapRemove(obj, 2); + printf("%d\n", myHashMapGet(obj, 2)); // expect: -1 +} diff --git a/design_hashmap.cpp b/design_hashmap.cpp new file mode 100644 index 0000000..6b7ce3d --- /dev/null +++ b/design_hashmap.cpp @@ -0,0 +1,12 @@ +#include "leetcode.h" + +class MyHashMap { +public: + int data[1000001]; + MyHashMap() { fill(data, data + 1000000, -1); } + void put(int key, int value) { data[key] = value; } + int get(int key) { return data[key]; } + void remove(int key) { data[key] = -1; } +}; + +int main() {} diff --git a/design_hashmap.py b/design_hashmap.py new file mode 100644 index 0000000..44a70cc --- /dev/null +++ b/design_hashmap.py @@ -0,0 +1,28 @@ +# 706. Design HashMap + +""" +design a hashmap without usin any built-in hash table libraries. implement +the 'MyHashMap' class: +- myHashMapCreate() initialises the object with an empty map +- put() inserts a key, value pair into the hashmap. if the key already exists +in the map, update the corresponding value +- get() returns the value to which the specified key is mapped, or -1 if this +map contains no mapping for the key +- remove() removes the key and its corresponding value if the map contains +the mapping for the key +""" + + +class MyHashMap(object): + def __init__(self): + self.data = [None] * 1000001 + + def put(self, key, value): + self.data[key] = value + + def get(self, key): + value = self.data[key] + return value if value != None else -1 + + def remove(self, key): + self.data[key] = None diff --git a/design_hashset.c b/design_hashset.c new file mode 100644 index 0000000..88f95a9 --- /dev/null +++ b/design_hashset.c @@ -0,0 +1,108 @@ +// 705. Design HashSet +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * design a 'HashSet' without using any built-in hash table libraries. implement + * 'MyHashSet' class: + * - 'void add(key)' inserts the value 'key' into the HashSet + * - 'bool contains(key)' returns whether the value 'key' exists or not + * - 'void remove(key)' removes the value 'key'. does nothing if 'key' does not + * exist + */ + +#define TABLE_SIZE 500 + +struct Node { + struct Node *next; + int val; +}; + +typedef struct { + struct Node *table[TABLE_SIZE]; +} MyHashSet; + +MyHashSet *myHashSetCreate() { + MyHashSet *obj = (MyHashSet *)malloc(sizeof(MyHashSet)); + if (obj) + memset(obj, 0, sizeof(MyHashSet)); + return obj; +} + +void myHashSetAdd(MyHashSet *obj, int key) { + int idx = key % TABLE_SIZE; + struct Node **added_node; + struct Node *n = obj->table[idx]; + if (!n) + added_node = &obj->table[idx]; + else + while (n) { + if (n->val == key) + return; + if (!n->next) { + added_node = &n->next; + break; + } + n = n->next; + } + *added_node = (struct Node *)malloc(sizeof(struct Node)); + (*added_node)->val = key; + (*added_node)->next = NULL; +} + +void myHashSetRemove(MyHashSet *obj, int key) { + int idx = key % TABLE_SIZE; + struct Node *n = obj->table[idx], *t; + if (n && n->val == key) { + obj->table[idx] = n->next; + free(n); + } else { + while (n) { + if (n->next && n->next->val == key) { + t = n->next; + n->next = t->next; + free(t); + break; + } + n = n->next; + } + } +} + +bool myHashSetContains(MyHashSet *obj, int key) { + int idx = key % TABLE_SIZE; + struct Node *n = obj->table[idx]; + while (n) { + if (n->val == key) + return true; + n = n->next; + } + return false; +} + +void myHashSetFree(MyHashSet *obj) { + struct Node *n, *t; + for (int i = 0; i < TABLE_SIZE; i++) { + n = obj->table[i]; + while (n) { + t = n->next; + free(n); + n = t; + } + } + free(obj); +} + +int main() { + MyHashSet *obj = myHashSetCreate(); + myHashSetAdd(obj, 1); + myHashSetAdd(obj, 2); + printf("%d\n", myHashSetContains(obj, 1)); // expect: 1 + printf("%d\n", myHashSetContains(obj, 3)); // expect: 0 + myHashSetAdd(obj, 2); + printf("%d\n", myHashSetContains(obj, 2)); // expect: 1 + myHashSetRemove(obj, 2); + printf("%d\n", myHashSetContains(obj, 2)); // expect: 0 +} diff --git a/design_hashset.cpp b/design_hashset.cpp new file mode 100644 index 0000000..52d1097 --- /dev/null +++ b/design_hashset.cpp @@ -0,0 +1,12 @@ +#include "leetcode.h" + +class MyHashSet { +public: + vector<bool> ans; + MyHashSet() { ans.resize(1e6 + 1, false); } + void add(int key) { ans[key] = true; } + void remove(int key) { ans[key] = false; } + bool contains(int key) { return ans[key]; } +}; + +int main() {} diff --git a/design_parking_system.c b/design_parking_system.c new file mode 100644 index 0000000..3a28ad5 --- /dev/null +++ b/design_parking_system.c @@ -0,0 +1,51 @@ +// 1603. Design Parking System +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * design a parking system for a parking lot. the parking lot has three kinds of + * parking spaces: big, medium, and small. with a fixed number of slots for each + * size. implement the 'ParkingSystem' class: + * - 'ParkingSystem(big, medium, small)' initialises object of the + * 'ParkingSystem' class the number of slots for each parking space are given as + * part of the constructor + * - 'bool addCar(car_type)' checks whether there is a parking space of + * 'car_type' for the car that wants to get into the parking lot. 'car_type' can + * be of three kinds: big, medium, or small, which are represented by 1, 2, or + * 3, respectively. a car can only park in a parking space of its 'car_type'. if + * there is no space available, return false, else park the car in that size + * space and return true + */ + +typedef struct { + int b; + int m; + int s; +} ParkingSystem; + +ParkingSystem *parkingSystemCreate(int big, int medium, int small) { + ParkingSystem *obj = malloc(sizeof(ParkingSystem)); + obj->b = big; + obj->m = medium; + obj->s = small; + return obj; +} + +bool parkingSystemAddCar(ParkingSystem *obj, int car_type) { + if (car_type == 1) + return obj->b-- > 0; + if (car_type == 2) + return obj->m-- > 0; + return obj->s-- > 0; +} + +void parkingSystemFree(ParkingSystem *obj) { free(obj); } + +int main() { + ParkingSystem *obj = parkingSystemCreate(1, 1, 0); + printf("%d\n", parkingSystemAddCar(obj, 1)); // expect: 1 + printf("%d\n", parkingSystemAddCar(obj, 2)); // expect: 1 + printf("%d\n", parkingSystemAddCar(obj, 3)); // expect: 0 + printf("%d\n", parkingSystemAddCar(obj, 1)); // expect: 0 +} diff --git a/design_parking_system.cpp b/design_parking_system.cpp new file mode 100644 index 0000000..5cfaf74 --- /dev/null +++ b/design_parking_system.cpp @@ -0,0 +1,40 @@ +// 1603. Design Parking System +#include "leetcode.h" + +/* + * design a parking system for a parking lot. the parking lot has three kinds of + * parking spaces: big, medium, and small. with a fixed number of slots for each + * size. implement the 'ParkingSystem' class: + * - 'ParkingSystem(big, medium, small)' initialises object of the + * 'ParkingSystem' class the number of slots for each parking space are given as + * part of the constructor + * - 'bool addCar(car_type)' checks whether there is a parking space of + * 'car_type' for the car that wants to get into the parking lot. 'car_type' can + * be of three kinds: big, medium, or small, which are represented by 1, 2, or + * 3, respectively. a car can only park in a parking space of its 'car_type'. if + * there is no space available, return false, else park the car in that size + * space and return true + */ + +class ParkingSystem { +public: + vector<int> vehicle; + ParkingSystem(int big, int medium, int small) { + vehicle = {big, medium, small}; + } + bool addCar(int car_type) { + if (vehicle[car_type - 1]) { + vehicle[car_type - 1] -= 1; + return true; + } + return false; + } +}; + +int main() { + ParkingSystem *obj = new ParkingSystem(1, 1, 0); + printf("%d\n", obj->addCar(1)); // expect: 1 + printf("%d\n", obj->addCar(2)); // expect: 1 + printf("%d\n", obj->addCar(3)); // expect: 0 + printf("%d\n", obj->addCar(1)); // expect: 0 +} diff --git a/design_underground_system.c b/design_underground_system.c new file mode 100644 index 0000000..2f8b88a --- /dev/null +++ b/design_underground_system.c @@ -0,0 +1,97 @@ +// 1396. Design Underground System +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + */ + +typedef struct { + int id; + int s; + int e; + char depart[11]; + char destina[11]; +} TravelInfo; + +typedef struct { + TravelInfo data[20000]; + int custom; +} UndergroundSystem; + +UndergroundSystem *undergroundSystemCreate() { + UndergroundSystem *obj = + (UndergroundSystem *)malloc(sizeof(UndergroundSystem)); + memset(obj->data, 0, sizeof(TravelInfo) * 2000); + obj->custom = 0; + return obj; +} + +void undergroundSystemCheckIn(UndergroundSystem *obj, int id, + char *station_name, int t) { + obj->data[obj->custom].id = id; + strncpy(obj->data[obj->custom].depart, station_name, strlen(station_name)); + obj->data[obj->custom].depart[strlen(station_name)] = NULL; + obj->data[obj->custom].s = t; + obj->data[obj->custom].destina[0] = NULL; + obj->data[obj->custom].e = 0; + obj->custom++; +} + +void undergroundSystemCheckOut(UndergroundSystem *obj, int id, + char *station_name, int t) { + for (int i = 0; i < obj->custom; i++) + if (obj->data[i].id == id && !obj->data[i].e) { + strncpy(obj->data[i].destina, station_name, strlen(station_name)); + obj->data[obj->custom].destina[strlen(station_name)] = NULL; + obj->data[i].e = t; + break; + } +} + +double undergroundSystemGetAverageTime(UndergroundSystem *obj, + char *start_station, char *end_station) { + double res = 0, cnt = 0; + for (int i = 0; i < obj->custom; i++) + if (!strcmp(obj->data[i].depart, start_station) & + !strcmp(obj->data[i].destina, end_station)) { + cnt++; + res += (obj->data[i].e - obj->data[i].s); + } + return res / cnt; +} + +void undergroundSystemFree(UndergroundSystem *obj) { free(obj); } + +int main() { + UndergroundSystem *obj = undergroundSystemCreate(); + undergroundSystemCheckIn(obj, 45, "Leyton", 3); + undergroundSystemCheckIn(obj, 32, "Paradise", 8); + undergroundSystemCheckOut( + obj, 45, "Waterloo", + 15); // Customer 45 "Leyton" -> "Waterloo" in 15-3 = 12 + undergroundSystemCheckOut( + obj, 27, "Waterloo", + 20); // Customer 27 "Leyton" -> "Waterloo" in 20-10 = 10 + undergroundSystemCheckOut( + obj, 32, "Cambridge", + 22); // Customer 32 "Paradise" -> "Cambridge" in 22-8 = 14 + printf("%f\n", undergroundSystemGetAverageTime( + obj, "Paradise", + "Cambridge")); // return 14.00000. One trip "Paradise" -> + // "Cambridge", (14) / 1 = 14 + printf("%f\n", + undergroundSystemGetAverageTime( + obj, "Leyton", "Waterloo")); // return 11.00000. Two trips "Leyton" + // -> "Waterloo", (10 + 12) / 2 = 11 + undergroundSystemCheckIn(obj, 10, "Leyton", 24); + printf("%f\n", undergroundSystemGetAverageTime( + obj, "Leyton", "Waterloo")); // return 11.00000 + undergroundSystemCheckOut( + obj, 10, "Waterloo", + 38); // Customer 10 "Leyton" -> "Waterloo" in 38-24 = 14 + printf("%f\n", undergroundSystemGetAverageTime( + obj, "Leyton", + "Waterloo")); // return 12.00000. Three trips "Leyton" -> + // "Waterloo", (10 + 12 + 14) / 3 = 12 +} diff --git a/design_underground_system.cpp b/design_underground_system.cpp new file mode 100644 index 0000000..f0904d2 --- /dev/null +++ b/design_underground_system.cpp @@ -0,0 +1,20 @@ +class UndergroundSystem { +public: + unordered_map<int, pair<string, int>> checkIns; + unordered_map<string, pair<int, int>> routes; + UndergroundSystem() {} + void checkIn(int id, string stationName, int t) { + checkIns[id] = {stationName, t}; + } + void checkOut(int id, string stationName, int t) { + auto [stn, start] = checkIns[id]; + checkIns.erase(id); + string route = stn + "," + stationName; + routes[route].first++; + routes[route].second += t - start; + } + double getAverageTime(string startStation, string endStation) { + auto &[count, sum] = routes[startStation + "," + endStation]; + return (double)sum / count; + } +}; diff --git a/destination_city.c b/destination_city.c new file mode 100644 index 0000000..1c48eec --- /dev/null +++ b/destination_city.c @@ -0,0 +1,28 @@ +// 1436. Destination City +#include "leetcode.h" + +/* + * given the array 'paths' where 'paths[i] = [citya[i], cityb[i]]' means there + * exists a direct path going from 'citya[i]' to 'cityb[i]'. return the + * destination city that is the city without any path outgoing to another city. + * it is guaranteed that the graph of paths forms a line without any loop, + * therefore there will be exactly one destination. + */ + +char *destCity(char ***paths, int paths_size, int *paths_col_size) { + char *dest = paths[0][1]; + for (int i = 1; i < paths_size; i++) + if (!strcmp(paths[i][0], dest)) { + dest = paths[i][1]; + i = 0; + } + return dest; +} + +int main() { + char ***p1 = { + {"London", "New York"}, {"New York", "Lima"}, {"Lima", "Sao Paulo"}}; + char ***p2 = {{"B", "C"}, {"D", "B"}, {"C", "A"}}; + printf("%s\n", destCity(p1, 3, NULL)); + printf("%s\n", destCity(p2, 3, NULL)); +} diff --git a/destination_city.py b/destination_city.py new file mode 100644 index 0000000..b34bfbc --- /dev/null +++ b/destination_city.py @@ -0,0 +1,35 @@ +# 1436. Destination City + +""" +given the array 'paths' where 'paths[i] = [citya[i], cityb[i]]' means there +exists a direct path going from 'citya[i]' to 'cityb[i]'. return the +destination city that is the city without any path outgoing to another city. +it is guaranteed that the graph of paths forms a line without any loop, +therefore there will be exactly one destination. +""" + + +class Solution(object): + def destCity(self, paths): + """ + :type paths: List[List[str]] + :rtype: str + """ + cities = set() + for i in paths: + cities.add(i[0]) + for i in paths: + dest = i[1] + if dest not in cities: + return dest + return "" + + +if __name__ == "__main__": + obj = Solution() + print( + obj.destCity( + paths=[["London", "New York"], ["New York", "Lima"], ["Lima", "Sao Paulo"]] + ) + ) + print(obj.destCity(paths=[["B", "C"], ["D", "B"], ["C", "A"]])) diff --git a/detect_capital.cpp b/detect_capital.cpp new file mode 100644 index 0000000..27aa46b --- /dev/null +++ b/detect_capital.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + bool detectCapitalUse(string word) { + bool firstCaps = isupper(word[0]), allCaps = true, allLower = true; + for (int i = 1; i < word.size(); i++) { + if (isupper(word[i])) + allLower = false; + else + allCaps = false; + } + return (firstCaps && allCaps) || allLower; + } +}; + +int main() { + Solution obj; + testBool(obj.detectCapitalUse("USA")); // true + testBool(obj.detectCapitalUse("FlaG")); // false +} diff --git a/detect_capital.rs b/detect_capital.rs new file mode 100644 index 0000000..454381d --- /dev/null +++ b/detect_capital.rs @@ -0,0 +1,20 @@ +struct Solution; + +impl Solution { + pub fn detect_capital_use(word: String) -> bool { + let v: Vec<char> = word.chars().collect(); + if v[0].is_lowercase() { + return v.iter().all(|&c| c.is_lowercase()); + } + if v.len() > 1 { + let b = v[1].is_lowercase(); + return v.iter().skip(1).all(|&c| c.is_lowercase() == b); + } + true + } +} + +fn main() { + let word = String::from("USA"); + print!("{}", Solution::detect_capital_use(word)); //true +} diff --git a/determine_cell_reachable.c b/determine_cell_reachable.c new file mode 100644 index 0000000..5f0412c --- /dev/null +++ b/determine_cell_reachable.c @@ -0,0 +1,21 @@ +// 2849. Determine if a Cell Is Reachable at a Given Time +#include "leetcode.h" + +/* + * given four integers, and a signed integer 't'. in an infinite 2d grid, you + * start at the cell '(sx, sy)'. eachh second you must move to any of its + * ajacent cells. return 'true' if you can reach cell '(fx, fy)' after exactly + * 't' seconds or 'false' otherwise. a cells adjacent cells are thhe 8 cells + * around it thhat shhhare at leastt one corner withh it. you can visit thhe + * same cell several times. + */ + +bool isReachableAtTime(int sx, int sy, int fx, int fy, int t) { + int min_step = fmax(abs(sx - fx), abs(sy - fy)); + return !min_step ? t != 1 : min_step <= t; +} + +int main() { + printf("%d\n", isReachableAtTime(2, 4, 7, 7, 6)); // expect: 1 + printf("%d\n", isReachableAtTime(3, 1, 7, 3, 3)); // expect: 0 +} diff --git a/determine_cell_reachable.py b/determine_cell_reachable.py new file mode 100644 index 0000000..4d3c20d --- /dev/null +++ b/determine_cell_reachable.py @@ -0,0 +1,30 @@ +# 2849. Determine if a Cell Is Reachable at a Given Time + +""" +given four integers, and a signed integer 't'. in an infinite 2d grid, you +start at the cell '(sx, sy)'. eachh second you must move to any of its +ajacent cells. return 'true' if you can reach cell '(fx, fy)' after exactly +'t' seconds or 'false' otherwise. a cells adjacent cells are thhe 8 cells +around it thhat shhhare at leastt one corner withh it. you can visit thhe +same cell several times. +""" + + +class Solution(object): + def isReachableAtTime(self, sx, sy, fx, fy, t): + """ + :type sx: int + :type sy: int + :type fx: int + :type fy: int + :type t: int + :rtype: bool + """ + need = max(abs(sx - fx), abs(sy - fy)) + return t >= need if need else t != 1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.isReachableAtTime(sx=2, sy=4, fx=7, fy=7, t=6)) + print(obj.isReachableAtTime(sx=3, sy=1, fx=7, fy=3, t=3)) diff --git a/determine_string_halves.c b/determine_string_halves.c new file mode 100644 index 0000000..5d18158 --- /dev/null +++ b/determine_string_halves.c @@ -0,0 +1,37 @@ +// 1704. Determine if String Halves Are Alike +#include "leetcode.h" + +/* + * given a string 's' of even length. split this string into two halves of equal + * lengths and let 'a' be the first half and 'b' be the second half. two strings + * are alike if they have the same number of vowels (a e i o u, A E I O U) + * notice that 's' contains uppercase and lowercase letters. return 'true' if a + * and b are alike, otherwise return false. + */ + +int check(char *s, int n) { + int ans = 0; + for (int i = 0; i < n; i++) { + if (s[i] >= 'a') { + if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || + s[i] == 'u') + ans++; + } else { + if (s[i] == 'A' || s[i] == 'E' || s[i] == 'I' || s[i] == 'O' || + s[i] == 'U') + ans++; + } + } + return ans; +} + +bool halvesAreAlike(char *s) { + int n = strlen(s); + return check(s, n / 2) == check(&s[n / 2], n / 2) ? 1 : 0; +} + +int main() { + char s1[] = {"book"}, s2[] = {"textbook"}; + printf("%d\n", halvesAreAlike(s1)); // expect: 1 + printf("%d\n", halvesAreAlike(s2)); // expect: 0 +} diff --git a/determine_string_halves.cpp b/determine_string_halves.cpp new file mode 100644 index 0000000..fd249e1 --- /dev/null +++ b/determine_string_halves.cpp @@ -0,0 +1,25 @@ +#include "leetcode.h" + +class Solution { + string vowels = "aeiouAEIOU"; + +public: + bool halvesAreAlike(string s) { + int mid = s.size() / 2, ans = 0; + for (int i = 0, j = mid; i < mid; i++, j++) { + if (~vowels.find(s[i])) + ans++; + if (~vowels.find(s[j])) + ans--; + } + return ans == 0; + } +}; + +int main() { + Solution obj; + if (obj.halvesAreAlike("book")) + cout << "true"; + else + cout << "false"; +} diff --git a/determine_string_halves.py b/determine_string_halves.py new file mode 100644 index 0000000..d20a7b9 --- /dev/null +++ b/determine_string_halves.py @@ -0,0 +1,28 @@ +# 1704. Determine if String Halves Are Alike + +""" +given a string 's' of even length. split this string into two halves of equal +lengths and let 'a' be the first half and 'b' be the second half. two strings +are alike if they have the same number of vowels (a e i o u, A E I O U) +notice that 's' contains uppercase and lowercase letters. return 'true' if a +and b are alike, otherwise return false. +""" + + +class Solution(object): + def halvesAreAlike(self, s): + vowels = set("aeiouAEIOU") + a = b = 0 + i, j = 0, len(s) - 1 + while i < j: + a += s[i] in vowels + b += s[j] in vowels + i += 1 + j -= 1 + return a == b + + +if __name__ == "__main__": + obj = Solution() + print(obj.halvesAreAlike("book")) # expect: True + print(obj.halvesAreAlike("textbook")) # expect: false diff --git a/determine_string_halves.rs b/determine_string_halves.rs new file mode 100644 index 0000000..f7f4303 --- /dev/null +++ b/determine_string_halves.rs @@ -0,0 +1,18 @@ +use std::collections::HashSet; +struct Solution; + +impl Solution { + pub fn halves_are_alike(s: String) -> bool { + let vowels: HashSet<char> = HashSet::from(['a','e','i','o','u','A','E','I','O','U']); + s.chars() + .enumerate() + .filter(|(_, c)| vowels.contains(c)) + .map(|(i, _)| (s.len() as i32 - 2 * (i as i32) - 1).signum()) + .sum::<i32>() == 0 + } +} + +fn main() { + let s = String::from("book"); + print!("{}", Solution::halves_are_alike(s)); +} diff --git a/determine_strings_close.cpp b/determine_strings_close.cpp new file mode 100644 index 0000000..89e2322 --- /dev/null +++ b/determine_strings_close.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" + +class Solution { +public: + bool closeStrings(string word1, string word2) { + if (word1.size() != word2.size()) + return false; + vector<int> c1(26), c2(26); + for (auto i = 0; i < word1.size(); ++i) { + ++c1[word1[i] - 'a']; + ++c2[word2[i] - 'a']; + } + if (!equal(begin(c1), end(c1), begin(c2), end(c2), + [](int a, int b) { return (bool)a == bool(b); })) + return false; + sort(begin(c1), end(c1)); + sort(begin(c2), end(c2)); + return c1 == c2; + } +}; + +int main() { + Solution obj; + if (obj.closeStrings("abc", "bca")) + cout << "true"; + else + cout << "false"; +} diff --git a/determine_strings_close.rs b/determine_strings_close.rs new file mode 100644 index 0000000..f293b6d --- /dev/null +++ b/determine_strings_close.rs @@ -0,0 +1,25 @@ +struct Solution; + +impl Solution { + pub fn close_strings(word1: String, word2: String) -> bool { + let (mut c1, mut c2) = ([0; 26], [0; 26]); + for &b in word1.as_bytes() { + c1[(b - b'a') as usize] += 1; + } + for &b in word2.as_bytes() { + c2[(b - b'a') as usize] += 1; + } + if (0..26).any(|i| (c1[i] > 0) != (c2[i] > 0)) { + return false; + } + c1.sort_unstable(); + c2.sort_unstable(); + c1 == c2 + } +} + +fn main() { + let word1 = String::from("abc"); + let word2 = String::from("bca"); + print!("{}", Solution::close_strings(word1, word2)); +} diff --git a/determine_two_str_close.c b/determine_two_str_close.c new file mode 100644 index 0000000..39b6d0a --- /dev/null +++ b/determine_two_str_close.c @@ -0,0 +1,45 @@ +// 1657. Determine if Two Strings Are Close +#include "leetcode.h" + +/* + * two strings are considered close if you can attain one from the other using + * the following operations. operation 1:swap any two existing characters. + * operation 2: transform every occurence of one exiting character into another + * existing character, and do the same with the other character. you can use the + * operations on either string as many times as necessary.given two strings 'w1' + * and 'w2', return true if 'w1' and 'w2' are close and false otherwise. + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +bool closeStrings(char *w1, char *w2) { + int n1 = strlen(w1), n2 = strlen(w2); + if (n1 != n2) + return false; + int *a1 = calloc(26, sizeof(int)), *a2 = calloc(26, sizeof(int)); + for (int i = 0; i < n1; i++) { + a1[w1[i] - 'a']++; + a2[w2[i] - 'a']++; + } + for (int i = 0; i < 26; i++) { + if (a1[i] == 0 && a2[i] != 0) + return false; + if (a2[i] == 0 && a1[i] != 0) + return false; + } + qsort(a1, 26, sizeof(int), cmp); + qsort(a2, 26, sizeof(int), cmp); + for (int i = 0; i < 26; i++) + if (a1[i] != a2[i]) + return false; + return true; +} + +int main() { + char *w11 = "abc", *w21 = "bca"; + char *w12 = "a", *w22 = "aa"; + char *w13 = "cabbba", *w23 = "abbccc"; + printf("%d\n", closeStrings(w11, w21)); // expect: 1 + printf("%d\n", closeStrings(w12, w22)); // expect: 0 + printf("%d\n", closeStrings(w13, w23)); // expect: 1 +} diff --git a/determine_two_str_close.py b/determine_two_str_close.py new file mode 100644 index 0000000..d0aedfb --- /dev/null +++ b/determine_two_str_close.py @@ -0,0 +1,41 @@ +# 1657. Determine if Two Strings Are Close + +""" +two strings are considered close if you can attain one from the other using +the following operations. operation 1:swap any two existing characters. +operation 2: transform every occurence of one exiting character into another +existing character, and do the same with the other character. you can use the +operations on either string as many times as necessary.given two strings 'w1' +and 'w2', return true if 'w1' and 'w2' are close and false otherwise. +""" + + +class Solution(object): + def closeStrings(self, word1, word2): + """ + :type word1: str + :type word2: str + :rtype: bool + """ + freq1 = [0] * 26 + freq2 = [0] * 26 + for char in word1: + freq1[ord(char) - ord("a")] += 1 + for char in word2: + freq2[ord(char) - ord("a")] += 1 + for i in range(26): + if (freq1[i] == 0 and freq2[i] != 0) or (freq2[i] == 0 and freq1[i] != 0): + return False + freq1.sort() + freq2.sort() + for i in range(26): + if freq1[i] != freq2[i]: + return False + return True + + +if __name__ == "__main__": + obj = Solution() + print(obj.closeStrings(word1="abc", word2="bca")) + print(obj.closeStrings(word1="a", word2="aa")) + print(obj.closeStrings(word1="cabbba", word2="abbccc")) diff --git a/detonate_max_bombs.c b/detonate_max_bombs.c new file mode 100644 index 0000000..ddf65c2 --- /dev/null +++ b/detonate_max_bombs.c @@ -0,0 +1,87 @@ +// 2101. Detonate the Maximum Bombs +#include <math.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given a list of bombs. the range of a bomb is defined as the area where its + * effect can be felt. this area is in the shape of a circle with the center as + * the location of the bomb. the bombs are represented by a 0-indexed 2d integer + * array 'bombs' where 'bombs[i] = [xi, yi, ri]'. 'xi' and 'yi' denote the x and + * y coordinates of the location of the i'th bomb, whereas 'ri' denotes the + * radius of its range. you may choose to detonate a single bomb. when a bomb is + * detonated, it will detonate all the bombs that lie in its range. these bombs + * will further detonate the bombs that lie in their ranges. given the list of + * 'bombs', return the max number of bombs that can be detonated + */ + +int maximumDetonation(int **bombs, int bombs_size, int *bombs_col_size) { + bool *check = calloc(bombs_size, sizeof(bool)); + bool **attach = malloc(bombs_size * sizeof(bool *)); + for (int i = 0; i < bombs_size; i++) + attach[i] = calloc(bombs_size, sizeof(bool)); + for (int i = 0; i < bombs_size; i++) { + attach[i][i] = true; + for (int j = i + 1; j < bombs_size; j++) { + int x = abs(bombs[i][0] - bombs[j][0]); + int y = abs(bombs[i][1] - bombs[j][1]); + long long dis = (long long)x * x + (long long)y * y; + if (dis <= (long long)bombs[i][2] * bombs[i][2]) + attach[i][j] = true; + if (dis <= (long long)bombs[j][2] * bombs[j][2]) + attach[j][i] = true; + } + } + int *stack1 = malloc(bombs_size * sizeof(int)); + int *stack2 = malloc(bombs_size * sizeof(int)); + int id1 = 0, id2 = 0, max = 1; + for (int i = 0; i < bombs_size; i++) { + check = calloc(bombs_size, sizeof(bool)); + int curr = 1; + check[i] = true; + stack1[id1] = i; + id1++; + while (id1 || id2) { + if (id1) { + for (int j = 0; j < id1; j++) { + int p = stack1[j]; + for (int k = 0; k < bombs_size; k++) { + if (attach[p][k] && !check[k]) { + curr++; + check[k] = true; + stack2[id2] = k; + id2++; + } + } + } + id1 = 0; + } else { + for (int j = 0; j < id2; j++) { + int p = stack2[j]; + for (int k = 0; k < bombs_size; k++) { + if (attach[p][k] && !check[k]) { + curr++; + check[k] = true; + stack1[id1] = k; + id1++; + } + } + } + id2 = 0; + } + } + max = fmax(max, curr); + } + return max; +} + +int main() { + int b1[2][3] = {{2, 1, 3}, {6, 1, 4}}, bs1 = 2, *bcs1; + int b2[2][5] = {{1, 1, 5}, {10, 10, 5}}, bs2 = 2, *bcs2; + int b3[5][3] = {{1, 2, 3}, {2, 3, 1}, {3, 4, 2}, {4, 5, 3}, {5, 6, 4}}, + bs3 = 5, *bcs3; + printf("%d\n", maximumDetonation(b1, bs1, bcs1)); // expect: 2 + printf("%d\n", maximumDetonation(b2, bs2, bcs2)); // expect: 1 + printf("%d\n", maximumDetonation(b3, bs3, bcs3)); // expect: 5 +} diff --git a/detonate_max_bombs.cpp b/detonate_max_bombs.cpp new file mode 100644 index 0000000..3a1e803 --- /dev/null +++ b/detonate_max_bombs.cpp @@ -0,0 +1,61 @@ +// 2101. Detonate the Maximum Bombs +#include "leetcode.h" + +/* + * given a list of bombs. the range of a bomb is defined as the area where its + * effect can be felt. this area is in the shape of a circle with the center as + * the location of the bomb. the bombs are represented by a 0-indexed 2d integer + * array 'bombs' where 'bombs[i] = [xi, yi, ri]'. 'xi' and 'yi' denote the x and + * y coordinates of the location of the i'th bomb, whereas 'ri' denotes the + * radius of its range. you may choose to detonate a single bomb. when a bomb is + * detonated, it will detonate all the bombs that lie in its range. these bombs + * will further detonate the bombs that lie in their ranges. given the list of + * 'bombs', return the max number of bombs that can be detonated + */ + +class Solution { + void dfs(vvd(int) & graph, vector<bool> &visited, int c, int i) { + visited[i] = true; + c++; + for (int j = 0; j < graph[i].size(); j++) + if (!visited[graph[i][j]]) + dfs(graph, visited, c, graph[i][j]); + } + +public: + int maximumDetonation(vvd(int) & bombs) { + int n = bombs.size(), ans = INT_MIN; + vvd(int) graph(n); + for (int i = 0; i < n; i++) { + long long int x1, y1, r1; + x1 = bombs[i][0]; + y1 = bombs[i][1]; + r1 = bombs[i][2]; + for (int j = 0; j < n; j++) + if (i != j) { + long long int x2, y2, r2; + x2 = abs(x1 - bombs[j][0]); + y2 = abs(y1 - bombs[j][1]); + if (x2 * x2 + y2 * y2 <= r1 * r1) + graph[i].push_back(j); + } + } + for (int i = 0; i < n; i++) { + int c = 0; + vector<bool> visited(n, false); + dfs(graph, visited, c, i); + ans = max(ans, c); + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) b1 = {{2, 1, 3}, {6, 1, 4}}; + vvd(int) b2 = {{1, 1, 5}, {10, 10, 5}}; + vvd(int) b3 = {{1, 2, 3}, {2, 3, 1}, {3, 4, 2}, {4, 5, 3}, {5, 6, 4}}; + printf("%d\n", obj.maximumDetonation(b1)); // expect: 2 + printf("%d\n", obj.maximumDetonation(b2)); // expect: 1 + printf("%d\n", obj.maximumDetonation(b3)); // expect: 5 +} diff --git a/diameter_binay_tree.c b/diameter_binay_tree.c new file mode 100644 index 0000000..8129d07 --- /dev/null +++ b/diameter_binay_tree.c @@ -0,0 +1,30 @@ +// 543. Diameter of Binary Tree +#include "leetcode.h" + +/* + * given the 'root' of a binary tree, return the length of the diameter of the + * tree. the diameter of a binary tree is the length of the longest path between + * any two nodes in a tree. this path may or may not pass through the 'root'. + * the length of a path between two nodes is represented by the number of edges + * between them + */ + +struct TreeNode { + int val; + struct TreeNode *left, *right; +}; + +int between_diameter(struct TreeNode *root, int *diameter) { + if (!root) + return 0; + int left_height = between_diameter(root->left, diameter); + int right_height = between_diameter(root->right, diameter); + int curr = left_height + right_height; + *diameter = fmax(*diameter, curr); + return fmax(left_height, right_height) + 1; +} + +int diameterOfBinaryTree(struct TreeNode *root) { + int diameter = 0; + return between_diameter(root, &diameter); +} diff --git a/diameter_binay_tree.py b/diameter_binay_tree.py new file mode 100644 index 0000000..234143d --- /dev/null +++ b/diameter_binay_tree.py @@ -0,0 +1,39 @@ +# 543. Diameter of Binary Tree + +""" +given the 'root' of a binary tree, return the length of the diameter of the +tree. the diameter of a binary tree is the length of the longest path between +any two nodes in a tree. this path may or may not pass through the 'root'. +the length of a path between two nodes is represented by the number of edges +between them +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def diameterOfBinaryTree(self, root): + """ + :type root: TreeNode + :rtype: int + """ + + def depth(p): + if not p: + return 0 + left, right = depth(p.left), depth(p.right) + self.ans = max(self.ans, left + right) + return max(left, right) + 1 + + depth(root) + return self.ans + + +if __name__ == "__main__": + obj = Solution() diff --git a/diff_add_parentheses.c b/diff_add_parentheses.c new file mode 100644 index 0000000..d9ecf4e --- /dev/null +++ b/diff_add_parentheses.c @@ -0,0 +1,82 @@ +// 241. Different Ways to Add Parentheses +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a string 'expression' of numbers and operators, return all possible + * results from computing all the different possible ways to group numbers and + * operators. you may return the answer in any order. the test cases are + * generated such that the output values fit in a 32-bit integer and the number + * of different results is <10^4 + */ + +#define CAL(a, b, op) ('+' == op ? a + b : '-' == op ? a - b : a * b) + +void token_size(char *s, char **op, int **num, int *return_size) { + int i, s_len = (int)strlen(s), len = 0; + int *res = malloc(sizeof(int) * ((s_len + 1) >> 1)); + char *ops = malloc(s_len >> 1); + res[0] = 0; + for (int i = 0; i < s_len; ++i) { + if ('0' > s[i] || s[i] > '9') { + ops[len++] = s[i]; + res[len] = 0; + } else + res[len] = res[len] * 10 + s[i] - '0'; + } + len++; + *return_size = len; + *num = res; + *op = ops; +} + +int *helper(int *return_size, int *nums, int len, char *op) { + int i, j, k, cnt = 0, cap = 10, *set = malloc(sizeof(int) * cap); + int *ss1 = NULL, *ss2 = NULL, sl1 = 0, sl2 = 0; + if (2 >= len) { + set[cnt++] = 1 == len ? nums[0] : CAL(nums[0], nums[1], op[0]); + *return_size = cnt; + return set; + } + for (i = 1; i <= len - 1; ++i) { + ss1 = helper(&sl1, nums, i, op); + ss2 = helper(&sl2, nums + i, len - i, op + i); + if (cnt + sl1 * sl2 >= cap) { + cap += (sl1 * sl2) << 1; + set = realloc(set, sizeof(int) * cap); + } + for (j = 0; j < sl1; ++j) + for (k = 0; k < sl2; ++k) + set[cnt++] = CAL(ss1[j], ss2[k], op[i - 1]); + free(ss1); + free(ss2); + } + *return_size = cnt; + return set; +} + +int *diffWaysToCompute(char *expression, int *return_size) { + int *nums, *ans, len; + char *op; + if (!expression) { + *return_size = 0; + return NULL; + } + token_size(expression, &op, &nums, &len); + ans = helper(return_size, nums, len, op); + free(op); + free(nums); + return ans; +} + +int main() { + char e1[] = {"2 - 1 - 1"}, e2[] = {"2 * 3 - 4 * 5"}; + int *dwtc1 = diffWaysToCompute(e1, NULL); + int *dwtc2 = diffWaysToCompute(e2, NULL); + for (int i = 0; i < 2; i++) + printf("%d ", dwtc1[i]); // expect: 0,2 + printf("\n"); + for (int i = 0; i < 5; i++) + printf("%d ", dwtc2[i]); // expect: -34,-14,-10,-10,10 +} diff --git a/diff_ones_zeros_row_col.c b/diff_ones_zeros_row_col.c new file mode 100644 index 0000000..c03b459 --- /dev/null +++ b/diff_ones_zeros_row_col.c @@ -0,0 +1,35 @@ +// 2482. Difference Between Ones and Zeros in Row and Column +#include "leetcode.h" + +/* + * given a 0-indexed 'm * n' binary matrix 'grid', where the difference matrix + * 'diff' is created with the following procedure: let the number of ones in + * i'th row be 'ones_row[i]', let the number of ones in the j'th column be + * 'ones_col[j]', let the number of zeros in the i'th row be 'zeros_row[i]', let + * the number of zeros in the j'th column be 'zeros_col[j]'. 'diff[i][j] = + * ones_row[i] + ones_col[j] - zeros_row[i] - zeros_col[j]'. return the + * difference matrix 'diff' + */ + +int **onesMinusZeros(int **grid, int grid_size, int *grid_col_size, + int *return_size, int **return_col_size) { + int m = grid_size, n = *grid_col_size; + int **ans = malloc(m * sizeof(int *)); + for (int i = 0; i < m; i++) + ans[i] = malloc(n * sizeof(int)); + int *row_one = calloc(m, sizeof(int)); + int *col_one = calloc(n, sizeof(int)); + for (int i = 0; i < m; i++) + for (int j = 0; j < n; j++) + if (grid[i][j] == 1) + row_one[i]++, col_one[j]++; + for (int i = 0; i < m; i++) + for (int j = 0; j < n; j++) + ans[i][j] = 2 * row_one[i] + 2 * col_one[j] - m - n; + *return_size = m; + *return_col_size = malloc(m * sizeof(int)); + for (int i = 0; i < m; i++) + return_col_size[0][i] = n; + free(row_one), free(col_one); + return ans; +} diff --git a/diff_ones_zeros_row_col.py b/diff_ones_zeros_row_col.py new file mode 100644 index 0000000..7e332b7 --- /dev/null +++ b/diff_ones_zeros_row_col.py @@ -0,0 +1,36 @@ +# 2482. Difference Between Ones and Zeros in Row and Column + +""" +given a 0-indexed 'm n' binary matrix 'grid', where the difference matrix +'diff' is created with the following procedure: let the number of ones in +i'th row be 'ones_row[i]', let the number of ones in the j'th column be +'ones_col[j]', let the number of zeros in the i'th row be 'zeros_row[i]', let +the number of zeros in the j'th column be 'zeros_col[j]'. 'diff[i][j] = +ones_row[i] + ones_col[j] - zeros_row[i] - zeros_col[j]'. return the +difference matrix 'diff' +""" + + +class Solution(object): + def onesMinusZeros(self, grid): + """ + :type grid: List[List[int]] + :rtype: List[List[int]] + """ + m, n = len(grid), len(grid[0]) + row_one = [0] * m + col_one = [0] * n + for i in range(m): + for j in range(n): + row_one[i] += grid[i][j] + col_one[j] += grid[i][j] + for i in range(m): + for j in range(n): + grid[i][j] = 2 * (row_one[i] + col_one[j]) - m - n + return grid + + +if __name__ == "__main__": + obj = Solution() + print(obj.onesMinusZeros(grid=[[0, 1, 1], [1, 0, 1], [0, 0, 1]])) + print(obj.onesMinusZeros(grid=[[1, 1, 1], [1, 1, 1]])) diff --git a/diff_two_array.c b/diff_two_array.c new file mode 100644 index 0000000..604d2fa --- /dev/null +++ b/diff_two_array.c @@ -0,0 +1,81 @@ +// 2215. Find the Difference of Two Arrays +#include <stdio.h> +#include <stdlib.h> + +/* + * given two zero-indexed arrays 'n1' and 'n2', return a list + * 'ans' of size 2 where: + * 'ans[0]' is a list of all distinct integers in 'n1' which + * are not present in 'n2' + * 'ans[1]' is a list of all distinct integers in 'n2' which + * are not present in 'n1' + * note that the integers in the lists may be returned in any order + */ + +int max1, min1, max2, min2, total_max, total_min; + +int find_len(int *n1, int n1_size, int *n2, int n2_size, int size) { + for (int i = 1; i < size; i++) { + if (i < n1_size) { + max1 = n1[i] > max1 ? n1[i] : max1; + min1 = n1[i] < min1 ? n1[i] : min1; + } + if (i < n2_size) { + max2 = n2[i] > max2 ? n2[i] : max2; + min2 = n2[i] < min2 ? n2[i] : min2; + } + } + total_max = max1 > max2 ? max1 : max2; + total_min = min1 < min2 ? min1 : min2; + return total_max < 0 ? abs(total_min) + 1 : abs(total_min) + total_max + 1; +} + +int **findDifference(int *n1, int n1_size, int *n2, int n2_size, + int *return_size, int **return_col_size) { + max1 = n1[0], min1 = n1[0]; + max2 = n2[0], min2 = n2[0]; + total_max = 0, total_min = 0; + *return_size = 2; + *return_col_size = (int *)malloc(2 * sizeof(int)); + int **ans = (int **)malloc(2 * sizeof(int *)); + ans[0] = (int *)malloc(n1_size * sizeof(int)); + ans[1] = (int *)malloc(n2_size * sizeof(int)); + int size = n1_size > n2_size ? n1_size : n2_size; + int arr_size = find_len(n1, n1_size, n2, n2_size, size); + int shift = total_min < 0 ? abs(total_min) : 0; + int *arr1 = (int *)calloc(arr_size, sizeof(int)); + int *arr2 = (int *)calloc(arr_size, sizeof(int)); + for (int i = 0; i < n1_size; i++) + arr1[n1[i] + shift] = 1; + for (int i = 0; i < n2_size; i++) + arr2[n2[i] + shift] = 1; + int idx1 = 0, idx2 = 0; + for (int i = 0; i < n1_size; i++) + if (!arr2[n1[i] + shift] && arr1[n1[i] + shift]) { + ans[0][idx1++] = n1[i]; + arr1[n1[i] + shift]--; + } + for (int i = 0; i < n2_size; i++) + if (!arr2[n2[i] + shift] && arr2[n2[i] + shift]) { + ans[1][idx2++] = n2[i]; + arr2[n2[i] + shift]--; + } + return_col_size[0][0] = idx1; + return_col_size[0][1] = idx2; + free(arr1); + free(arr2); + return ans; +} + +int main() { + int n11[] = {1, 2, 3}, n11s = 3, n21[] = {2, 4, 6}, n21s = 3; + int n12[] = {1, 2, 3, 3}, n12s = 4, n22[] = {1, 1, 2, 2}, n22s = 4; + int **fd1 = findDifference(n11, n11s, n21, n21s, NULL, NULL); + int **fd2 = findDifference(n12, n12s, n22, n22s, NULL, NULL); + for (int i = 0; i < n11s; i++) + for (int j = 0; j < n21s; j++) + printf("%d\n", fd1[i][j]); + for (int i = 0; i < n12s; i++) + for (int j = 0; j < n22s; j++) + printf("%d\n", fd2[i][j]); +} diff --git a/diff_two_array.cpp b/diff_two_array.cpp new file mode 100644 index 0000000..65bbd2a --- /dev/null +++ b/diff_two_array.cpp @@ -0,0 +1,35 @@ +// 2215. Find the Difference of Two Arrays +#include "leetcode.h" + +/* + * given two zero-indexed arrays 'n1' and 'n2', return a list + * 'ans' of size 2 where: + * 'ans[0]' is a list of all distinct integers in 'n1' which + * are not present in 'n2' + * 'ans[1]' is a list of all distinct integers in 'n2' which + * are not present in 'n1' + * note that the integers in the lists may be returned in any order + */ + +class Solution { +public: + vvd(int) findDifference(vector<int> &n1, vector<int> &n2) { + unordered_set<int> us1(begin(n1), end(n1)), us2(begin(n2), end(n2)); + vvd(int) ans(2); + for (int i : us1) + if (!us2.count(i)) + ans[0].push_back(i); + for (int i : us2) + if (!us1.count(i)) + ans[1].push_back(i); + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n11 = {1, 2, 3}, n21 = {2, 4, 6}; + vector<int> n12 = {1, 2, 3, 3}, n22 = {1, 1, 2, 2}; + vvd(int) fd1 = obj.findDifference(n11, n21); + vvd(int) fd2 = obj.findDifference(n12, n22); +} diff --git a/discount_n_orders.cpp b/discount_n_orders.cpp new file mode 100644 index 0000000..a76d21e --- /dev/null +++ b/discount_n_orders.cpp @@ -0,0 +1,27 @@ +#include "leetcode.h" + +class Cashier { +public: + Cashier(int n, int discount, vector<int> &products, vector<int> &prices) { + count = 0, mod = n, pct = (100.0 - discount) / 100.0; + for (int i = 0; i < products.size(); ++i) + tags[products[i]] = prices[i]; + } + double getBill(vector<int> product, vector<int> amount) { + count++; + double ans(0.0); + for (int i = 0; i < product.size(); ++i) + ans += tags[product[i]] * amount[i]; + return count % mod ? ans : ans * pct; + } + +private: + unordered_map<int, int> tags; + int count, mod; + double pct; +}; + +int main() { + Cashier *obj = new Cashier(n, discount, products, prices); + double param_1 = obj->getBill(product, amount); +} diff --git a/distinct_char_equal.c b/distinct_char_equal.c new file mode 100644 index 0000000..e805926 --- /dev/null +++ b/distinct_char_equal.c @@ -0,0 +1,64 @@ +// 2531. Make Number of Distinct Characters Equal +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given: 2 0-indexed strings 'word1' & 'word2' + * a move consists of choosing two indices i and j such that 0 <= i < word1.len + * and 0 <= j < word2.len and swapping word1[i] with word2[i] + * return true if it is possible to get the number of distinct characters + * in 'word1' & 'word2' to be equal **with exactly one** move + */ + +bool isItPossible(char *word1, char *word2) { + int n1 = strlen(word1), n2 = strlen(word2); + int *a1 = calloc(26, sizeof(int)), *a2 = calloc(26, sizeof(int)); + int t1 = 0, t2 = 0; + for (int i = 0; i < n1; i++) { + a1[word1[i] - 'a']++; + if (a1[word1[i] - 'a'] == 1) + t1++; + } + for (int i = 0; i < n2; i++) { + a2[word2[i] - 'a']++; + if (a2[word2[i] - 'a'] == 1) + t2++; + } + for (int i = 0; i < 26; i++) { + if (a1[i] == 0) + continue; + for (int j = 0; j < 26; j++) { + if (a2[j] == 0) + continue; + if (i == j) { + if (t1 == t2) + return true; + else + return false; + } + int tee1 = t1, tee2 = t2; + if ((a1[i] - 1) == 0) + tee1--; + if ((a2[j] - 1) == 0) + tee2--; + if (a1[j] == 0) + tee1++; + if (a2[i] == 0) + tee2++; + if (tee1 == tee2) + return true; + } + } + return false; +} + +int main() { + char word11[] = {"ac"}, word21[] = {"b"}; + char word12[] = {"abcc"}, word22[] = {"aab"}; + char word13[] = {"abcde"}, word23[] = {"fghij"}; + printf("%d\n", isItPossible(word11, word21)); // expect: 0 + printf("%d\n", isItPossible(word11, word21)); // expect: 1 + printf("%d\n", isItPossible(word11, word21)); // expect: 1 +} diff --git a/distribute_coins_binary_tree.c b/distribute_coins_binary_tree.c new file mode 100644 index 0000000..9df6b16 --- /dev/null +++ b/distribute_coins_binary_tree.c @@ -0,0 +1,30 @@ +// 979. Distribute Coins in Binay Tree +#include "leetcode.h" + +/* + * given the 'root' of a binary tree with 'n' nodes where each 'node' is the + * tree that has 'node.val' coins. there are 'n' coins in total throughout the + * whole tree. in one move, we may choose two adjacent nodes and move one coin + * from one node to another. a move may be from parent to child, or from child + * to parent. return the minimum number of moves required to make every node + * have exactly one coin. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int dfs(struct TreeNode *root, int steps) { + if (!root) + return 0; + int val = root->val + dfs(root->left, steps) + dfs(root->right, steps); + steps += abs(val - 1); + return val - 1; +} + +int distributeCoins(struct TreeNode *root) { + int steps = 0, tmp = dfs(root, steps); + return steps; +} diff --git a/distribute_coins_binary_tree.py b/distribute_coins_binary_tree.py new file mode 100644 index 0000000..e14f7a4 --- /dev/null +++ b/distribute_coins_binary_tree.py @@ -0,0 +1,35 @@ +# 979. Distribute Coins in Binay Tree + +""" +given the 'root' of a binary tree with 'n' nodes where each 'node' is the +tree that has 'node.val' coins. there are 'n' coins in total throughout the +whole tree. in one move, we may choose two adjacent nodes and move one coin +from one node to another. a move may be from parent to child, or from child +to parent. return the minimum number of moves required to make every node +have exactly one coin. +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def distributeCoins(self, root): + """ + :type root: TreeNode + :rtype: int + """ + + def dfs(node): + if not node: + return 0, 0 + (lbal, lcnt), (rbal, rcnt) = dfs(node.left), dfs(node.right) + bal = node.val + lbal + rbal - 1 + return bal, lcnt + rcnt + abs(bal) + + return dfs(root)[1] diff --git a/divide_2_int.cpp b/divide_2_int.cpp new file mode 100644 index 0000000..7c172f7 --- /dev/null +++ b/divide_2_int.cpp @@ -0,0 +1,32 @@ +#include <bits/stdc++.h> + +class Solution { +public: + int divide(int dividend, int divisor) { + if (dividend == divisor) { + if (divisor == -1) + return INT_MAX; + else if (divisor == INT_MIN) + return 1; + else if (divisor < 0) + return 1 + divide(dividend - divisor, divisor); + else + return -1 + divide(dividend + divisor, divisor); + } else if (divisor == INT_MIN) + return 0; + bool negative = (dividend < 0) ^ (divisor < 0); + dividend = abs(dividend); + divisor = abs(divisor); + int result = 0; + for (int i = 31; i >= 0; --i) { + int shiftedDiv = (dividend >> i); + if (shiftedDiv >= divisor) { + result += (1 << i); + dividend -= (divisor << i); + } + } + return (negative ? -result : result); + } +}; + +int main() {} diff --git a/divide_array_max_diff.c b/divide_array_max_diff.c new file mode 100644 index 0000000..72e8648 --- /dev/null +++ b/divide_array_max_diff.c @@ -0,0 +1,35 @@ +// 2966. Divide Array Into Arrays With Max Difference +#include "leetcode.h" + +/* + * given an integer array 'nums' of size 'n' and a positive integer 'k'. divide + * the array into one or more arrays of size 3 satisfying the following + * conditions. each element of 'nums' should be in exactly one array. the + * different between any two elements in one array is less than or equal to 'k'. + * return a 2d array containing all the arrays if it is impossible to satisfy + * the conditions, return an empty array. and if there are multiple answers, + * return any of them + */ + +int cmp(const void *a, const void *b) { return (*(int *)a) - (*(int *)b); } + +int **divideArray(int *nums, int numsSize, int k, int *returnSize, + int **returnColumnSizes) { + int num_arr = numsSize / 3; + int **ans = (int **)calloc(num_arr, sizeof(int *)); + *returnColumnSizes = (int *)calloc(num_arr, sizeof(int)); + *returnSize = 0; + qsort(nums, numsSize, sizeof(int), cmp); + for (int i = 0; i < num_arr; i++) { + ans[i] = (int *)calloc(3, sizeof(int)); + (*returnColumnSizes)[i] = 3; + for (int j = 0; j < 3; j++) { + int idx = i * 3 + j; + if (j && nums[idx] - nums[i * 3] > k) + return ans; + ans[i][j] = nums[idx]; + } + } + *returnSize = num_arr; + return ans; +} diff --git a/divide_array_max_diff.py b/divide_array_max_diff.py new file mode 100644 index 0000000..41a2a22 --- /dev/null +++ b/divide_array_max_diff.py @@ -0,0 +1,39 @@ +# 2966. Divide Array Into Arrays With Max Difference + +""" +given an integer array 'nums' of size 'n' and a positive integer 'k'. divide +the array into one or more arrays of size 3 satisfying the following +conditions. each element of 'nums' should be in exactly one array. the +different between any two elements in one array is less than or equal to 'k'. +return a 2d array containing all the arrays if it is impossible to satisfy +the conditions, return an empty array. and if there are multiple answers, +return any of them +""" + + +class Solution(object): + def divideArray(self, nums, k): + """ + :type nums: List[int] + :type k: int + :rtype: List[List[int]] + """ + size = len(nums) + if size % 3 != 0: + return [] + nums.sort() + ans = [] + group_idx = 0 + for i in range(0, size, 3): + if i + 2 < size and nums[i + 2] - nums[i] <= k: + ans.append([nums[i], nums[i + 1], nums[i + 2]]) + group_idx += 1 + else: + return [] + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.divideArray(nums=[1, 3, 4, 8, 7, 9, 3, 5, 1], k=2)) + print(obj.divideArray(nums=[1, 3, 3, 2, 7, 3], k=3)) diff --git a/divide_two_int.cpp b/divide_two_int.cpp new file mode 100644 index 0000000..6afa1ea --- /dev/null +++ b/divide_two_int.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + int divide(int dividend, int divisor) { + if (dividend == INT_MIN && divisor == -1) + return INT_MAX; + long dvd = labs(dividend), dvs = labs(divisor), ans = 0; + int sign = dividend > 0 ^ divisor > 0 ? -1 : 1; + while (dvd >= dvs) { + long temp = dvs, m = 1; + while (temp << 1 <= dvd) { + temp <<= 1; + m <<= 1; + } + dvd -= temp; + ans += m; + } + return sign * ans; + } +}; + +int main() {} diff --git a/domino_tromino_tiling.cpp b/domino_tromino_tiling.cpp new file mode 100644 index 0000000..80a97d0 --- /dev/null +++ b/domino_tromino_tiling.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" +#include <vector> + +class Solution { +public: + int numTilings(int n) { + int mod = 1e9; + mod += 7; + vector<long long> ans(1001, 0); + ans[1] = 1; + ans[2] = 2; + ans[3] = 5; + if (n <= 3) + return ans[n]; + for (int i = 4; i <= n; ++i) { + ans[i] = 2 * ans[i - 1] + ans[i - 3]; + ans[i] %= mod; + } + return ans[n]; + } +}; + +int main() { + Solution obj; + cout << obj.numTilings(3); // 5 + cout << endl; + cout << obj.numTilings(1); // 1 +} diff --git a/domino_tromino_tiling.rs b/domino_tromino_tiling.rs new file mode 100644 index 0000000..554f147 --- /dev/null +++ b/domino_tromino_tiling.rs @@ -0,0 +1,20 @@ +struct Solution; + +impl Solution { + pub fn num_tilings(n: i32) -> i32 { + const MOD: i32 = 1_000_000_007; + let (mut x, mut y, mut z) = (-1, 0, 1); + for _ in 1..=n { + let curr = (2 * z % MOD + x) % MOD; + x = y; + y = z; + z = curr; + } + z + } +} + +fn main() { + println!("{}", Solution::num_tilings(3)); // 5 + println!("{}", Solution::num_tilings(1)); // 1 +} diff --git a/dota2_senate.c b/dota2_senate.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/dota2_senate.c diff --git a/dota2_senate.cpp b/dota2_senate.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/dota2_senate.cpp diff --git a/double_num_represent_ll.c b/double_num_represent_ll.c new file mode 100644 index 0000000..feb4c6f --- /dev/null +++ b/double_num_represent_ll.c @@ -0,0 +1,62 @@ +// 2816. Double a Number Represented as a Linked List +#include "leetcode.h" + +/* + * given the 'head' of a non-empty linked list representing a non negative + * integer without leading zeros. return the 'head' of the linked list after + * doubling it. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +int depth(struct ListNode *head) { + int n = 0; + struct ListNode *tmp = head; + while (tmp) { + tmp = tmp->next; + n++; + } + return n; +} + +struct ListNode *gen_list(int *arr, int len) { + struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode)); + struct ListNode *node = head; + for (int i = 0; i < len; i++) + if ((!i && arr[i]) || i) { + node->val = arr[i]; + if (i == len - 1) + break; + struct ListNode *tmp = (struct ListNode *)malloc(sizeof(struct ListNode)); + node->next = tmp; + node = node->next; + } + node->next = NULL; + return head; +} + +struct ListNode *doubleIt(struct ListNode *head) { + int n = depth(head) + 1, *arr = (int *)calloc(n, sizeof(int)); + struct ListNode *tmp = head; + for (int i = 1; i < n; i++) { + arr[i] = tmp->val << 1; + tmp = tmp->next; + } + int j = 0; + for (int i = n - 1; i >= 0; i--) { + if (arr[i] >= 10) { + arr[i] += j; + j = arr[i] / 10; + arr[i] %= 10; + } else { + arr[i] += j; + j = 0; + } + } + struct ListNode *ans = gen_list(arr, n); + free(arr); + return ans; +} diff --git a/double_num_represent_ll.py b/double_num_represent_ll.py new file mode 100644 index 0000000..482909e --- /dev/null +++ b/double_num_represent_ll.py @@ -0,0 +1,31 @@ +# 2816. Double a Number Represented as a Linked List + +""" +given the 'head' of a non-empty linked list representing a non negative +integer without leading zeros. return the 'head' of the linked list after +doubling it. +""" + + +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, val=0, next=None): + self.val = val + self.next = next + + +class Solution(object): + def doubleIt(self, head): + """ + :type head: Optional[ListNode] + :rtype: Optional[ListNode] + """ + if head.val > 4: + head = ListNode(0, head) + node = head + while node: + node.val = (node.val * 2) % 10 + if node.next and node.next.val > 4: + node.val += 1 + node = node.next + return head diff --git a/earliest_possible_full_bloom.cpp b/earliest_possible_full_bloom.cpp new file mode 100644 index 0000000..f990e62 --- /dev/null +++ b/earliest_possible_full_bloom.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + int earliestFullBloom(vector<int> &plantTime, vector<int> &growTime) { + int n = plantTime.size(); + vector<pair<int, int>> times(n); + for (int i = 0; i < n; i++) { + times[i].first = -growTime[i]; + times[i].second = plantTime[i]; + } + sort(times.begin(), times.end()); + int total = 0, curr = 0; + for (int i = 0; i < n; i++) { + total = max(total, curr + times[i].second - times[i].first); + curr += times[i].second; + } + return total; + } +}; + +int main() { + Solution obj; + vector<int> plantTime = {1, 4, 3}, growTime = {2, 3, 1}; + cout << obj.earliestFullBloom(plantTime, growTime); +} diff --git a/earliest_possible_full_bloom.rs b/earliest_possible_full_bloom.rs new file mode 100644 index 0000000..b8e6444 --- /dev/null +++ b/earliest_possible_full_bloom.rs @@ -0,0 +1,20 @@ +struct Solution; + +impl Solution { + pub fn earliest_full_bloom(plant_time: Vec<i32>, grow_time: Vec<i32>) -> i32 { + let n = plant_time.len(); + let mut plant_data: Vec<(i32, i32)> = plant_time.into_iter().zip(grow_time.into_iter()).collect(); + plant_data.sort_by(|a,b| b.1.cmp(&a.1)); + let (mut free_time, mut max_bloom_time) = (0,0); + for i in 0..n { + free_time += plant_data[i].0; + max_bloom_time = max_bloom_time.max(free_time + plant_data[i].1); + } + max_bloom_time + } +} + +fn main() { + let (plant_time, grow_time) = (vec![1,4,3], vec![2,3,1]); + print!("{}", Solution::earliest_full_bloom(plant_time, grow_time)); +} diff --git a/edit_distance.c b/edit_distance.c new file mode 100644 index 0000000..a091b21 --- /dev/null +++ b/edit_distance.c @@ -0,0 +1,60 @@ +// 72. Edit Distance +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define MIN(a, b, c) \ + ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c))) + +/* + * given two strings 'word1' and 'word2', return minimum number of operations + * required to convert 'word1' to 'word2'. the following operations are + * permitted: insert character, delete character, replace character + */ + +int minDistance(char *word1, char *word2) { + int len1 = strlen(word1), len2 = strlen(word2); + if (len1 == 0) + return len2; + if (len2 == 0) + return len1; + int **table = (int **)malloc(len1 * sizeof(int *)); + for (int i = 0; i < len1; i++) + table[i] = (int *)malloc(len2 * sizeof(int)); + if (word1[0] == word2[0]) + table[0][0] = 0; + else + table[0][0] = 1; + for (int i = 1; i < len2; i++) { + if (word1[0] == word2[i]) + table[0][i] = i; + else + table[0][i] = table[0][i - 1] + 1; + } + for (int i = 1; i < len1; i++) { + if (word2[0] == word1[i]) + table[i][0] = i; + else + table[i][0] = table[i - 1][0] + 1; + } + for (int i = 1; i < len1; i++) + for (int j = 1; j < len2; j++) { + if (word1[i] == word2[i]) + table[i][j] = table[i - 1][j - 1]; + else + table[i][j] = + MIN(table[i - 1][j], table[i][j - 1], table[i - 1][j - 1]); + } + int ans = table[len1 - 1][len2 - 1]; + for (int i = 0; i < len1; i++) + free(table[i]); + free(table); + return ans; +} + +int main() { + char w11[] = "horse", w21[] = "ros"; + char w12[] = "intention", w22[] = "execution"; + printf("%d\n", minDistance(w11, w21)); // expect: 3 + printf("%d\n", minDistance(w12, w22)); // expect: 5 +} diff --git a/edit_distance.cpp b/edit_distance.cpp new file mode 100644 index 0000000..080df8d --- /dev/null +++ b/edit_distance.cpp @@ -0,0 +1,41 @@ +// 72. Edit Distance +#include "leetcode.h" + +/* + * given two strings 'word1' and 'word2', return minimum number of operations + * required to convert 'word1' to 'word2'. the following operations are + * permitted: insert character, delete character, replace character + */ + +class Solution { +public: + int minDistance(string word1, string word2) { + int m = word1.size(), n = word2.size(); + vvd(int) memo(m + 1, vector<int>(n + 1, -1)); + return editDistance(word1, word2, m, n, memo); + } + +private: + int editDistance(string word1, string word2, int m, int n, vvd(int) memo) { + if (m == 0) + return memo[m][n] = n; + if (n == 0) + return memo[m][n] = m; + if (memo[m][n] != -1) + return memo[m][n]; + if (word1[m - 1] == word2[n - 1]) + return memo[m][n] = editDistance(word1, word2, m - 1, n - 1, memo); + else { + int insertChar = editDistance(word1, word2, m, n - 1, memo); + int deleteChar = editDistance(word1, word2, m - 1, n, memo); + int replacChar = editDistance(word1, word2, m - 1, n - 1, memo); + return memo[m][n] = 1 + min({insertChar, deleteChar, replacChar}); + } + } +}; + +int main() { + Solution obj; + cout << obj.minDistance("horse", "ros") << endl; // expect: 3 + cout << obj.minDistance("intention", "execution"); // expect: 5 +} diff --git a/eliminate_max_monster.c b/eliminate_max_monster.c new file mode 100644 index 0000000..f43bfbe --- /dev/null +++ b/eliminate_max_monster.c @@ -0,0 +1,53 @@ +// 1921. Eliminate Maximum Number of Monsters +#include "leetcode.h" + +/* + * you are playing a video game where you are defending your city from a group + * of 'n' monsters. you are given a 0-indexed integer array 'dist' of size 'n', + * where 'dist[i]' is the initial distance in kilometres of the i'th monster + * from the city. the monsters walk toward the city at a constant speed. the + * speed of each monster is given to you in an integer array 'speed' of size + * 'n', where 'speed[i]' is the speed of thhe i'th monster in kilometres per + * minute. you have a weapon that once fully charged can eliminate a single + * monster. however, the weapon takes one minute to charge. the weapon is fully + * charged at the very start. you lose when any monster reaches your city. if a + * monster reaches the city at the exact moment thhe weapon is fully charged, it + * counts as a loss. and thhe game ends before you can use your weapon. return + * the maximum number of monsters that you can eliminate before you lose of 'n' + * if you can eliminate all the monsters before they reachh thhe city + */ + +int cmp(const void *a, const void *b) { + double res = *(double *)a - *(double *)b; + if (res > 0) + return 1; + if (res < 0) + return -1; + return 0; +} + +int eliminateMaximum(int *dist, int dist_size, int *speed, int speed_size) { + double *time = malloc(dist_size * sizeof(double)); + for (int i = 0; i < dist_size; i++) + time[i] = (double)dist[i] / speed[i]; + qsort(time, dist_size, sizeof(double), cmp); + int ans = 0; + for (int i = 0; i < dist_size; i++) { + if (time[i] <= i) + break; + ans++; + } + return ans; +} + +int main() { + int d1[] = {1, 3, 4}, s1[] = {1, 1, 1}; + int d2[] = {1, 1, 2, 3}, s2[] = {1, 1, 1, 1}; + int d3[] = {3, 2, 4}, s3[] = {5, 3, 2}; + printf("%d\n", + eliminateMaximum(d1, ARRAY_SIZE(d1), s1, ARRAY_SIZE(s1))); // expect: 3 + printf("%d\n", + eliminateMaximum(d2, ARRAY_SIZE(d2), s2, ARRAY_SIZE(s2))); // expect: 1 + printf("%d\n", + eliminateMaximum(d3, ARRAY_SIZE(d3), s3, ARRAY_SIZE(s3))); // expect: 1 +} diff --git a/eliminate_max_monster.py b/eliminate_max_monster.py new file mode 100644 index 0000000..297c96e --- /dev/null +++ b/eliminate_max_monster.py @@ -0,0 +1,38 @@ +# 1921. Eliminate Maximum Number of Monsters + +""" +you are playing a video game where you are defending your city from a group +of 'n' monsters. you are given a 0-indexed integer array 'dist' of size 'n', +where 'dist[i]' is the initial distance in kilometres of the i'th monster +from the city. the monsters walk toward the city at a constant speed. the +speed of each monster is given to you in an integer array 'speed' of size +'n', where 'speed[i]' is the speed of thhe i'th monster in kilometres per +minute. you have a weapon that once fully charged can eliminate a single +monster. however, the weapon takes one minute to charge. the weapon is fully +charged at the very start. you lose when any monster reaches your city. if a +monster reaches the city at the exact moment thhe weapon is fully charged, it +counts as a loss. and thhe game ends before you can use your weapon. return +the maximum number of monsters that you can eliminate before you lose of 'n' +if you can eliminate all the monsters before they reachh thhe city +""" + + +class Solution(object): + def eliminateMaximum(self, dist, speed): + ans, t = 0, [] + for s, v in zip(dist, speed): + t.append(s / v) + t.sort() + for i in range(len(dist)): + if t[i] > i: + ans += 1 + else: + break + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.eliminateMaximum(dist=[1, 3, 4], speed=[1, 1, 1])) + print(obj.eliminateMaximum(dist=[1, 1, 2, 3], speed=[1, 1, 1, 1])) + print(obj.eliminateMaximum(dist=[3, 2, 4], speed=[5, 3, 2])) diff --git a/eliminate_monsters.cpp b/eliminate_monsters.cpp new file mode 100644 index 0000000..b0a1711 --- /dev/null +++ b/eliminate_monsters.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + typedef pair<double, int> p; + int eliminateMaxium(vector<int> &dist, vector<int> &speed) { + priority_queue<p, vector<p>, greater<p>> pq; + for (int i = 0; i < speed.size(); i++) { + double time = (double)dist[i] / (double)speed[i]; + pq.push({time, i}); + } + int ans = 0, t = 0; + while (pq.empty()) { + auto node = pq.top(); + pq.pop(); + int idx = node.second, d = dist[idx] - (t * speed[idx]); + if (d <= 0) + break; + else + ans++; + t++; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> dist = {1, 3, 4}, speed = {1, 1, 1}; + cout << obj.eliminateMaxium(dist, speed); +} diff --git a/encode_decode_tinyurl.cpp b/encode_decode_tinyurl.cpp new file mode 100644 index 0000000..7596c6a --- /dev/null +++ b/encode_decode_tinyurl.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +class Solution { +public: + unordered_map<string, string> codeDB, urlDB; + const string chars = + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + string encode(string longUrl) { + if (urlDB.find(longUrl) != urlDB.end()) + return urlDB[longUrl]; + string code = genCode(); + while (codeDB.find(code) != codeDB.end()) + code = genCode(); + codeDB[code] = longUrl; + urlDB[longUrl] = code; + return code; + } + string decode(string shortUrl) { return codeDB[shortUrl]; } + +private: + string genCode() { + string code = ""; + for (int i = 0; i < 6; i++) + code += chars[rand() % 62]; + return "http://tinyurl.com/" + code; + } +}; + +int main() {} diff --git a/equal_row_col_pair.c b/equal_row_col_pair.c new file mode 100644 index 0000000..1b51f55 --- /dev/null +++ b/equal_row_col_pair.c @@ -0,0 +1,32 @@ +// 2352. Equal Row and Column Pairs +#include <stdio.h> + +/* + * given a 0-indexed n x n integer matrix 'grid', return the number of pairs + * (ri, cj) such that row 'ri' and column 'ci' are equal. a row and column pair + * is considered equal if they contain the same elements in the same order (ie. + * an equal array) + */ + +int equalPairs(int **grid, int grid_size, int *grid_col_size) { + int ans = 0, r_len = grid_size, c_len = *grid_col_size; + for (int i = 0; i < r_len; i++) + for (int j = 0; j < c_len; j++) + if (grid[i][0] == grid[0][j]) { + ans++; + for (int k = 0; k < r_len; k++) + if (grid[i][k] != grid[k][j]) { + ans--; + break; + } + } + return ans; +} + +int main() { + int g1[3][3] = {{3, 2, 1}, {1, 7, 6}, {2, 7, 7}}, gs1 = 3, *gcs1; + int g2[4][4] = {{3, 1, 2, 2}, {1, 4, 4, 5}, {2, 4, 2, 2}, {2, 4, 2, 2}}, + gs2 = 4, *gcs2; + printf("%d\n", equalPairs(g1, gs1, gcs1)); // expect: 1 + printf("%d\n", equalPairs(g2, gs2, gcs2)); // expect: 3 +} diff --git a/equal_row_col_pair.cpp b/equal_row_col_pair.cpp new file mode 100644 index 0000000..3807c0c --- /dev/null +++ b/equal_row_col_pair.cpp @@ -0,0 +1,34 @@ +// 2352. Equal Row and Column Pairs +#include "leetcode.h" + +/* + * given a 0-indexed n x n integer matrix 'grid', return the number of pairs + * (ri, cj) such that row 'ri' and column 'ci' are equal. a row and column pair + * is considered equal if they contain the same elements in the same order (ie. + * an equal array) + */ + +class Solution { +public: + int equalPairs(vvd(int) & grid) { + int ans = 0; + map<vector<int>, int> mv; + for (int i = 0; i < grid.size(); i++) + mv[grid[i]]++; + for (int i = 0; i < grid[0].size(); i++) { + vector<int> v; + for (int j = 0; j < grid.size(); j++) + v.push_back(grid[j][i]); + ans += mv[v]; + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) g1 = {{3, 2, 1}, {1, 7, 6}, {2, 7, 7}}; + vvd(int) g2 = {{3, 1, 2, 2}, {1, 4, 4, 5}, {2, 4, 2, 2}, {2, 4, 2, 2}}; + printf("%d\n", obj.equalPairs(g1)); // expect: 1 + printf("%d\n", obj.equalPairs(g2)); // expect: 3 +} diff --git a/erect_fence.cpp b/erect_fence.cpp new file mode 100644 index 0000000..e68948b --- /dev/null +++ b/erect_fence.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +class Solution { +public: + using tree = vector<int>; + vector<tree> outerTrees(vector<tree> &trees) { + auto cross = [](tree &a, tree &b, tree &c) -> int { + return (c[1] - a[1]) * (a[0] - b[0]) - (a[1] - b[1]) * (c[0] - a[0]); + }; + sort(trees.begin(), trees.end()); + deque<tree> dv; + for (tree t : trees) { + while (dv.size() >= 2 && + cross(dv[dv.size() - 1], dv[dv.size() - 2], t) < 0) + dv.pop_back(); + dv.push_back(t); + while (dv.size() >= 2 && cross(dv[0], dv[1], t) > 0) + dv.pop_front(); + dv.push_front(t); + } + set<tree> unique(dv.begin(), dv.end()); + return vector<tree>(unique.begin(), unique.end()); + } +}; + +int main() { + Solution obj; + vvd(int) trees = {{1, 1}, {2, 2}, {2, 0}, {2, 4}, {3, 3}, {4, 2}}; +} diff --git a/erect_fence.rs b/erect_fence.rs new file mode 100644 index 0000000..6dee425 --- /dev/null +++ b/erect_fence.rs @@ -0,0 +1,27 @@ +use std::collections::VecDeque; +type Tree = Vec<i32>; +struct Solution; + +impl Solution { + pub fn outer_trees(mut trees: Vec<Tree>) -> Vec<Tree> { + fn cross(a: &Tree, b: &Tree, c: &Tree) -> i32 { + return (c[1] - a[1]) * (a[0] - b[0]) - (a[1] - b[1]) * (c[0] - a[0]) + } + trees.sort(); + let mut dv: VecDeque<Tree> = VecDeque::new(); + for t in trees { + while dv.len() >= 2 && cross(&dv[dv.len() - 1], &dv[dv.len() - 2], &t) < 0 { + dv.pop_back(); + } + dv.push_back(t.clone()); + while dv.len() >= 2 && cross(&dv[0], &dv[1], &t) > 0 { + dv.pop_front(); + } + dv.push_front(t.clone()); + } + let mut fence = Vec::from(dv); + fence.sort_unstable(); + fence.dedup(); + fence + } +} diff --git a/eval_reverse_polish_notation.c b/eval_reverse_polish_notation.c new file mode 100644 index 0000000..c15c100 --- /dev/null +++ b/eval_reverse_polish_notation.c @@ -0,0 +1,73 @@ +// 150. Evaluate Reverse Polish Notation +#include "leetcode.h" + +/* + * given an array of strings 'tokens' that represents an arithmetic expression + * in a reverse polish notation. evaluate the expression. return an integer that + * represents the value of the expression. note that the valid operators are + - + * * and /. each operand may be an integer or another expression. the division + * between two integers always truncates toward zero. there will not any + * division by zero. the input represents a valid arithmetic expression in + * reverse polish notation. the answer and all intermediate calculations can be + * represented in a 32 bit integer. + */ + +int char_to_int(char *s) { + int len = strlen(s), res = 0; + bool pos = 1; + for (int i = 0; i < len; i++) { + if (s[i] == '-') { + pos = 0; + continue; + } + res *= 10 + s[i] - '0'; + } + if (!pos) + res *= -1; + return res; +} + +int evalRPN(char **tokens, int tokens_size) { + long long *stack = (long long *)malloc(tokens_size * sizeof(long long)); + int idx = -1; + long long a, b; + for (int i = 0; i < tokens_size; i++) { + if (tokens[i][0] == '+') { + a = stack[idx]; + idx--; + b = stack[idx]; + stack[idx] = b + a; + } else if (strlen(tokens[i]) == 1 && tokens[i][0] == '-') { + a = stack[idx]; + idx--; + b = stack[idx]; + stack[idx] = b - a; + } else if (tokens[i][0] == '*') { + a = stack[idx]; + idx--; + b = stack[idx]; + stack[idx] = b * a; + } else if (tokens[i][0] == '/') { + a = stack[idx]; + idx--; + b = stack[idx]; + stack[idx] = b / a; + } else { + idx++; + stack[idx] = char_to_int(tokens[i]); + } + } + int ans = stack[0]; + free(stack); + return ans; +} + +int main() { + char t1[5][1] = {"2", "1", "+", "3", "*"}; + char t2[5][2] = {"4", "13", "5", "/", "+"}; + char t3[13][3] = {"10", "6", "9", "3", "+", "-11", "*", + "/", "*", "17", "+", "5", "+"}; + printf("%d\n", evalRPN(t1, 5)); // expect: 9 + printf("%d\n", evalRPN(t2, 5)); // expect: 6 + printf("%d\n", evalRPN(t3, 13)); // expect: 22 +} diff --git a/eval_reverse_polish_notation.cpp b/eval_reverse_polish_notation.cpp new file mode 100644 index 0000000..4cd39b8 --- /dev/null +++ b/eval_reverse_polish_notation.cpp @@ -0,0 +1,46 @@ +#include "leetcode.h" + +class Solution { +public: + int evalRPN(vector<string> &tokens) { + unordered_map<string, function<int(int, int)>> umf = { + {"+", [](long a, long b) { return a + b; }}, + {"-", [](long a, long b) { return a - b; }}, + {"*", [](long a, long b) { return a * b; }}, + {"/", [](long a, long b) { return a / b; }}}; + stack<long> stk; + for (string &s : tokens) { + if (!umf.count(s)) + stk.push(stoi(s)); + else { + long op1 = stk.top(); + stk.pop(); + long op2 = stk.top(); + stk.pop(); + stk.push(umf[s](op2, op1)); + } + } + return static_cast<int>(stk.top()); + } +}; + +int main() { + Solution obj; + vector<string> tokens1 = {"2", "1", "+", "3", "*"}; + // output: 9 + // ((2 + 1) * 3) + cout << obj.evalRPN(tokens1); + vector<string> tokens2 = {"4", "13", "5", "/", "+"}; + // output: 6 + // (4 + (13 / 5)) + cout << obj.evalRPN(tokens2); + vector<string> tokens3 = {"10", "6", "9", "3", "+", "-11", "*", + "/", "*", "17", "+", "5", "+"}; + // output: 22 + // ((10 * (6 / (12 * -11))) + 17) + 5 + // ((10 * (6 / -132)) + 17) + 5 + // ((10 * 0) + 17) + 5 + // (0 + 17) + 5 + // 17 + 5 + cout << obj.evalRPN(tokens3); +} diff --git a/eval_reverse_polish_notation.py b/eval_reverse_polish_notation.py new file mode 100644 index 0000000..f03438a --- /dev/null +++ b/eval_reverse_polish_notation.py @@ -0,0 +1,46 @@ +# 150. Evaluate Reverse Polish Notation + +""" +given an array of strings 'tokens' that represents an arithmetic expression +in a reverse polish notation. evaluate the expression. return an integer that +represents the value of the expression. note that the valid operators are + - +and /. each operand may be an integer or another expression. the division +between two integers always truncates toward zero. there will not any +division by zero. the input represents a valid arithmetic expression in +reverse polish notation. the answer and all intermediate calculations can be +represented in a 32 bit integer. +""" + + +class Solution(object): + def evalRPN(self, tokens): + """ + :type tokens: List[str] + :rtype: int + """ + stack = [] + for t in tokens: + if t not in "+-*/": + stack.append(int(t)) + else: + r, l = stack.pop(), stack.pop() + if t == "+": + stack.append(l + r) + elif t == "-": + stack.append(l - r) + elif t == "*": + stack.append(l * r) + else: + stack.append(int(float(l) / r)) + return stack.pop() + + +if __name__ == "__main__": + obj = Solution() + print(obj.evalRPN(tokens=["2", "1", "+", "3", "*"])) + print(obj.evalRPN(tokens=["4", "13", "5", "/", "+"])) + print( + obj.evalRPN( + tokens=["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"] + ) + ) diff --git a/eval_reverse_polish_notation.rs b/eval_reverse_polish_notation.rs new file mode 100644 index 0000000..11a36e3 --- /dev/null +++ b/eval_reverse_polish_notation.rs @@ -0,0 +1,29 @@ +struct Solution; + +impl Solution { + pub fn eval_rpn(tokens: Vec<String>) -> i32 { + tokens.iter().fold(Vec::new(), |mut stack, x| { + if let Ok(x) = x.parse() { + stack.push(x); + } else if let (Some(rhs), Some(lhs)) = (stack.pop(), stack.pop()) { + stack.push(match x.as_str() { + "+" => lhs + rhs, + "-" => lhs - rhs, + "*" => lhs * rhs, + "/" => lhs / rhs, + _ => unreachable!() + }) + } + stack + }) [0] + } +} + +fn main() { + let tokens1 = ["2","1","+","3","*"]; + let tokens2 = ["4","13","5","/","+"]; + let tokens3 = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]; + println!("{}", Solution::eval_rpn(tokens1)); + println!("{}", Solution::eval_rpn(tokens2)); + println!("{}", Solution::eval_rpn(tokens3)); +} diff --git a/evaluate_boolean_binary_tree.c b/evaluate_boolean_binary_tree.c new file mode 100644 index 0000000..14e71e4 --- /dev/null +++ b/evaluate_boolean_binary_tree.c @@ -0,0 +1,39 @@ +// 2331. Evaluate Boolean Binary Tree +#include "leetcode.h" + +/* + * given the 'root' of a full binary tree with the following properties. leaf + * nodes have either the value 0 or 1, where 0 represents false and 1 represents + * true. non leaf nodes have either the value 2 or 3, where 2 represents the + * boolean or, and 3 represents the boolean and. the evaluation of a node is as + * follows. if the node is a leaf node, the evaluation is the value of the node, + * ie. true or false. otherwise, evaluate the node's two children and apply the + * boolean operation of its value with the children's evaluations. return the + * boolean result of evaulating the 'root' node. a full binary tree is a binary + * tree where each node has either 0 or 2 children. a leaf node is a node that + * has zero children. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +bool evaluateTree(struct TreeNode *root) { + if (!root) + return true; + bool l = evaluateTree(root->left), r = evaluateTree(root->right); + switch (root->val) { + case 2: + root->val = l || r; + return l || r; + case 3: + root->val = l && r; + return l && r; + case 0: + return false; + default: + return true; + } +} diff --git a/evaluate_boolean_binary_tree.py b/evaluate_boolean_binary_tree.py new file mode 100644 index 0000000..cc9237a --- /dev/null +++ b/evaluate_boolean_binary_tree.py @@ -0,0 +1,36 @@ +# 2331. Evaluate Boolean Binary Tree + +""" +given the 'root' of a full binary tree with the following properties. leaf +nodes have either the value 0 or 1, where 0 represents false and 1 represents +true. non leaf nodes have either the value 2 or 3, where 2 represents the +boolean or, and 3 represents the boolean and. the evaluation of a node is as +follows. if the node is a leaf node, the evaluation is the value of the node, +ie. true or false. otherwise, evaluate the node's two children and apply the +boolean operation of its value with the children's evaluations. return the +boolean result of evaulating the 'root' node. a full binary tree is a binary +tree where each node has either 0 or 2 children. a leaf node is a node that +has zero children. +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def evaluateTree(self, root): + """ + :type root: Optional[TreeNode] + :rtype: bool + """ + if root.val == 0 or root.val == 1: + return root.val + if root.val == 2: + return self.evaluateTree(root.left) or self.evaluateTree(root.right) + if root.val == 3: + return self.evaluateTree(root.left) and self.evaluateTree(root.right) diff --git a/evaluate_division.c b/evaluate_division.c new file mode 100644 index 0000000..f0bfc20 --- /dev/null +++ b/evaluate_division.c @@ -0,0 +1,109 @@ +#include <stdlib.h> +#include <string.h> + +#define MAX_ELEM 40 + +int map_str(char *strs[MAX_ELEM], char *s, int num) { + for (int i = 0; i < num; i++) + if (!strcmp(strs[i], s)) + return i + 1; + return 0; +} + +int find_dj(int *rt, double wt[][MAX_ELEM], int x) { + int rx = rt[x]; + if (rx == x) + return x; + rt[x] = find_dj(rt, wt, rx); + if (rt[x] != rx) { + wt[x][rt[x]] = wt[x][rx] * wt[rx][rt[x]]; + wt[rt[x]][x] = 1 / wt[x][rt[x]]; + } + return rt[x]; +} + +void union_dj(int *rt, int *rnk, double wt[][MAX_ELEM], double w, int x, + int y) { + int rx, ry; + rx = find_dj(rt, wt, x); + ry = find_dj(rt, wt, y); + wt[x][y] = w; + wt[y][x] = 1 / w; + if (rx == ry) + return; + wt[rx][ry] = wt[rx][x] * wt[y][ry] * wt[x][y]; + wt[ry][rx] = 1 / wt[rx][ry]; + if (rnk[rx] > rnk[ry]) + rt[ry] = rx; + else if (rnk[ry] > rnk[rx]) + rt[rx] = ry; + else { + rt[ry] = rx; + rnk[rx]++; + } + return; +} + +double *calcEquation(char ***equations, int equations_size, + int *equations_col_size, double *values, int values_size, + char ***queries, int queries_size, int *queries_col_size, + int *return_size) { + int num_strs = 0, rt[MAX_ELEM], map_id1, map_id2; + char *strs[MAX_ELEM], *s; + double wt[MAX_ELEM][MAX_ELEM]; + { + int rnk[MAX_ELEM]; + for (int i = 0; i < MAX_ELEM; i++) { + for (int j = 0; j < MAX_ELEM; j++) + wt[i][j] = 1.0; + rt[i] = i; + rnk[i] = 1; + } + for (int i = 0; i < equations_size; i++) { + s = equations[i][0]; + if (!(map_id1 = map_str(strs, s, num_strs))) { + strs[num_strs] = s; + map_id1 = num_strs; + num_strs++; + } else + map_id1--; + s = equations[i][1]; + if (!(map_id2 = map_str(strs, s, num_strs))) { + strs[num_strs] = s; + map_id2 = num_strs; + num_strs++; + } else + map_id2--; + union_dj(rt, rnk, wt, values[i], map_id1, map_id2); + } + } + double *ans = (double *)malloc(sizeof(double) * queries_size); + for (int i = 0; i < queries_size; i++) { + s = queries[i][0]; + if (!(map_id1 = map_str(strs, s, num_strs))) { + ans[i] = -1; + continue; + } else + map_id1--; + s = queries[i][1]; + if (!(map_id2 = map_str(strs, s, num_strs))) { + ans[i] = -1; + continue; + } else + map_id2--; + if (map_id1 == map_id2) + ans[i] = 1; + else if (wt[map_id1][map_id2] != 1.0) + ans[i] = wt[map_id1][map_id2]; + else { + int rx = find_dj(rt, wt, map_id1); + int ry = find_dj(rt, wt, map_id2); + if (rx == ry) + ans[i] = wt[map_id1][rx] * wt[rx][map_id2]; + else + ans[i] = -1.0; + } + } + *return_size = queries_size; + return ans; +} diff --git a/evaluate_division.cpp b/evaluate_division.cpp new file mode 100644 index 0000000..7bda627 --- /dev/null +++ b/evaluate_division.cpp @@ -0,0 +1,63 @@ +#include "leetcode.h" + +class Solution { +public: + vector<double> calcEquation(vector<vector<string>> &equations, + vector<double> &values, + vector<vector<string>> &queries) { + vector<double> ans; + map<string, double> mp; + map<string, vector<string>> graph; + for (int i = 0; i < equations.size(); i++) { + string u = equations[i][0], v = equations[i][1]; + mp[u + "->" + v] = values[i]; + mp[v + "->" + u] = 1 / values[i]; + graph[u].push_back(v); + graph[v].push_back(u); + } + for (int i = 0; i < queries.size(); i++) { + string start = queries[i][0], end = queries[i][1]; + if (graph.find(start) == graph.end() || graph.find(end) == graph.end()) { + ans.push_back(-1); + } else { + double val = 1; + map<string, int> visited; + bool found = false; + if (start == end) + found = true; + else + dfs(start, end, mp, graph, val, visited, found); + if (found == true) + ans.push_back(val); + else + ans.push_back(-1); + } + } + return ans; + } + +private: + void dfs(string start, string end, map<string, double> &mp, + map<string, vector<string>> &graph, double &val, + map<string, int> &visited, bool &found) { + visited[start] = 1; + if (found == true) + return; + for (auto child : graph[start]) { + if (visited[child] != 1) { + val *= mp[start + "->" + child]; + if (end == child) { + found = true; + return; + } + dfs(child, end, mp, graph, val, visited, found); + if (found == true) + return; + else + val /= mp[start + "->" + child]; + } + } + } +}; + +int main() {} diff --git a/even_odd_tree.c b/even_odd_tree.c new file mode 100644 index 0000000..0cae3e8 --- /dev/null +++ b/even_odd_tree.c @@ -0,0 +1,76 @@ +// 1609. Even Odd Tree +#include "leetcode.h" + +/* + * a binary tree is even-odd if it meets the following conditions. the root of + * the binary tree is at level index 0 it s children are at level index 1 and + * their children are at level index 2, etc. for every even indexed level, all + * nodes at the level have odd integer values in strictly ordere (from left to + * right). for every odd-indexed level, all nodes at the level have even integer + * values in strictly decreasing order (from left to right). given 'root' of a + * binary tree, return true if the binary tree is even-odd, otherwise return + * false. + */ + +struct TreeNode { + int val; + struct TreeNode *left, *right; +}; + +int depth(struct TreeNode *root) { + if (!root) + return 0; + else + return 1 + fmax(depth(root->left), depth(root->right)); +} + +bool isEvenOddTree(struct TreeNode *root) { + int d = depth(root); + struct TreeNode **q0 = malloc(50000 * sizeof(struct TreeNode *)); + struct TreeNode **q1 = malloc(50000 * sizeof(struct TreeNode *)); + int idx0 = 0, idx1 = 0; + q0[idx0] = root; + idx0 = 1; + while (idx0 || idx1) { + if (idx0) { + for (int i = 0; i < idx0; i++) { + if (!i) { + if (!(q0[i]->val % 2)) + return 0; + } else { + if (!(q0[i]->val % 2) || q0[i]->val <= q0[i - 1]->val) + return 0; + } + if (q0[i]->left) { + q1[idx1] = q0[i]->left; + idx1++; + } + if (q0[i]->right) { + q1[idx1] = q0[i]->right; + idx1++; + } + } + idx0 = 0; + } else { + for (int i = 0; i < idx1; i++) { + if (!i) { + if (q1[i]->val % 2 == 1) + return 0; + } else { + if (q1[i]->val % 2 == 1 || q1[i]->val >= q1[i - 1]->val) + return 0; + } + if (q1[i]->left) { + q0[idx0] = q1[i]->left; + idx0++; + } + if (q1[i]->right) { + q0[idx0] = q1[i]->right; + idx0++; + } + } + idx1 = 0; + } + } + return 1; +} diff --git a/even_odd_tree.py b/even_odd_tree.py new file mode 100644 index 0000000..202fcf5 --- /dev/null +++ b/even_odd_tree.py @@ -0,0 +1,52 @@ +# 1609. Even Odd Tree +import collections + +""" +a binary tree is even-odd if it meets the following conditions. the root of +the binary tree is at level index 0 it s children are at level index 1 and +their children are at level index 2, etc. for every even indexed level, all +nodes at the level have odd integer values in strictly ordere (from left to +right). for every odd-indexed level, all nodes at the level have even integer +values in strictly decreasing order (from left to right). given 'root' of a +binary tree, return true if the binary tree is even-odd, otherwise return +false. +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def isEvenOddTree(self, root): + """ + :type root: TreeNode + :rtype: bool + """ + queue = collections.deque([root]) + is_even = True + while queue: + prev = None + for _ in range(len(queue)): + node = queue.popleft() + if is_even: + if node.val % 2 == 0: + return False + if prev and prev.val >= node.val: + return False + else: + if node.val % 2 == 1: + return False + if prev and prev.val <= node.val: + return False + if node.left: + queue.append(node.left) + if node.right: + queue.append(node.right) + prev = node + is_even = not is_even + return True diff --git a/eventual_safe_states.c b/eventual_safe_states.c new file mode 100644 index 0000000..21fa5d0 --- /dev/null +++ b/eventual_safe_states.c @@ -0,0 +1,44 @@ +// 802. Find Eventual Safe States +#include <stdbool.h> +#include <stdlib.h> + +/* + * there is a directed graph of 'n' nodes with each node labeled from 0 to n + * - 1. the graph is represented by a 0-indexed 2d integer array 'graph' where + * 'graph[i]' is an integer array of nodes adjacent to node 'i', meaning there + * is an edge from node 'i' to each node in 'graph[i]'. a node is a terminal + * node if there are no outgoing edges. a node is a safe node if every possible + * path starting from that node leads to a terminal node ( or another safe + * node). return an array containing all the safe nodes of the graph. the answer + * should be sorted in ascending order. + */ + +bool dfs(int **graph, int graph_size, int *graph_col_size, int *visited, + int node) { + if (visited[node] == 1) + return true; + if (visited[node] == 2) + return false; + visited[node] = 2; + for (int i = 0; i < graph_col_size[node]; i++) + if (!dfs(graph, graph_size, graph_col_size, visited, graph[node][i])) + return false; + visited[node] = 1; + return true; +} + +int *eventualSafeNodes(int **graph, int graph_size, int *graph_col_size, + int *return_size) { + int n = graph_size, a_idx = 0; + int *visited = calloc(n, sizeof(int)); + int *ans = malloc(n * sizeof(int)); + for (int i = 0; i < n; i++) + if (dfs(graph, graph_size, graph_col_size, visited, i)) { + ans[a_idx] = i; + a_idx++; + } + free(visited); + *return_size = a_idx; + ans = realloc(ans, a_idx * sizeof(int)); + return ans; +} diff --git a/eventual_safe_states.cpp b/eventual_safe_states.cpp new file mode 100644 index 0000000..659115b --- /dev/null +++ b/eventual_safe_states.cpp @@ -0,0 +1,57 @@ +// 802. Find Eventual Safe States +#include "leetcode.h" + +/* + * there is a directed graph of 'n' nodes with each node labeled from 0 to n + * - 1. the graph is represented by a 0-indexed 2d integer array 'graph' where + * 'graph[i]' is an integer array of nodes adjacent to node 'i', meaning there + * is an edge from node 'i' to each node in 'graph[i]'. a node is a terminal + * node if there are no outgoing edges. a node is a safe node if every possible + * path starting from that node leads to a terminal node ( or another safe + * node). return an array containing all the safe nodes of the graph. the answer + * should be sorted in ascending order. + */ + +class Solution { + unordered_set<int> cycle_nodes, safe_nodes; + bool dfs(const vvd(int) & graph, int i, unordered_set<int> visited) { + if (safe_nodes.find(i) != safe_nodes.end()) + return true; + if (cycle_nodes.find(i) != cycle_nodes.end()) + return false; + if (visited.find(i) != visited.end()) { + cycle_nodes.insert(i); + return false; + } + visited.insert(i); + for (int node : graph[i]) + if (!dfs(graph, node, visited)) { + cycle_nodes.insert(i); + return false; + } + safe_nodes.insert(i); + return true; + } + +public: + vector<int> eventualSafeNodes(vvd(int) & graph) { + vector<int> ans; + unordered_set<int> visited; + for (int i = 0; i < graph.size(); i++) + if (dfs(graph, i, visited)) + ans.push_back(i); + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) g1 = {{1, 2}, {2, 3}, {5}, {0}, {5}, {}, {}}; + vvd(int) g2 = {{1, 2, 3, 4}, {1, 2}, {3, 4}, {0, 4}, {}}; + for (auto i : obj.eventualSafeNodes(g1)) + printf("%d ", i); // expect: 2 4 5 6 + printf("\n"); + for (auto i : obj.eventualSafeNodes(g2)) + printf("%d ", i); // expect: 4 + printf("\n"); +} diff --git a/excel_sheet_column_title.c b/excel_sheet_column_title.c new file mode 100644 index 0000000..14c55be --- /dev/null +++ b/excel_sheet_column_title.c @@ -0,0 +1,49 @@ +// 168. Excel Sheet Column Title +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given an integer 'column_number', return its corresponding column title as it + * appears in an excel sheet. for example: A -> 1 B -> 2 C -> 3 + * ... + * Z -> 26 + * AA -> 27 + * AB -> 28 + * ... + */ + +int get_len(int n) { + int i = 0; + while (n) { + if (!(n % 26)) + n = (n - 1) / 26; + else + n /= 26; + i++; + } + return i; +} + +char *convertToTitle(int n) { + int len = get_len(n); + char *ans = (char *)malloc(sizeof(*ans) * (len + 1)); + memset(ans, 0, len + 1); + while (n) { + --len; + if (!(n % 26)) { + ans[len] = 'Z'; + n = (n - 1) / 26; + } else { + ans[len] = 'A' + (n % 26) - 1; + n /= 26; + } + } + return ans; +} + +int main() { + printf("%s\n", convertToTitle(1)); // expect: A + printf("%s\n", convertToTitle(28)); // expect: AB + printf("%s\n", convertToTitle(701)); // expect: ZY +} diff --git a/excel_sheet_column_title.cpp b/excel_sheet_column_title.cpp new file mode 100644 index 0000000..3de395f --- /dev/null +++ b/excel_sheet_column_title.cpp @@ -0,0 +1,39 @@ +// 168. Excel Sheet Column Title +#include "leetcode.h" + +/* + * given an integer 'column_number', return its corresponding column title as it + * appears in an excel sheet. for example: A -> 1 B -> 2 C -> 3 + * ... + * Z -> 26 + * AA -> 27 + * AB -> 28 + * ... + */ + +class Solution { +public: + string convertToTitle(int n) { + if (n < 27) + return string(1, 'A' + (n - 1) % 26); + string ans = ""; + while (n > 0) { + if (!(n % 26)) { + ans += 'A' + 25; + n--; + } else { + ans += 'A' + n % 26 - 1; + } + n /= 26; + } + reverse(ans.begin(), ans.end()); + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.convertToTitle(1) << endl; // expect: A + cout << obj.convertToTitle(28) << endl; // expect: AB + cout << obj.convertToTitle(701) << endl; // expect: ZY +} diff --git a/extra_char_string.cpp b/extra_char_string.cpp new file mode 100644 index 0000000..b26cb93 --- /dev/null +++ b/extra_char_string.cpp @@ -0,0 +1,50 @@ +// 2707. Extra Characters in a String +#include "leetcode.h" + +/* + * you are given a 0-indexed string 's' and a dictionary of words 'dictionary'. + * you have to break 's' into one or more non-overlapping substrings that each + * substring is present in 'dictionary'. there may be some extra characters in + * 's' which are not present in any of the substrings. return the minimum number + * of extra characters left over if you break up 's' optimally + */ + +class Solution { + int mod = 1e7 + 7; + int hash_func(string s) { + int res = 0; + for (auto i : s) + res = (res * 27 + i - 'a' + 1) % mod; + return res; + } + int min_cost(int l, vector<int> &dp, string s, unordered_set<int> &d) { + if (l == s.size()) + return 0; + if (dp[l] != -1) + return dp[l]; + int res = 1 + min_cost(l + 1, dp, s, d), curr = 0; + for (int i = l; i < s.size(); i++) { + curr = (curr * 27 + s[i] - 'a' + 1) % mod; + if (d.find(curr) != d.end()) + res = min(res, min_cost(i + 1, dp, s, d)); + } + return dp[l] = res; + } + +public: + int minExtraChar(string s, vector<string> &dictionary) { + unordered_set<int> d; + for (auto i : dictionary) + d.insert(hash_func(i)); + vector<int> dp(s.size(), -1); + return min_cost(0, dp, s, d); + } +}; + +int main() { + Solution obj; + string s1 = "leetscode", s2 = "sayhelloworld"; + vector<string> d1 = {"leet", "code", "leetcode"}, d2 = {"hello", "world"}; + printf("%d\n", obj.minExtraChar(s1, d1)); // expepct: 1 + printf("%d\n", obj.minExtraChar(s2, d2)); // expepct: 3 +} diff --git a/extra_char_string.py b/extra_char_string.py new file mode 100644 index 0000000..dd4b2af --- /dev/null +++ b/extra_char_string.py @@ -0,0 +1,37 @@ +# 2707. Extra Characters in a String + +""" +you are given a 0-indexed string 's' and a dictionary of words 'dictionary'. +you have to break 's' into one or more non-overlapping substrings that each +substring is present in 'dictionary'. there may be some extra characters in +'s' which are not present in any of the substrings. return the minimum number +of extra characters left over if you break up 's' optimally +""" + + +class Solution(object): + def func(self, idx, s, st, dp): + if idx == len(s): + return 0 + if dp[idx] != -1: + return dp[idx] + res = float("inf") + for j in range(idx, len(s)): + substr = s[idx : j + 1] + if substr in st: + res = min(res, 0 + self.func(j + 1, s, st, dp)) + else: + res = min(res, j - idx + 1 + self.func(j + 1, s, st, dp)) + dp[idx] = res + return res + + def minExtraChar(self, s, dictionary): + dp = [-1] * (len(s) + 1) + st = set(dictionary) + return self.func(0, s, st, dp) + + +if __name__ == "__main__": + obj = Solution() + print(obj.minExtraChar("leetscode", ["leet", "code", "leetcode"])) # expect: 1 + print(obj.minExtraChar("sayhelloworld", ["hello", "world"])) # expect: 3 diff --git a/fair_distribution_cookie.cpp b/fair_distribution_cookie.cpp new file mode 100644 index 0000000..69e0ab4 --- /dev/null +++ b/fair_distribution_cookie.cpp @@ -0,0 +1,45 @@ +// 2305. Fair Distribution of Cookies +#include "leetcode.h" + +/* + * given an integer array 'cookies', where 'cookies[i]' denotes the number of + * cookies in the i'th bag. you are also given an integer 'k' that denotes the + * number of children to distribute all the bags of cookies to. all the cookies + * in the same bag must go to the same child and cannot be split up. the + * unfairness of a distribution is defined as the maximum total cookies obtained + * by a single child in the distribution. return the minimum unfairness of all + * distributions + */ + +class Solution { + int ans = INT_MAX; + void solve(int start, vector<int> &cookies, vector<int> &v, int k) { + if (start == cookies.size()) { + int max_m = INT_MIN; + for (int i = 0; i < k; k++) + max_m = max(max_m, v[i]); + ans = min(ans, max_m); + return; + } + for (int i = 0; i < k; i++) { + v[i] += cookies[start]; + solve(start + 1, cookies, v, k); + v[i] -= cookies[start]; + } + } + +public: + int distributeCookies(vector<int> &cookies, int k) { + int n = cookies.size(); + vector<int> v(k, 0); + solve(0, cookies, v, k); + return ans; + } +}; + +int main() { + Solution obj; + vector<int> c1 = {8, 15, 10, 20, 8}, c2 = {6, 1, 3, 2, 2, 4, 1, 2}; + printf("%d\n", obj.distributeCookies(c1, 2)); // expect: 31 + printf("%d\n", obj.distributeCookies(c2, 3)); // expect: 7 +} diff --git a/far_from_land.c b/far_from_land.c new file mode 100644 index 0000000..bfff564 --- /dev/null +++ b/far_from_land.c @@ -0,0 +1,56 @@ +// 1162. As Far from Land as Possible +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given 'n * n grid' containing only values 0 and 1, where 0 represents water + * and 1 represents land, find a water cell such that its distance to the + * nearest land cell is maximised, and returh the distance. if no land or water + * exists, return -1. the distance used is the manhattan distance: the distance + * between two cells '(x0, y0)' and '(x1, y1)' is '|x0 - x1| + |y0 - y1|' + */ + +int maxDistance(int **grid, int gridSize, int *gridColSize) { + int queue[10000][2] = {0}, dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; + int head = 0, tail = 0, step = -1; + bool has_land = false, has_water = false; + for (int i = 0; i < gridSize; i++) + for (int j = 0; j < *gridColSize; j++) + if (grid[i][j] == 1) { + has_land = true; + grid[i][j] = 2; + queue[tail][0] = i; + queue[tail][1] = j; + tail += 1; + } else + has_water = true; + while (head < tail) { + int size = tail - head; + step += 1; + for (int i = 0; i < size; i++) { + int x = queue[head][0], y = queue[head][1]; + head += 1; + for (int j = 0; j < 4; j++) { + int new_x = x + dir[j][0], new_y = y + dir[j][1]; + if (new_x >= 0 && new_y >= 0 && new_x < gridSize && + new_y < *gridColSize && grid[new_x][new_y] == 0) { + grid[new_x][new_y] = 2; + queue[tail][0] = new_x; + queue[tail][1] = new_y; + tail += 1; + } + } + } + } + if (!has_land || !has_water) + return -1; + return step; +} + +int main() { + int grid1[3][3] = {{1, 0, 1}, {0, 0, 0}, {1, 0, 1}}, gs1 = 3, gcs1[] = {3}; + int grid2[3][3] = {{1, 0, 0}, {0, 0, 0}, {0, 0, 0}}, gs2 = 3, gcs2[] = {3}; + printf("%d\n", maxDistance(grid1, gs1, gcs1)); // expect: 2 + printf("%d\n", maxDistance(grid2, gs2, gcs2)); // expect: 2 +} diff --git a/far_from_land.cpp b/far_from_land.cpp new file mode 100644 index 0000000..651b8a7 --- /dev/null +++ b/far_from_land.cpp @@ -0,0 +1,44 @@ +#include "leetcode.h" + +class Solution { +public: + int maxDistance(vector<vector<int>> &grid) { + int ans = -1; + if (grid.empty() || grid[0].empty()) + return ans; + + vector<vector<int>> gridValues(grid.size(), + vector<int>(grid[0].size(), INT_MAX)); + queue<pair<int, int>> q; + + for (int i = 0; i < grid.size(); ++i) { + for (int j = 0; j < grid[0].size(); ++j) { + if (grid[i][j] == 1) { + q.push(make_pair(i, j)); + gridValues[i][j] = 0; + } + } + } + if (q.empty()) + return -1; + vector<int> dx({0, 1, 0, -1}), dy({1, 0, -1, 0}); + while (!q.empty()) { + auto pos = q.front(); + q.pop(); + for (int i = 0; i < 4; ++i) { + int x = pos.first + dx[i], y = pos.second + dy[i]; + if (x >= 0 && x < grid.size() && y >= 0 && y < grid[0].size()) { + if (gridValues[x][y] == INT_MAX) + q.push(make_pair(x, y)); + gridValues[x][y] = + min(gridValues[x][y], gridValues[pos.first][pos.second] + 1); + } + } + } + for (int i = 0; i < grid.size(); ++i) + for (int j = 0; j < grid[0].size(); ++j) + if (grid[i][j] == 0) + ans = max(ans, gridValues[i][j]); + return ans; + } +}; diff --git a/fibonacci_number.cpp b/fibonacci_number.cpp new file mode 100644 index 0000000..69e46ee --- /dev/null +++ b/fibonacci_number.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + int fib(int n) { + if (n < 2) + return n; + int ans[n + 1]; + ans[0] = 0; + ans[1] = 1; + for (int i = 2; i <= n; i++) + ans[i] = ans[i - 1] + ans[i - 2]; + return ans[n]; + } +}; + +int main() { + Solution obj; + cout << obj.fib(2); +} diff --git a/find_all_anagrams.c b/find_all_anagrams.c new file mode 100644 index 0000000..f5bca21 --- /dev/null +++ b/find_all_anagrams.c @@ -0,0 +1,49 @@ +// 438. Find All Anagrams in a String +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given two strings 's & p', return an array of all the start indices of 'p's + * anagrams in 's' (any order). an anagram is a word or phrase formed by + * rearranging the letters of a different word or phrase, typically using all + * original letters exactly one + */ + +int cmp(int *a, int *b) { + for (int i = 0; i < 26; i++) + if (a[i] != b[i]) + return 0; + return 1; +} + +int *findAnagrams(char *s, char *p, int *returnSize) { + int ssz = strlen(s), psz = strlen(p); + int *ans = (int *)malloc(sizeof(int) * ssz); + if (ssz < psz) + return ans; + int sabc[26] = {0}, pabc[26] = {0}; + (*returnSize) = 0; + for (int i = 0; i < psz; i++) { + pabc[p[i] - 'a']++; + sabc[s[i] - 'a']++; + } + for (int i = 0; i < ssz - psz; i++) { + if (i != 0) + sabc[s[i + psz - 1] - 'a']++; + if (cmp(sabc, pabc)) { + ans[*returnSize] = i; + (*returnSize)++; + } + sabc[s[i] - 'a']--; + } + return ans; +} + +int main() { + char s1[] = "cbaebabacd", s2[] = "abc"; + char p1[] = "abc", p2[] = "ab"; + int rs1[] = {2}, rs2[] = {3}; + printf("%d\n", *findAnagrams(s2, p1, rs1)); // expect: 0 6 + printf("%d\n", *findAnagrams(s2, p2, rs2)); // expect: 0 1 2 +} diff --git a/find_all_anagrams.cpp b/find_all_anagrams.cpp new file mode 100644 index 0000000..39fe153 --- /dev/null +++ b/find_all_anagrams.cpp @@ -0,0 +1,40 @@ +// 438. Find All Anagrams in a String +#include "leetcode.h" + +/* + * given two strings 's & p', return an array of all the start indices of 'p's + * anagrams in 's' (any order). an anagram is a word or phrase formed by + * rearranging the letters of a different word or phrase, typically using all + * original letters exactly one + */ + +class Solution { +public: + vector<int> findAnagrams(string s, string p) { + int ssz = s.size(), psz = p.size(); + if (ssz < psz) + return {}; + vector<int> freq(26, 0), window(26, 0), ans; + for (int i = 0; i < psz; i++) { + freq[p[i] - 'a']++; + window[s[i] - 'a']++; + } + if (freq == window) + ans.push_back(0); + for (int i = psz; i < ssz; i++) { + window[s[i - psz] - 'a']--; + window[s[i] - 'a']++; + if (freq == window) + ans.push_back(i - psz + 1); + } + return ans; + } +}; + +int main() { + Solution obj; + for (auto i : obj.findAnagrams("cbaebabacd", "abc")) + cout << i << ' '; // expect 0 6 + for (auto i : obj.findAnagrams("abab", "ab")) + cout << i << ' '; // expect 0 1 2 +} diff --git a/find_all_people_secret.c b/find_all_people_secret.c new file mode 100644 index 0000000..578799d --- /dev/null +++ b/find_all_people_secret.c @@ -0,0 +1,129 @@ +// 2092. Find All People With Secret +#include "leetcode.h" + +/* + * given an integer 'n' indicating there are 'n' people numbered from 0 to 'n - + * 1'. you are also given a 0-indexed 2d integer array 'meetings' where + * 'meetings[i] = [x_i, y_i, time_i]' indicates that person 'x_i' and person + * 'y_i' have a metting at 'time_i'. a person may attend multiple meetings at + * the same time. finally, you are given an integer 'firstPerson'. person 0 has + * a secret and initially shares the secret with a person 'firstPerson' at time + * 0. this secret is then shared every time a meeting takes place with a person + * that has the secret. more formall, for every meeting 'x_i', has secret at + * 'time_i' then they will share the secret with person 'y_i' and vice versa + */ + +int cmp(const void **a, const void **b) { + if ((*(int **)a)[2] == (*(int **)b)[2]) + return (*(int **)a)[0] - (*(int **)b)[0]; + return (*(int **)a)[2] - (*(int **)b)[2]; +} + +void check(int *list, int a, int b, int i, int *returnSize, int *ans, int *time, + int *timecount) { + if (list[a] - list[b] == 1) { + list[b]++; + ans[*returnSize] = b; + *returnSize += 1; + } else if (list[b] - list[a] == 1) { + list[a]++; + ans[*returnSize] = a; + *returnSize += 1; + } else if (list[b] == 0 && list[a] == 0) { + time[*timecount] = i; + *timecount += 1; + } +} + +void sametime(int **meetings, int *ans, int *returnSize, int *time, + int timecount, int *list) { + int count = 1, newtimecount; + while (count) { + int copy = *returnSize; + newtimecount = 0; + for (int i = 0; i < timecount; i++) { + check(list, meetings[time[i]][0], meetings[time[i]][1], time[i], + returnSize, ans, time, &newtimecount); + } + count = *returnSize - copy; + if (count == 0) { + break; + } + copy = *returnSize; + timecount = newtimecount; + newtimecount = 0; + for (int i = timecount - 1; i >= 0; i--) { + check(list, meetings[time[i]][0], meetings[time[i]][1], time[i], + returnSize, ans, time, &newtimecount); + } + count = *returnSize - copy; + timecount = newtimecount; + } +} + +int *findAllPeople(int n, int **meetings, int meetingsSize, + int *meetingsColSize, int firstPerson, int *returnSize) { + int *list = calloc(n, sizeof(int)); + int *ans = malloc(sizeof(int) * n); + int *time = malloc(sizeof(int) * n); + int timecount = 0; + *returnSize = 2; + for (int i = 0; i < meetingsSize; i++) { + if (meetings[i][0] > meetings[i][1]) { + int a = meetings[i][1]; + meetings[i][1] = meetings[i][0]; + meetings[i][0] = a; + } + } + qsort(meetings, meetingsSize, sizeof(int *), cmp); + list[0]++; + list[firstPerson]++; + ans[0] = 0; + ans[1] = firstPerson; + for (int i = 0; i < meetingsSize; i++) { + if (list[meetings[i][0]] - list[meetings[i][1]] == 1) { + list[meetings[i][1]]++; + ans[*returnSize] = meetings[i][1]; + *returnSize += 1; + } else if (list[meetings[i][1]] - list[meetings[i][0]] == 1) { + list[meetings[i][0]]++; + ans[*returnSize] = meetings[i][0]; + *returnSize += 1; + } else if (i + 1 < meetingsSize && meetings[i][2] == meetings[i + 1][2]) { + timecount = 0; + check(list, meetings[i][0], meetings[i][1], i, returnSize, ans, time, + &timecount); + i++; + while (i + 1 < meetingsSize && meetings[i][2] == meetings[i + 1][2]) { + check(list, meetings[i][0], meetings[i][1], i, returnSize, ans, time, + &timecount); + i++; + } + check(list, meetings[i][0], meetings[i][1], i, returnSize, ans, time, + &timecount); + sametime(meetings, ans, returnSize, time, timecount, list); + } + } + free(list); + free(time); + return ans; +} + +int main() { + int m1[3][3] = {{1, 2, 5}, {2, 3, 8}, {1, 5, 10}}, + m2[3][3] = {{3, 1, 3}, {1, 2, 2}, {0, 3, 3}}, + m3[3][3] = {{3, 4, 2}, {1, 2, 1}, {2, 3, 1}}; + int *mcs1, *mcs2, *mcs3, *rs1, *rs2, *rs3; + int *fap1 = findAllPeople(6, (int **)m1, 3, mcs1, 1, rs1); + int *fap2 = findAllPeople(4, (int **)m2, 3, mcs2, 1, rs2); + int *fap3 = findAllPeople(5, (int **)m3, 3, mcs3, 1, rs3); + for (int i = 0; i < 5; i++) + printf("%d ", fap1[i]); + printf("\n"); + for (int i = 0; i < 3; i++) + printf("%d ", fap2[i]); + printf("\n"); + for (int i = 0; i < 5; i++) + printf("%d ", fap3[i]); + printf("\n"); +} diff --git a/find_all_people_secret.py b/find_all_people_secret.py new file mode 100644 index 0000000..8d27193 --- /dev/null +++ b/find_all_people_secret.py @@ -0,0 +1,93 @@ +# 2092. Find All People With Secret +from collections import defaultdict + +""" +given an integer 'n' indicating there are 'n' people numbered from 0 to 'n - +1'. you are also given a 0-indexed 2d integer array 'meetings' where +'meetings[i] = [x_i, y_i, time_i]' indicates that person 'x_i' and person +'y_i' have a metting at 'time_i'. a person may attend multiple meetings at +the same time. finally, you are given an integer 'firstPerson'. person 0 has +a secret and initially shares the secret with a person 'firstPerson' at time +0. this secret is then shared every time a meeting takes place with a person +that has the secret. more formall, for every meeting 'x_i', has secret at +'time_i' then they will share the secret with person 'y_i' and vice versa +""" + + +class Solution(object): + def findAllPeople(self, n, meetings, firstPerson): + """ + :type n: int + :type meetings: List[List[int]] + :type firstPerson: int + :rtype: List[int] + """ + + class UnionFind: + def __init__(self): + self.parents = {} + self.ranks = {} + + def insert(self, x): + if x not in self.parents: + self.parents[x] = x + self.ranks[x] = 0 + + def find_parent(self, x): + if self.parents[x] != x: + self.parents[x] = self.find_parent(self.parents[x]) + return self.parents[x] + + def union(self, x, y): + self.insert(x) + self.insert(y) + x, y = self.find_parent(x), self.find_parent(y) + if x == y: + return + if self.ranks[x] > self.ranks[y]: + self.parents[y] = x + else: + self.parents[x] = y + if self.ranks[x] == self.ranks[y]: + self.ranks[y] += 1 + + time2meets = defaultdict(list) + for x, y, t in meetings: + time2meets[t].append((x, y)) + time2meets = sorted(time2meets.items()) + + curr_know = set([0, firstPerson]) + + for time, meets in time2meets: + uf = UnionFind() + for x, y in meets: + uf.union(x, y) + + groups = defaultdict(set) + for idx in uf.parents: + groups[uf.find_parent(idx)].add(idx) + + for group in groups.values(): + if group & curr_know: + curr_know.update(group) + + return list(curr_know) + + +if __name__ == "__main__": + obj = Solution() + print( + obj.findAllPeople( + n=6, meetings=[[1, 2, 5], [2, 3, 8], [1, 5, 10]], firstPerson=1 + ) + ) + print( + obj.findAllPeople( + n=4, meetings=[[3, 1, 3], [1, 2, 2], [0, 3, 3]], firstPerson=3 + ) + ) + print( + obj.findAllPeople( + n=5, meetings=[[3, 4, 2], [1, 2, 1], [2, 3, 1]], firstPerson=1 + ) + ) diff --git a/find_array_sorted.c b/find_array_sorted.c new file mode 100644 index 0000000..de6e701 --- /dev/null +++ b/find_array_sorted.c @@ -0,0 +1,38 @@ +// 3011. Find if Array Can Be Sorted +#include "leetcode.h" + +/* + * given a 0-indexed array of positive integers 'nums', in one operation you can + * swap any two adjacent elements if they have the same number of set bits. you + * are allowed to do this operation any number of times (including zero). return + * true if you can sort the array, otherwise return false. + */ + +bool canSortArray(int *nums, int numsSize) { + int prev_cnt = 0, prev_max = INT_MIN, prev_min = 0; + int curr_cnt, curr_max = 0, curr_min; + for (int i = 0; i < numsSize; i++) { + curr_cnt = __builtin_popcount(nums[i]); + if (curr_cnt != prev_cnt) { + if (curr_max < prev_max || curr_min < prev_max) + return false; + prev_max = curr_max; + curr_max = nums[i]; + curr_min = nums[i]; + prev_cnt = curr_cnt; + } else { + curr_max = fmax(curr_max, nums[i]); + curr_min = fmin(curr_min, nums[i]); + } + } + if (curr_max < prev_max || curr_min < prev_max) + return false; + return true; +} + +int main() { + int n1[] = {8, 4, 2, 30, 15}, n2[] = {1, 2, 3, 4, 5}, n3[] = {3, 16, 8, 4, 2}; + printf("%d\n", canSortArray(n1, ARRAY_SIZE(n1))); // expect: 1 + printf("%d\n", canSortArray(n2, ARRAY_SIZE(n2))); // expect: 1 + printf("%d\n", canSortArray(n3, ARRAY_SIZE(n3))); // expect: 0 +} diff --git a/find_array_sorted.py b/find_array_sorted.py new file mode 100644 index 0000000..1f0a735 --- /dev/null +++ b/find_array_sorted.py @@ -0,0 +1,26 @@ +# 3011. Find if Array Can Be Sorted +import itertools + +""" +given a 0-indexed array of positive integers 'nums', in one operation you can +swap any two adjacent elements if they have the same number of set bits. you +are allowed to do this operation any number of times (including zero). return +true if you can sort the array, otherwise return false. +""" + + +class Solution(object): + def canSortArray(self, nums): + """ + :type nums: List[int] + :rtype: bool + """ + grp = itertools.groupby(nums, key=lambda x: x.bit_count()) + return list(itertools.chain(*[sorted(g) for _, g in grp])) == sorted(nums) + + +if __name__ == "__main__": + obj = Solution() + print(obj.canSortArray([8, 4, 2, 30, 15])) + print(obj.canSortArray([1, 2, 3, 4, 5])) + print(obj.canSortArray([3, 16, 8, 4, 2])) diff --git a/find_bottom_left_tree.c b/find_bottom_left_tree.c new file mode 100644 index 0000000..7d6231d --- /dev/null +++ b/find_bottom_left_tree.c @@ -0,0 +1,35 @@ +// 513. Find Bottom Left Tree Value +#include "leetcode.h" + +/* + * given the 'root' of a binary tree, return the leftmost value in the last row + * of the tree + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int depth(struct TreeNode *root) { + if (!root) + return 0; + else + return 1 + fmax(depth(root->left), depth(root->right)); +} + +void dfs(struct TreeNode *root, int len, int *res) { + if (!root) + return; + if (!len) + *res = root->val; + dfs(root->right, len - 1, res); + dfs(root->right, len - 1, res); +} + +int findBottomLeftValue(struct TreeNode *root) { + int len = depth(root), ans = 0; + dfs(root, len - 1, &ans); + return ans; +} diff --git a/find_bottom_left_tree.py b/find_bottom_left_tree.py new file mode 100644 index 0000000..d1a2444 --- /dev/null +++ b/find_bottom_left_tree.py @@ -0,0 +1,21 @@ +# 513. Find Bottom Left Tree Value + +""" +given the 'root' of a binary tree, return the leftmost value in the last row +of the tree +""" + + +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def findBottomLeftValue(self, root): + queue = [root] + for node in queue: + queue += filter(None, (node.right, node.left)) + return node.val diff --git a/find_common_char.c b/find_common_char.c new file mode 100644 index 0000000..b8707fb --- /dev/null +++ b/find_common_char.c @@ -0,0 +1,51 @@ +// 1002. Find Common Characters +#include "leetcode.h" + +/* + * given a string array 'words' return an array of all characters that show up + * in all strings within the 'words' including duplicates. you may return the + * answer in any order. + */ + +#define MAX_WORD_LEN 100 + +char **commonChars(char **words, int wordsSize, int *returnSize) { + int table[MAX_WORD_LEN][26] = {0}, cnt = 0; + char **ans = (char **)malloc(MAX_WORD_LEN * sizeof(char *)); + for (int i = 0; i < MAX_WORD_LEN; i++) + ans[i] = (char *)malloc(2 * sizeof(char)); + for (int i = 0; i < wordsSize; i++) + for (int j = 0; j < words[i][j]; ++j) + table[i][words[i][j] - 'a']++; + for (int i = 0; i < 26; i++) { + int c = 0, min = MAX_WORD_LEN + 1; + for (int j = 0; j < wordsSize; j++) + if (table[j][i]) { + ++c; + if (table[j][i] < min) + min = table[j][i]; + } + if (c == wordsSize && min != MAX_WORD_LEN + 1) + for (int j = 0; j < min; ++j) { + ans[cnt][0] = (char)(i + 'a'); + ans[cnt][1] = '\0'; + ++cnt; + } + } + *returnSize = cnt; + return ans; +} + +int main() { + char *w1[] = {"bella", "label", "roller"}, *w2[] = {"cool", "lock", "cook"}; + int rs1, rs2; + char **cc1 = commonChars((char **)w1, ARRAY_SIZE(w1), &rs1); + char **cc2 = commonChars((char **)w2, ARRAY_SIZE(w2), &rs2); + for (int i = 0; i < rs1; i++) + printf("%s ", cc1[i]); + printf("\n"); // expect: e l l + for (int i = 0; i < rs2; i++) + printf("%s ", cc2[i]); + printf("\n"); // expect: c o + free(cc1), free(cc2); +} diff --git a/find_common_char.py b/find_common_char.py new file mode 100644 index 0000000..d9e9ee7 --- /dev/null +++ b/find_common_char.py @@ -0,0 +1,28 @@ +# 1002. Find Common Characters +from functools import reduce +from collections import Counter + +""" +given a string array 'words' return an array of all characters that show up +in all strings within the 'words' including duplicates. you may return the +answer in any order. +""" + + +class Solution(object): + def commonChars(self, words): + """ + :type words: List[str] + :rtype: List[str] + """ + ans = Counter(words[0]) + for w in words: + ans &= Counter(w) + return list(ans.elements()) + # return list(reduce(Counter.__and__, map(Counter, words)).elements()) + + +if __name__ == "__main__": + obj = Solution() + print(obj.commonChars(["bella", "label", "roller"])) + print(obj.commonChars(["cool", "lock", "cook"])) diff --git a/find_critical_edge_tree.cpp b/find_critical_edge_tree.cpp new file mode 100644 index 0000000..31c0338 --- /dev/null +++ b/find_critical_edge_tree.cpp @@ -0,0 +1,101 @@ +// 1489. Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree +#include "leetcode.h" + +/* + * given a weighted undirected connected graph with 'n' vertices numbered from 0 + * to 'n - 1' and an array 'edges' where 'edges[i] = [ai, bi, weighti]' + * represents a bidrectional and weighted edge between nodes 'ai' and 'bi'. a + * minimum spanning tree (MST) is a subset of the graph's edges that connects + * all vertices withoutcycles and with the minimum possible total edge weight. + * find all critical and pseudo-critical edges in the given graph's MST. an MST + * edge whose deletion from the graph would casue the MST weight to increase is + * called a critical edge. on the other hand, a pseudo-critical edge is that + * which can appear in some MSTs butnot all. note that you can return the + * indices of the edges in any order. + */ + +class UnionFind { + vector<int> f, rank; + +public: + UnionFind(int n) { + rank = vector<int>(n, 1); + f.resize(n); + for (int i = 0; i < n; ++i) + f[i] = i; + } + int find(int x) { + if (f[x] == x) + return x; + else + return f[x] = find(f[x]); + } + void uinion(int x, int y) { + int fx = find(x), fy = find(y); + if (fx == fy) + return; + if (rank[fx] > rank[fy]) + swap(fx, fy); + f[fx] = fy; + if (rank[fx] == rank[fy]) + rank[fy]++; + } +}; + +class Solution { + int get_mst(const int n, const vvd(int) & edges, int block_edge, + int pre_edge = -1) { + UnionFind uf(n); + int weight = 0; + if (pre_edge != -1) { + weight += edges[pre_edge][2]; + uf.uinion(edges[pre_edge][0], edges[pre_edge][1]); + } + for (int i = 0; i < edges.size(); ++i) { + if (block_edge == i) + continue; + const auto &e = edges[i]; + if (uf.find(e[0]) == uf.find(e[1])) + continue; + uf.uinion(e[0], e[1]); + weight += e[2]; + } + for (int i = 0; i < n; ++i) + if (uf.find(i) != uf.find(0)) + return 1e9 + 7; + return weight; + } + +public: + vvd(int) findCriticalAndPseudoCriticalEdges(int n, vvd(int) & edges) { + for (int i = 0; i < edges.size(); ++i) + edges[i].push_back(i); + sort( + edges.begin(), edges.end(), + [](const vector<int> &a, const vector<int> &b) { return a[2] < b[2]; }); + int origin_mst = get_mst(n, edges, -1); + vector<int> critical, non_critical; + for (int i = 0; i < edges.size(); ++i) { + if (origin_mst < get_mst(n, edges, i)) + critical.push_back(edges[i][3]); + else if (origin_mst == get_mst(n, edges, -1, i)) + non_critical.push_back(edges[i][3]); + } + return {critical, non_critical}; + } +}; + +int main() { + Solution obj; + vvd(int) e1 = {{0, 1, 1}, {1, 2, 1}, {2, 3, 2}, {0, 3, 2}, + {0, 4, 3}, {3, 4, 3}, {1, 4, 6}}, + e2 = {{0, 1, 1}, {1, 2, 1}, {2, 3, 1}, {0, 3, 1}}; + for (auto i : obj.findCriticalAndPseudoCriticalEdges(5, e1)) + for (auto j : i) + printf("%d ", j); + printf("\n"); + for (auto i : obj.findCriticalAndPseudoCriticalEdges(4, e2)) + for (auto j : i) + printf("%d ", j); + printf("\n"); +} diff --git a/find_difference.c b/find_difference.c new file mode 100644 index 0000000..948bbd5 --- /dev/null +++ b/find_difference.c @@ -0,0 +1,25 @@ +// 389. Find the Difference +#include <stdio.h> + +/* + * given two strings 's' and 't'. string 't' is generated by random shuffling + * string 's' and then add one more letter at a random position. return the + * letter that was added to 't'. + */ + +char findTheDifference(char *s, char *t) { + char ans = 0; + while (*s != '\0') { + ans ^= (*s) ^ (*t); + ++s; + ++t; + } + return ans ^ (*t); +} + +int main() { + char s1[] = {"abcd"}, t1[] = {"abcde"}; + char s2[] = {""}, t2[] = {"y"}; + printf("%c\n", findTheDifference(s1, t1)); // expect: e + printf("%c\n", findTheDifference(s2, t2)); // expect: y +} diff --git a/find_difference.py b/find_difference.py new file mode 100644 index 0000000..f0b26a6 --- /dev/null +++ b/find_difference.py @@ -0,0 +1,23 @@ +# 389. Find the Difference + +""" +given two strings 's' and 't'. string 't' is generated by random shuffling +string 's' and then add one more letter at a random position. return the +letter that was added to 't'. +""" + + +class Solution(object): + def findTheDifference(self, s, t): + ans = 0 + for i in s: + ans ^= ord(i) + for i in t: + ans ^= ord(i) + return chr(ans) + + +if __name__ == "__main__": + obj = Solution() + print(obj.findTheDifference("abcd", "abcde")) # expect: e + print(obj.findTheDifference("", "y")) # expect: y diff --git a/find_duplicate_array.c b/find_duplicate_array.c new file mode 100644 index 0000000..be574b1 --- /dev/null +++ b/find_duplicate_array.c @@ -0,0 +1,53 @@ +// 442. Find All Duplicates in an Array +#include "leetcode.h" + +/* + * given an integer array 'nums' of length 'n' where all the integers of 'nums' + * are in the range '[1, n]' and each integer appears once or twice, return an + * array of all the integers that appear twice. you must write an algorithm that + * runs in 'O(n)' time and uses only constant extra space. + */ + +int *findDuplicates(int *nums, int numsSize, int *returnSize) { + *returnSize = 0; + if (!nums || numsSize < 2) + return 0; + int *ans = NULL; + for (int i = 0; i < numsSize; i++) { + int n = abs(nums[i]) - 1; + if (nums[n] < 0) { + (*returnSize)++; + ans = realloc(ans, sizeof(int) * *returnSize); + ans[*returnSize - 1] = abs(nums[i]); + } else + nums[n] = -1 * nums[n]; + } + return ans; +} + +int main() { + int n1[] = {4, 3, 2, 7, 8, 2, 3, 1}, n2[] = {1, 1, 2}, n3[] = {1}, rs1, rs2, + rs3; + int *fd1 = findDuplicates(n1, ARRAY_SIZE(n1), &rs1); + int *fd2 = findDuplicates(n2, ARRAY_SIZE(n2), &rs2); + int *fd3 = findDuplicates(n3, ARRAY_SIZE(n3), &rs3); + if (fd1) + for (int i = 0; i < rs1; i++) + printf("%d ", fd1[i]); + else + printf("NULL"); + printf("\n"); + if (fd2) + for (int i = 0; i < rs2; i++) + printf("%d ", fd2[i]); + else + printf("NULL"); + printf("\n"); + if (fd3) + for (int i = 0; i < rs3; i++) + printf("%d ", fd3[i]); + else + printf("NULL"); + printf("\n"); + free(fd1), free(fd2), free(fd3); +} diff --git a/find_duplicate_array.py b/find_duplicate_array.py new file mode 100644 index 0000000..c3056fe --- /dev/null +++ b/find_duplicate_array.py @@ -0,0 +1,30 @@ +# 442. Find All Duplicates in an Array + +""" +given an integer array 'nums' of length 'n' where all the integers of 'nums' +are in the range '[1, n]' and each integer appears once or twice, return an +array of all the integers that appear twice. you must write an algorithm that +runs in 'O(n)' time and uses only constant extra space. +""" + + +class Solution(object): + def findDuplicates(self, nums): + """ + :type nums: List[int] + :rtype: List[int] + """ + ans = [] + for i in nums: + if nums[abs(i) - 1] < 0: + ans.append(abs(i)) + else: + nums[abs(i) - 1] *= -1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.findDuplicates(nums=[4, 3, 2, 7, 8, 2, 3, 1])) + print(obj.findDuplicates(nums=[1, 1, 2])) + print(obj.findDuplicates(nums=[1])) diff --git a/find_duplicate_file.cpp b/find_duplicate_file.cpp new file mode 100644 index 0000000..17ff6f0 --- /dev/null +++ b/find_duplicate_file.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + vvd(string) findDuplicate(vector<string> &paths) { + unordered_map<string, vector<string>> files; + vvd(string) ans; + for (auto &path : paths) { + int i = 0, j; + while (path[i] != ' ') + i++; + string dir = path.substr(0, i), file, content; + while (i++ < path.size()) { + j = i; + while (path[i] != '(') + i++; + file = path.substr(j, i - j); + j = i; + while (path[i++] != ')') + ; + content = path.substr(j, i - j); + files[content].emplace_back(dir + '/' + file); + } + } + for (auto &content : files) + if (content.second.size() > 1) + ans.push_back(move(content.second)); + return ans; + } +}; diff --git a/find_duplicate_num.c b/find_duplicate_num.c new file mode 100644 index 0000000..5549403 --- /dev/null +++ b/find_duplicate_num.c @@ -0,0 +1,25 @@ +// 287. Find the Duplicate Number +#include "leetcode.h" + +/* given an integer array 'nums' containing 'n + 1' integers where each integer + * is in the range '[1, n]' inclusive. there is only one repeated number in + * 'nums', return this repeated number. you must solve the problem without + * modifying the array 'nums' and uses only constant extra space. + */ + +int findDuplicate(int *nums, int nums_size) { + int *cnt = (int *)calloc(nums_size, sizeof(int)); + for (int i = 0; i < nums_size; i++) + cnt[nums[i] - 1]++; + for (int i = 0; i < nums_size; i++) + if (cnt[i] >= 2) + return i + 1; + free(cnt); + return -1; +} + +int main() { + int n1[] = {1, 3, 4, 2, 2}, n2[] = {3, 1, 3, 4, 2}; + printf("%d\n", findDuplicate(n1, 5)); // expect: 2 + printf("%d\n", findDuplicate(n2, 5)); // expect: 3 +} diff --git a/find_duplicate_num.py b/find_duplicate_num.py new file mode 100644 index 0000000..f1d6170 --- /dev/null +++ b/find_duplicate_num.py @@ -0,0 +1,24 @@ +# 287. Find the Duplicate Number + +""" +given an integer array 'nums' containing 'n + 1' integers where each integer +is in the range '[1, n]' inclusive. there is only one repeated number in +'nums', return this repeated number. you must solve the problem without +modifying the array 'nums' and uses only constant extra space. +""" + + +class Solution(object): + def findDuplicate(self, nums): + for n in nums: + idx = abs(n) + if nums[idx] < 0: + return idx + nums[idx] = -nums[idx] + return len(nums) + + +if __name__ == "__main__": + obj = Solution() + print(obj.findDuplicate([1, 3, 4, 2, 2])) # expect: 2 + print(obj.findDuplicate([3, 1, 3, 4, 2])) # expect: 3 diff --git a/find_duplicate_subtree.c b/find_duplicate_subtree.c new file mode 100644 index 0000000..a8ac477 --- /dev/null +++ b/find_duplicate_subtree.c @@ -0,0 +1,59 @@ +// 652. Find Duplicate Subtrees +#include "./lib/uthash/src/uthash.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given 'root' of a binary tree, return all duplicate subtrees. for each kind + * of duplicate, only return the root node of any one of them. two trees are + * duplicate if they have the same structure with the same node values. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +typedef struct { + char *r_key; + int cnt; + UT_hash_handle hh; +} h_elem; + +char *dfs(struct TreeNode *root, h_elem **map, struct TreeNode **ans, + int *idx) { + h_elem *tmp; + if (!root) { + char *r = calloc(sizeof(char), 2); + strcpy(r, "N"); + return r; + } + char *l_str = dfs(root->left, map, ans, idx); + char *r_str = dfs(root->right, map, ans, idx); + int c_len = strlen(l_str) + strlen(r_str) + 7; + char *ans_str = calloc(sizeof(char), c_len); + sprintf(ans_str, "%d, %s, %s\n", root->val, l_str, r_str); + HASH_FIND_STR(*map, ans_str, tmp); + if (tmp) { + tmp->cnt++; + if (tmp->cnt == 2) + ans[(*idx)++] = root; + } else { + h_elem *tmp = malloc(sizeof(h_elem)); + tmp->r_key = ans_str; + tmp->cnt = 1; + HASH_ADD_KEYPTR(hh, *map, tmp->r_key, strlen(tmp->r_key), tmp); + } + return ans_str; +} + +struct TreeNode **findDuplicateSubtrees(struct TreeNode *root, + int *returnSize) { + struct TreeNode **ans = malloc(sizeof(struct TreeNode *) * 250); + *returnSize = 0; + h_elem *map = NULL; + dfs(root, &map, ans, returnSize); + return ans; +} diff --git a/find_duplicate_subtree.cpp b/find_duplicate_subtree.cpp new file mode 100644 index 0000000..5880fc8 --- /dev/null +++ b/find_duplicate_subtree.cpp @@ -0,0 +1,30 @@ +// 652. Find Duplicate Subtrees +#include "leetcode.h" + +/* + * given 'root' of a binary tree, return all duplicate subtrees. for each kind + * of duplicate, only return the root node of any one of them. two trees are + * duplicate if they have the same structure with the same node values. + */ + +class Solution { +public: + vector<TreeNode *> findDuplicateSubtrees(TreeNode *root) { + unordered_map<string, vector<TreeNode *>> map; + vector<TreeNode *> dups; + serialise(root, map); + for (auto it = map.begin(); it != map.end(); it++) + if (it->second.size() > 1) + dups.push_back(it->second[0]); + return dups; + } + +private: + string serialise(TreeNode *node, + unordered_map<string, vector<TreeNode *>> &map) { + string s = "(" + serialise(node->left, map) + to_string(node->val) + + serialise(node->right, map) + ")"; + map[s].push_back(node); + return s; + } +}; diff --git a/find_duplicates_array.c b/find_duplicates_array.c new file mode 100644 index 0000000..14e6fd8 --- /dev/null +++ b/find_duplicates_array.c @@ -0,0 +1,48 @@ +// 442. Find All Duplicates in an Array +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array 'nums' of length 'n' where all the integers of 'nums' + * are in the range [1, n] and each integer appears once or twice. return an + * array of all the integers that appears twice. you must write an algorithm + * that run O(n) time and uses only constant extra space. + */ + +int *findDuplicats(int *nums, int nums_size, int *return_size) { + if (!nums || nums_size < 2) { + *return_size = 0; + return 0; + } + int *ans = NULL; + *return_size = 0; + for (int i = 0; i < nums_size; i++) { + int ti = abs(nums[i]) - 1; + if (nums[ti] < 0) { + *return_size += 1; + ans = realloc(ans, sizeof(int)); + ans[*return_size - 1] = abs(nums[i]); + } else + nums[ti] = -1 * nums[ti]; + } + return ans; +} + +int main() { + int n1[] = {4, 3, 2, 7, 8, 2, 3, 1}, ns1 = 8, rs1[] = {}; + int n2[] = {1, 1, 2}, ns2 = 3, rs2[] = {}; + int n3[] = {1}, ns3 = 1, rs3[] = {}; + int *fd1 = findDuplicats(n1, ns1, rs1); + int *fd2 = findDuplicats(n2, ns2, rs2); + int *fd3 = findDuplicats(n3, ns3, rs3); + for (int i = 0; i < ns1; i++) + printf("%d ", fd1[i]); // expect: 2 3 + printf("\n"); + for (int i = 0; i < ns2; i++) + printf("%d ", fd2[i]); // expect: 1 + printf("\n"); + for (int i = 0; i < ns3; i++) + printf("%d ", fd3[i]); // expect: + printf("\n"); +} diff --git a/find_first_last_array.c b/find_first_last_array.c new file mode 100644 index 0000000..a7d5468 --- /dev/null +++ b/find_first_last_array.c @@ -0,0 +1,61 @@ +// 34. Find First and Last Position of Element in Sorted Array +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array of integers 'nums' sorted in non-decreasing order, find the + * starting ending position of a given 'target' value. if target is not found in + * the array, return '[-1, -1]'. you must write an algorithm with O(log n) + * runtime complexity + */ + +int *searchRange(int *nums, int nums_size, int target, int *return_size) { + int l = 0, r = nums_size - 1, mid = r / 2; + *return_size = 2; + int *ans = malloc(sizeof(int) * 2); + ans[0] = -1; + ans[1] = -1; + while (l <= r) { + mid = l + (r - l) / 2; + if (target == nums[mid]) { + int mid2 = mid; + while (l < mid) { + int l_mid = (mid + l) / 2; + if (nums[l_mid] < target) + l = l_mid + 1; + else + mid = l_mid; + } + while (mid2 < r) { + int r_mid = (mid2 + r + 1) / 2; + if (nums[r_mid] > target) + r = r_mid - 1; + else + mid2 = r_mid; + } + ans[0] = l; + ans[1] = r; + return ans; + } else if (target < nums[mid]) + r = mid - 1; + else if (target > nums[mid]) + l = mid + 1; + } + return ans; +} + +int main() { + int n1[] = {5, 7, 7, 8, 8, 10}, n2[] = {5, 7, 7, 8, 8, 10}, n3[] = {}; + int *sr1 = searchRange(n1, 6, 8, NULL); + int *sr2 = searchRange(n2, 6, 6, NULL); + int *sr3 = searchRange(n3, 0, 0, NULL); + for (int i = 0; i < 2; i++) + printf("%d ", sr1[i]); // expect: 3 4 + printf("\n"); + for (int i = 0; i < 2; i++) + printf("%d ", sr2[i]); // expect: -1 -1 + printf("\n"); + for (int i = 0; i < 2; i++) + printf("%d ", sr3[i]); // expect: -1 -1 + printf("\n"); +} diff --git a/find_first_last_array.cpp b/find_first_last_array.cpp new file mode 100644 index 0000000..7f5f989 --- /dev/null +++ b/find_first_last_array.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> searchRange(vector<int> &nums, int target) { + int tLeft = find(target, nums); + if (tLeft == nums.size() || nums[tLeft] != target) + return {-1, -1}; + return {tLeft, find(target + 1, nums, tLeft) - 1}; + } + int find(int target, vector<int> arr, int left = 0) { + int right = arr.size() - 1; + while (left <= right) { + int mid = left + right >> 1; + if (arr[mid] < target) + left = mid + 1; + else + right = mid - 1; + } + return left; + } +}; diff --git a/find_first_last_array.py b/find_first_last_array.py new file mode 100644 index 0000000..d9dcdfb --- /dev/null +++ b/find_first_last_array.py @@ -0,0 +1,31 @@ +# 34. Find First and Last Position of Element in Sorted Array + +""" +given an array of integers 'nums' sorted in non-decreasing order, find the +starting ending position of a given 'target' value. if target is not found in +the array, return '[-1, -1]'. you must write an algorithm with O(log n) +runtime complexity +""" + +class Solution(object): + def searchRange(self, nums, target): + low, high = 0, len(nums) - 1 + index = -1 + while low <= high: + mid = (low + high) // 2 + if nums[mid] == target: + index = mid + if left: + high = mid - 1 + else: + low = mid + 1 + elif nums[mid] < target: + low = mid + 1 + else: + high = mid - 1 + return index + + left_index = binary_search(nums, target, left=True) + right_index = binary_search(nums, target, left=False) + + return [left_index, right_index] diff --git a/find_first_palindromic_str.c b/find_first_palindromic_str.c new file mode 100644 index 0000000..b2d32be --- /dev/null +++ b/find_first_palindromic_str.c @@ -0,0 +1,35 @@ +// 2108. Find First Palindromic String in the Array +#include "leetcode.h" + +/* + * given an array of strings 'words', return the first palindromic string in the + * array. if there is no such string, return an empty string. a string is a + * palindromic if it reads the same forward and backward. + */ + +char *firstPalindrome(char **words, int wordsSize) { + char *ans = ""; + for (int i = 0; i < wordsSize; i++) { + int start = 0, end = strlen(words[i]) - 1; + while (start < end) { + if (words[i][start] != words[i][end]) + break; + start++; + end--; + } + if (start == end || end < start) { + ans = words[i]; + break; + } + } + return ans; +} + +int main() { + char **w1 = {"abc", "car", "ada", "racecar", "cool"}; + char **w2 = {"notapalindrome", "racecar"}; + char **w3 = {"def", "ghi"}; + printf("%s\n", firstPalindrome(w1, 5)); // expect: ada + printf("%s\n", firstPalindrome(w2, 2)); // expect: racecar + printf("%s\n", firstPalindrome(w3, 2)); // expect: null +} diff --git a/find_first_palindromic_str.py b/find_first_palindromic_str.py new file mode 100644 index 0000000..1fd1a33 --- /dev/null +++ b/find_first_palindromic_str.py @@ -0,0 +1,26 @@ +# 2108. Find First Palindromic String in the Array + +""" +given an array of strings 'words', return the first palindromic string in the +array. if there is no such string, return an empty string. a string is a +palindromic if it reads the same forward and backward. +""" + + +class Solution(object): + def firstPalindrome(self, words): + """ + :type words: List[str] + :rtype: str + """ + for w in words: + if w == w[::-1]: + return w + return "" + + +if __name__ == "__main__": + obj = Solution() + print(obj.firstPalindrome(words=["abc", "car", "ada", "racecar", "cool"])) + print(obj.firstPalindrome(words=["notapalindrome", "racecar"])) + print(obj.firstPalindrome(words=["def", "ghi"])) diff --git a/find_group_farmland.c b/find_group_farmland.c new file mode 100644 index 0000000..dcbbd6e --- /dev/null +++ b/find_group_farmland.c @@ -0,0 +1,54 @@ +// 1992. Find All Groups of Farmland +#include "leetcode.h" + +/* + * given a 0-indexed 'm * n' binary matrix 'land' where a 0 represents a hectare + * of forested land and a 1 represents a hectare of farmland. to keep the land + * organised, there are designated rectangular areas of hectares that consist + * entirely of farmland. these rectangular areas are called groups. no two + * groups are adjacent, meaning farmland in one group is not four directionally + * adjacent to another farmland in another group. return a 2d array containing + * the 4 length arrays described above for each group o farmland in 'land'. + */ + +void dfs(int **land, int rows, int cols, int r, int c, int *top_left, + int *bottom_right, int *count) { + if (r < 0 || r >= rows || c < 0 || c >= cols || !land[r][c]) + return; + (*count)++; + if (r < top_left[0]) + top_left[0] = r; + if (c < top_left[1]) + top_left[1] = c; + if (r > bottom_right[0]) + bottom_right[0] = r; + if (c > bottom_right[1]) + bottom_right[1] = c; + land[r][c] = 0; + dfs(land, rows, cols, r + 1, c, top_left, bottom_right, count); + dfs(land, rows, cols, r - 1, c, top_left, bottom_right, count); + dfs(land, rows, cols, r, c + 1, top_left, bottom_right, count); + dfs(land, rows, cols, r, c - 1, top_left, bottom_right, count); +} + +int **findFarmland(int **land, int landSize, int *landColSize, int *returnSize, + int **returnColumnSizes) { + int m = landSize, n = *landColSize; + int **ans = (int **)malloc(sizeof(int *) * m * n); + *returnColumnSizes = (int *)malloc(sizeof(int) * (m * n)); + *returnSize = 0; + for (int i = 0; i < m; i++) + for (int j = 0; j < n; j++) + if (land[i][j] == '1') { + int top_left[2] = {i, j}, bottom_right[2] = {i, j}, cnt = 0, group[4]; + dfs(land, m, n, i, j, top_left, bottom_right, &cnt); + group[0] = top_left[0]; + group[1] = top_left[1]; + group[2] = bottom_right[0]; + group[3] = bottom_right[1]; + ans[*returnSize] = group; + (*returnColumnSizes)[*returnSize] = 4; + (*returnSize)++; + } + return ans; +} diff --git a/find_group_farmland.py b/find_group_farmland.py new file mode 100644 index 0000000..e52f31f --- /dev/null +++ b/find_group_farmland.py @@ -0,0 +1,59 @@ +# 1992. Find All Groups of Farmland + +""" +given a 0-indexed 'm n' binary matrix 'land' where a 0 represents a hectare +of forested land and a 1 represents a hectare of farmland. to keep the land +organised, there are designated rectangular areas of hectares that consist +entirely of farmland. these rectangular areas are called groups. no two +groups are adjacent, meaning farmland in one group is not four directionally +adjacent to another farmland in another group. return a 2d array containing +the 4 length arrays described above for each group o farmland in 'land'. +""" + + +class Solution(object): + def findFarmland(self, land): + """ + :type land: List[List[int]] + :rtype: List[List[int]] + """ + + def dfs(x, y): + stack = [(x, y)] + min_row, min_col = x, y + max_row, max_col = x, y + visited.add((x, y)) + while stack: + cur_x, cur_y = stack.pop() + for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]: + nx, ny = cur_x + dx, cur_y + dy + if ( + 0 <= nx < rows + and 0 <= ny < cols + and (nx, ny) not in visited + and land[nx][ny] == 1 + ): + visited.add((nx, ny)) + stack.append((nx, ny)) + min_row = min(min_row, nx) + min_col = min(min_col, ny) + max_row = max(max_row, nx) + max_col = max(max_col, ny) + return (min_row, min_col, max_row, max_col) + + rows, cols = len(land), len(land[0]) + visited = set() + ans = [] + for i in range(rows): + for j in range(cols): + if land[i][j] == 1 and (i, j) not in visited: + min_row, min_col, max_row, max_col = dfs(i, j) + ans.append([min_row, min_col, max_row, max_col]) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.findFarmland(land=[[1, 0, 0], [0, 1, 1], [0, 1, 1]])) + print(obj.findFarmland(land=[[1, 1], [1, 1]])) + print(obj.findFarmland(land=[[0]])) diff --git a/find_groups_farmland.cpp b/find_groups_farmland.cpp new file mode 100644 index 0000000..12b1b83 --- /dev/null +++ b/find_groups_farmland.cpp @@ -0,0 +1,43 @@ +#include "leetcode.h" + +class Solution { +public: + vvd(int) findFarmland(vvd(int) & land) { + int n = land.size(), m = land[0].size(); + vvd(int) ans; + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (land[i][j] == 1) { + if ((!i || !land[i - 1][j]) && (!j || !land[i][j - 1])) { + int right = j, down = i; + while (down + 1 < n && land[down + 1][j] == 1) + down++; + while (right + 1 < m && land[i][right + 1] == 1) + right++; + ans.push_back({i, j, down, right}); + } + } + } + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) l1 = {{1, 0, 0}, + { + 0, + 1, + 1, + }, + {0, 1, 1}}; + vvd(int) l2 = {{1, 1}, {1, 1}}; + for (auto i : obj.findFarmland(l1)) + for (auto j : i) + printf("%d ", j); // expect: [[0,0,0,0],[1,1,2,2]] + printf("\n"); + for (auto i : obj.findFarmland(l2)) + for (auto j : i) + printf("%d ", j); // expect: [[0,0,1,1]] +} diff --git a/find_highest_altitude.c b/find_highest_altitude.c new file mode 100644 index 0000000..3aa9adc --- /dev/null +++ b/find_highest_altitude.c @@ -0,0 +1,29 @@ +// 1732. Find the Highest Altitude +#include <limits.h> +#include <math.h> +#include <stdio.h> + +/* + * there is a biker going on a road trip. the road trip consists of 'n + 1' + * points at different altitudes. the biker starts his trip on point 0 with + * altitude 0. given an integer array 'ain' of length 'n' where 'gain[i]' is the + * net gain in altidude between points 'i' and 'i + 1' for all '0 <= i < n'. + * return the highest altitude of a point + */ + +int largestAltitude(int *gain, int gain_size) { + int ans = INT_MIN, pre_sum = 0; + for (int i = 0; i < gain_size; i++) { + ans = fmax(pre_sum, ans); + pre_sum += gain[i]; + } + if (pre_sum > ans) + ans = pre_sum; + return ans; +} + +int main() { + int g1[] = {-5, 1, 5, 0, -7}, g2[] = {-4, -3, -2, -1, 4, 3, 2}; + printf("%d\n", largestAltitude(g1, 5)); // expect: 1 + printf("%d\n", largestAltitude(g2, 7)); // expect: 0 +} diff --git a/find_highest_altitude.cpp b/find_highest_altitude.cpp new file mode 100644 index 0000000..c67dbac --- /dev/null +++ b/find_highest_altitude.cpp @@ -0,0 +1,31 @@ +// 1732. Find the Highest Altitude +#include "leetcode.h" + +/* + * there is a biker going on a road trip. the road trip consists of 'n + 1' + * points at different altitudes. the biker starts his trip on point 0 with + * altitude 0. given an integer array 'ain' of length 'n' where 'gain[i]' is the + * net gain in altidude between points 'i' and 'i + 1' for all '0 <= i < n'. + * return the highest altitude of a point + */ + +class Solution { +public: + int largestAltitude(vector<int> &gain) { + int ans = INT_MIN, pre_sum = 0; + for (int i = 0; i < gain.size(); i++) { + ans = max(pre_sum, ans); + pre_sum += gain[i]; + } + if (pre_sum > ans) + ans = pre_sum; + return ans; + } +}; + +int main() { + Solution obj; + vector<int> g1 = {-5, 1, 5, 0, -7}, g2 = {-4, -3, -2, -1, 4, 3, 2}; + printf("%d\n", obj.largestAltitude(g1)); // expect: 1 + printf("%d\n", obj.largestAltitude(g2)); // expect: 0 +} diff --git a/find_k_beauty_num.cpp b/find_k_beauty_num.cpp new file mode 100644 index 0000000..a8a224e --- /dev/null +++ b/find_k_beauty_num.cpp @@ -0,0 +1,16 @@ +#include "leetcode.h" + +class Solution { +public: + int divisorSubStrings(int num, int k) {} +}; + +int main() { + Solution obj; + cout << obj.divisorSubStrings(240, 2); + + int num = 240, k = 2; + string s = to_string(num); + int i = 0, j = 0, n = s.size(); + cout << s.size(); +} diff --git a/find_k_closest_elements.cpp b/find_k_closest_elements.cpp new file mode 100644 index 0000000..ecc1f53 --- /dev/null +++ b/find_k_closest_elements.cpp @@ -0,0 +1,16 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> findClosestElements(vector<int> &arr, int k, int x) { + int left = 0, right = arr.size() - k; + while (left < right) { + int mid = (left + right) / 2; + if (x - arr[mid] > arr[mid + k] - x) + left = mid + 1; + else + right = mid; + } + return vector<int>(arr.begin() + left, arr.begin() + left + k); + } +}; diff --git a/find_k_pair_sum.c b/find_k_pair_sum.c new file mode 100644 index 0000000..a388c5e --- /dev/null +++ b/find_k_pair_sum.c @@ -0,0 +1,87 @@ +// 373. Find K Pairs with Smallest Sums +#include <stdio.h> +#include <stdlib.h> + +/* + * given two integer arrays 'nums1 nums2' sorted in ascending order and an + * integer k. define a pair '(u, v)' which consists of one element from the + * first array and one element from the second array. return the 'k' pairs '(u1, + * v1), (u2, v2), ..., (uk, vk)' with the smallest sums + */ + +long long count_less_equal_items(int val, int *nums1, int n1, int *nums2, + int n2) { + long long res = 0; + for (int i = 0; i < n1; i++) { + int k = val - nums1[i]; + int l = 0, r = n2 - 1; + if (nums2[0] > k) + break; + while (l < r) { + int mid = r - (r - l) / 2; + if (nums2[mid] > k) + r = mid - 1; + else + l = mid; + } + res += (l + 1); + } + return res; +} + +int **kSmallestPairs(int *nums1, int nums1_size, int *nums2, int nums2_size, + int k, int *return_size, int **return_col_size) { + int n1 = nums1_size, n2 = nums2_size; + int lower = nums1[0] + nums2[0]; + int upper = nums1[n1 - 1] + nums2[n2 - 1]; + while (lower < upper) { + int mid = lower + (upper - lower) / 2; + long long t = count_less_equal_items(mid, nums1, n1, nums2, n2); + if (t >= k) + upper = mid; + else + lower = mid + 1; + } + int **ans = malloc(k * sizeof(int *)); + for (int i = 0; i < k; i++) + ans[i] = malloc(2 * sizeof(int)); + int **tmp = malloc(k * sizeof(int *)); + int a_idx = 0, t_idx = 0; + for (int i = 0; i < n1; i++) { + for (int j = 0; j < n2; j++) { + int sum = nums1[i] + nums2[j]; + if (sum < lower) { + ans[a_idx][0] = nums1[i]; + ans[a_idx][1] = nums2[j]; + a_idx++; + } else if (sum == lower) { + if (t_idx == k) + break; + tmp[t_idx] = malloc(2 * sizeof(int)); + tmp[t_idx][0] = nums1[i]; + tmp[t_idx][1] = nums2[j]; + t_idx++; + } else + break; + } + } + int a = 0; + if (a_idx < k) { + for (int i = a_idx; i < k; i++) { + if (a == t_idx) + break; + ans[a_idx][0] = tmp[a][0]; + ans[a_idx][1] = tmp[a][1]; + a++; + a_idx++; + } + } + *return_size = a_idx; + *return_col_size = malloc(a_idx * sizeof(int)); + for (int i = 0; i < a_idx; i++) + return_col_size[0][i] = 2; + for (int i = 0; i < t_idx; i++) + free(tmp[i]); + free(tmp); + return ans; +} diff --git a/find_k_pair_sum.cpp b/find_k_pair_sum.cpp new file mode 100644 index 0000000..a352b7e --- /dev/null +++ b/find_k_pair_sum.cpp @@ -0,0 +1,50 @@ +// 373. Find K Pairs with Smallest Sums +#include "leetcode.h" + +/* + * given two integer arrays 'nums1 nums2' sorted in ascending order and an + * integer k. define a pair '(u, v)' which consists of one element from the + * first array and one element from the second array. return the 'k' pairs '(u1, + * v1), (u2, v2), ..., (uk, vk)' with the smallest sums + */ + +class Solution { +public: + vvd(int) kSmallestPairs(vector<int> &nums1, vector<int> &nums2, int k) { + priority_queue<pair<int, pair<int, int>>, vector<pair<int, pair<int, int>>>, + greater<pair<int, pair<int, int>>>> + pq; + int n = nums1.size(), m = nums2.size(); + vvd(int) ans; + for (int i = 0; i < n; i++) + pq.push({nums1[i] + nums2[0], {i, 0}}); + while (!pq.empty() && k--) { + pair<int, pair<int, int>> tp = pq.top(); + int x = tp.second.first, y = tp.second.second; + pq.pop(); + ans.push_back({nums1[x], nums2[y]}); + if (y != m - 1) + pq.push({nums1[x] + nums2[y + 1], {x, y + 1}}); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n11 = {1, 7, 11}, n21 = {2, 4, 6}; + vector<int> n12 = {1, 1, 2}, n22 = {1, 2, 3}; + vector<int> n13 = {1, 2}, n23 = {3}; + for (auto i : obj.kSmallestPairs(n11, n21, 3)) + for (auto j : i) + printf("%d ", j); + printf("\n"); + for (auto i : obj.kSmallestPairs(n12, n22, 2)) + for (auto j : i) + printf("%d ", j); + printf("\n"); + for (auto i : obj.kSmallestPairs(n13, n23, 3)) + for (auto j : i) + printf("%d ", j); + printf("\n"); +} diff --git a/find_kth_largest_int_arr.c b/find_kth_largest_int_arr.c new file mode 100644 index 0000000..58a5f76 --- /dev/null +++ b/find_kth_largest_int_arr.c @@ -0,0 +1,96 @@ +// 1985. Find the Kth Largest Integer in the Array +#include "leetcode.h" + +/* + * you are given an array of strings 'nums' and an integer 'k'. each string in + * 'nums' represents an integer without leading zeros. return the string that + * represents the k'th largest integer in 'nums'. duplicate numbers should be + * counted distinctly. + */ + +int cmp(const void *a, const void *b) { + char *aa = *(char **)a, *bb = *(char **)b; + int na = strlen(aa), nb = strlen(bb); + if (na == nb) { + for (int i = 0; i < na; i++) + if (aa[i] != bb[i]) + return aa[i] - bb[i]; + return 0; + } + return na - nb; +} + +bool is_leq(char *s, char *t) { + int n1 = strlen(s), n2 = strlen(t); + if (n1 < n2) + return true; + if (n1 > n2) + return false; + for (int i = 0; i < n1; i++) { + if (s[i] < t[i]) + return true; + if (s[i] > t[i]) + return false; + } + return true; +} + +void insert(char **heap, int k, char *s) { + if (is_leq(s, heap[0])) + return; + heap[0] = s; + int f = 0; + while (1) { + int s1 = 2 * f + 1, s2 = 2 * f + 2; + if (s2 < k) { + if (is_leq(heap[s1], heap[s2])) { + if (is_leq(heap[s1], heap[f])) { + char *tmp = heap[f]; + heap[f] = heap[s1]; + heap[s1] = tmp; + f = s1; + } else { + break; + } + } else { + if (is_leq(heap[s2], heap[f])) { + char *tmp = heap[f]; + heap[f] = heap[s2]; + heap[s2] = tmp; + f = s2; + } else { + break; + } + } + } else if (s1 < k) { + if (is_leq(heap[s1], heap[f])) { + char *tmp = heap[f]; + heap[f] = heap[s1]; + heap[s1] = tmp; + f = s1; + } else { + break; + } + } else { + break; + } + } +} + +char *kthLargestNumber(char **nums, int numsSize, int k) { + char **heap = (char **)malloc((k + 1) * sizeof(char *)); + for (int i = 0; i < k; i++) + heap[i] = nums[i]; + qsort(heap, k, sizeof(char *), cmp); + for (int i = k; i < numsSize; i++) + insert(heap, k, nums[i]); + return heap[0]; +} + +int main() { + char *n1[] = {"3", "6", "7", "10"}, *n2[] = {"2", "21", "12", "1"}, + *n3[] = {"0", "0"}; + printf("%s\n", kthLargestNumber((char **)n1, ARRAY_SIZE(n1), 4)); // expect: 3 + printf("%s\n", kthLargestNumber((char **)n2, ARRAY_SIZE(n2), 3)); // expect: 2 + printf("%s\n", kthLargestNumber((char **)n3, ARRAY_SIZE(n3), 2)); // expect: 0 +} diff --git a/find_kth_largest_int_arr.py b/find_kth_largest_int_arr.py new file mode 100644 index 0000000..488bdd1 --- /dev/null +++ b/find_kth_largest_int_arr.py @@ -0,0 +1,31 @@ +# 1985. Find the Kth Largest Integer in the Array +import heapq + +""" +you are given an array of strings 'nums' and an integer 'k'. each string in +'nums' represents an integer without leading zeros. return the string that +represents the k'th largest integer in 'nums'. duplicate numbers should be +counted distinctly. +""" + + +class Solution(object): + def kthLargestNumber(self, nums, k): + """ + :type nums: List[str] + :type k: int + :rtype: str + """ + max_heap = [-int(x) for x in nums] + heapq.heapify(max_heap) + while k > 1: + heapq.heappop(max_heap) + k -= 1 + return str(-max_heap[0]) + + +if __name__ == "__main__": + obj = Solution() + print(obj.kthLargestNumber(nums=["3", "6", "7", "10"], k=4)) + print(obj.kthLargestNumber(nums=["2", "21", "12", "1"], k=3)) + print(obj.kthLargestNumber(nums=["0", "0"], k=2)) diff --git a/find_largest_val_tree.c b/find_largest_val_tree.c new file mode 100644 index 0000000..35678f2 --- /dev/null +++ b/find_largest_val_tree.c @@ -0,0 +1,72 @@ +// 515. Find Largest Value in Each Tree Row +#include "leetcode.h" + +/* + * given the 'root' of a binary tree, return an array of the largest value in + * each row of the tree (0-indexed) + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int depth(struct TreeNode *root) { + if (!root) + return 0; + else + return 1 + fmax(depth(root->left), depth(root->right)); +} + +int *largestValues(struct TreeNode *root, int *return_size) { + int dep = depth(root); + if (!dep) { + *return_size = 0; + return 0; + } + int *ans = malloc(dep * sizeof(int)); + int ans_idx = 0, idx0 = 0, idx1 = 0; + struct TreeNode **q0 = malloc(5000 * sizeof(struct TreeNode *)); + struct TreeNode **q1 = malloc(5000 * sizeof(struct TreeNode *)); + q0[idx0] = root; + idx0 = 1; + while (idx0 || idx1) { + int max = INT_MIN; + if (idx0) { + for (int i = 0; i < idx0; i++) { + if (q0[i]->val > max) + max = q0[i]->val; + if (q0[i]->left) { + q1[idx1] = q0[i]->left; + idx1++; + } + if (q0[i]->right) { + q1[idx1] = q0[i]->right; + idx1++; + } + } + ans[ans_idx] = max; + ans_idx++; + idx0 = 0; + } else { + for (int i = 0; i < idx1; i++) { + if (q1[i]->val > max) + max = q1[i]->val; + if (q1[i]->left) { + q0[idx0] = q1[i]->left; + idx0++; + } + if (q1[i]->right) { + q0[idx0] = q1[i]->right; + idx0++; + } + } + ans[ans_idx] = max; + ans_idx++; + idx1 = 0; + } + } + *return_size = ans_idx; + return ans; +} diff --git a/find_largest_val_tree.py b/find_largest_val_tree.py new file mode 100644 index 0000000..b47375e --- /dev/null +++ b/find_largest_val_tree.py @@ -0,0 +1,29 @@ +# 515. Find Largest Value in Each Tree Row + +""" +given the 'root' of a binary tree, return an array of the largest value in +each row of the tree (0-indexed) +""" + + +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def largestValues(self, root): + ans = [] + row = [root] + while any(row): + ans.append(max(node.val for node in row)) + row = [child for node in row for child in (node.left, node.right) if child] + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.largestValues(root=[1, 3, 2, 5, 3, null, 9])) # expect: 1, 3, 9 + print(obj.largestValues(root=[1, 2, 3])) # expect: 1, 3 diff --git a/find_len_longest_prefix.c b/find_len_longest_prefix.c new file mode 100644 index 0000000..2d8bb36 --- /dev/null +++ b/find_len_longest_prefix.c @@ -0,0 +1,33 @@ +// 3043. Find the Length of the Longest Common Prefix +#include "leetcode.h" + +/* + * given two arrays with positive integers 'arr1' and 'arr2'. a prefix of a + * positive integer is an integer formed by one or more of its digits, starting + * from its leftmost digit. a common prefix of two integers 'a' and 'b' is an + * integer 'c' such that is a prefix of both a and b. for example 6555359 and + * 56554 have a common prefix 565 while q223 and 43456 do not have a common + * prefix. return the length of the longest common prefix among all pairs. if no + * common prefix exists among them, return 0. + */ + +struct node { + char val; + int height; + struct node *children[10]; +}; + +struct trie { + struct node *root; +}; + +int longestCommonPrefix(int *arr1, int arr1_size, int *arr2, int arr2_size) {} + +int main() { + int a11[] = {1, 10, 100}, a21[] = {1000}; + int a12[] = {1, 2, 3}, a22[] = {4, 4, 4}; + printf("%d\n", longestCommonPrefix(a11, ARRAY_SIZE(a11), a21, + ARRAY_SIZE(a21))); // expect: 3 + printf("%d\n", longestCommonPrefix(a12, ARRAY_SIZE(a12), a22, + ARRAY_SIZE(a22))); // expect: 3 +} diff --git a/find_len_longest_prefix.py b/find_len_longest_prefix.py new file mode 100644 index 0000000..821e911 --- /dev/null +++ b/find_len_longest_prefix.py @@ -0,0 +1,55 @@ +# 3043. Find the Length of the Longest Common Prefix +from bisect import bisect_left + +""" +given two arrays with positive integers 'arr1' and 'arr2'. a prefix of a +positive integer is an integer formed by one or more of its digits, starting +from its leftmost digit. a common prefix of two integers 'a' and 'b' is an +integer 'c' such that is a prefix of both a and b. for example 6555359 and +56554 have a common prefix 565 while q223 and 43456 do not have a common +prefix. return the length of the longest common prefix among all pairs. if no +common prefix exists among them, return 0. +""" + + +class Solution(object): + def longestCommonPrefix(self, arr1, arr2): + """ + :type arr1: List[int] + :type arr2: List[int] + :rtype: int + """ + + def findCommonPrefixLength(x, y): + common_prefix_length = 0 + min_length = min(len(x), len(y)) + + for i in range(min_length): + if x[i] == y[i]: + common_prefix_length += 1 + else: + break + + return common_prefix_length + + a = [str(x) for x in arr1] + b = [str(x) for x in arr2] + + a.sort() + b.sort() + + ans = 0 + n = len(a) + for i in range(len(b)): + idx = bisect_left(a, b[i]) + if idx < n: + ans = max(ans, findCommonPrefixLength(a[idx], b[i])) + if idx > 0: + ans = max(ans, findCommonPrefixLength(a[idx - 1], b[i])) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.longestCommonPrefix(arr1=[1, 10, 100], arr2=[1000])) + print(obj.longestCommonPrefix(arr1=[1, 2, 3], arr2=[4, 4, 4])) diff --git a/find_max_sum_node_val.cpp b/find_max_sum_node_val.cpp new file mode 100644 index 0000000..d9f8fd7 --- /dev/null +++ b/find_max_sum_node_val.cpp @@ -0,0 +1,43 @@ +// 3068. Find the Maximum Sum of Node Values +#include "leetcode.h" + +/* + * there exists an undirected tree with 'n' nodes numbered 0 to 'n - 1'. you are + * given a 0-indexed 2d integer array 'edges' of length 'n - 1', where 'edges[i] + * = [ui,vi]' indicates that there is an edge between nodes 'ui' and 'vi' in the + * tree. you are also given a positive integer 'k' and a 0 indexed array of non + * negative integers 'nums' of length 'n' where 'nums[i]' represents the value + * of the node numbered 'i'. return the maximum possible sum of the values alice + * can achieve by performing the operation any number of times. + */ + +class Solution { +public: + long long maximumValueSum(vector<int> &nums, int k, + vector<vector<int>> &edges) { + int change = 0; + long long sum = 0LL, ans = 0LL; + for (auto &n : nums) { + if ((n ^ k) > n) { + change++; + sum += (n ^ k); + } else + sum += n; + } + if (!(change & 1)) + return sum; + for (int i = 0; i < nums.size(); i++) + ans = max(ans, sum - abs(nums[i] - (nums[i] ^ k))); + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 2, 1}, n2 = {2, 3}, n3 = {7, 7, 7, 7, 7, 7}; + vvd(int) e1 = {{0, 1}, {0, 2}}, e2 = {{0, 1}}, + e3 = {{0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}}; + printf("%lld\n", obj.maximumValueSum(n1, 3, e1)); // expect: 6 + printf("%lld\n", obj.maximumValueSum(n2, 7, e2)); // expect: 9 + printf("%lld\n", obj.maximumValueSum(n3, 3, e3)); // expect: 42 +} diff --git a/find_max_sum_node_val.py b/find_max_sum_node_val.py new file mode 100644 index 0000000..80bc7d4 --- /dev/null +++ b/find_max_sum_node_val.py @@ -0,0 +1,38 @@ +# 3068. Find the Maximum Sum of Node Values + +""" +there exists an undirected tree with 'n' nodes numbered 0 to 'n - 1'. you are +given a 0-indexed 2d integer array 'edges' of length 'n - 1', where 'edges[i] += [ui,vi]' indicates that there is an edge between nodes 'ui' and 'vi' in the +tree. you are also given a positive integer 'k' and a 0 indexed array of non +negative integers 'nums' of length 'n' where 'nums[i]' represents the value +of the node numbered 'i'. return the maximum possible sum of the values alice +can achieve by performing the operation any number of times. +""" + + +class Solution(object): + def maximumValueSum(self, nums, k, edges): + """ + :type nums: List[int] + :type k: int + :type edges: List[List[int]] + :rtype: int + """ + ans, c, d = 0, 0, 1 << 30 + for n in nums: + ans += max(n, b := n ^ k) + c ^= n < b + d = min(d, abs(n - b)) + return ans - d * c + + +if __name__ == "__main__": + obj = Solution() + print(obj.maximumValueSum(nums=[1, 2, 1], k=3, edges=[[0, 1], [0, 2]])) + print(obj.maximumValueSum(nums=[2, 3], k=7, edges=[[0, 1]])) + print( + obj.maximumValueSum( + nums=[7, 7, 7, 7, 7, 7], k=3, edges=[[0, 1], [0, 2], [0, 3], [0, 4], [0, 5]] + ) + ) diff --git a/find_median_data_stream.cpp b/find_median_data_stream.cpp new file mode 100644 index 0000000..14fbcc3 --- /dev/null +++ b/find_median_data_stream.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +class MedianFinder { +public: + void addNum(int num) { + small.push(num); + large.push(-small.top()); + small.pop(); + if (small.size() < large.size()) { + small.push(-large.top()); + large.pop(); + } + } + double findMedian() { + if (small.size() > large.size()) + return small.top(); + else + return (small.top() - large.top()) / 2.0; + } + +private: + priority_queue<long> small, large; +}; + +int main() { + MedianFinder *obj = new MedianFinder(); + obj->addNum(69); + double param_2 = obj->findMedian(); +} diff --git a/find_median_data_stream.rs b/find_median_data_stream.rs new file mode 100644 index 0000000..1ef5252 --- /dev/null +++ b/find_median_data_stream.rs @@ -0,0 +1,41 @@ +use std::cmp::Reverse; +use std::collections::BinaryHeap; +#[derive(Default)] +struct MedianFinder { + small: BinaryHeap<i32>, + large: BinaryHeap<Reverse<i32>>, + odd: bool +} + +impl MedianFinder { + fn new() -> Self { + Default::default() + } + fn add_num(&mut self, num: i32) { + if self.odd { + self.small.push(num); + if let Some(max) = self.small.pop() { + self.large.push(Reverse(max)); + } + } else { + self.large.push(Reverse(num)); + if let Some(Reverse(min)) = self.large.pop() { + self.small.push(min);; + } + } + self.odd = !self.odd; + } + fn find_median(&self) -> f64 { + if self.odd { + *self.small.peek().unwrap() as f64 + } else { + (self.small.peek().unwrap() + self.large.peek().unwrap().0) as f64 / 2.0 + } + } +} + +fn main() { + let obj = MedianFinder::new(); + obj.add_num(num); + let ret_2: f64 = obj.find_median(); +} diff --git a/find_min_rotated_arr.c b/find_min_rotated_arr.c new file mode 100644 index 0000000..87b4963 --- /dev/null +++ b/find_min_rotated_arr.c @@ -0,0 +1,29 @@ +// 153. Find Minimum in Rotated Sorted Array +#include "leetcode.h" + +/* + * suppose an array of length 'n' sorted in ascending order is rotated between 1 + * and 'n' times. for example, the array nums '0 1 2 4 5 6 7' mine become a + * different array. return the sorted array unique elements minimum times. + * algorithm must be o log n time. + */ + +int findMin(int *nums, int nums_size) { + int low = 0, high = nums_size - 1; + while (low < high) { + int mid = low + (high - low) / 2; + if (nums[mid] < nums[high]) + high = mid; + else + low = mid + 1; + } + return nums[low]; +} + +int main() { + int n1[] = {3, 4, 5, 1, 2}, n2[] = {4, 5, 6, 7, 0, 1, 2}, + n3[] = {11, 13, 15, 17}; + printf("%d\n", findMin(n1, ARRAY_SIZE(n1))); // expect: 1 + printf("%d\n", findMin(n2, ARRAY_SIZE(n2))); // expect: 0 + printf("%d\n", findMin(n3, ARRAY_SIZE(n3))); // expect: 11 +} diff --git a/find_min_rotated_arr.py b/find_min_rotated_arr.py new file mode 100644 index 0000000..18f5390 --- /dev/null +++ b/find_min_rotated_arr.py @@ -0,0 +1,34 @@ +# 153. Find Minimum in Rotated Sorted Array + +""" +suppose an array of length 'n' sorted in ascending order is rotated between 1 +and 'n' times. for example, the array nums '0 1 2 4 5 6 7' mine become a +different array. return the sorted array unique elements minimum times. +algorithm must be o log n time. +""" + + +class Solution(object): + def findMin(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + if len(nums) == 1 or nums[0] < nums[-1]: + return nums[0] + left, right = 0, len(nums) - 1 + while left <= right: + mid = left + (right - left) // 2 + if mid > 0 and nums[mid - 1] > nums[mid]: + return nums[mid] + if nums[mid] > nums[right]: + left = mid + 1 + else: + right = mid - 1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.findMin([3, 4, 5, 1, 2])) + print(obj.findMin([4, 5, 6, 7, 0, 1, 2])) + print(obj.findMin([11, 13, 15, 17])) diff --git a/find_missing_observations.c b/find_missing_observations.c new file mode 100644 index 0000000..87fafbc --- /dev/null +++ b/find_missing_observations.c @@ -0,0 +1,63 @@ +// 2028. Find Missing Observations +#include "leetcode.h" + +/* + * you have observations of n + m 6 sided dice rolls withh each face numbered + * from 1 to 6. n of the observations went missing and you only have the + * observations of m rolls. fortunately, you have also calculated thhe average + * value of the n + m rolls. you are given an integer array rolls of length m + * where rolls[i] is the value of the i'th observation. you are also given the + * two integers mean and n. return an array of length n containing thhe missing + * observations such that the average value of the n + m rolls is exactly mean. + * if there are multiple valid answers, return any of them. if no such array + * exists, return an empty array. thhe average value of a set of k numbers is + * the sum of the numbers divided by k. note that mean is an integer so the sum + * of the n + m rolls should be divisble by n + m. + */ + +int *missingRolls(int *rolls, int rolls_size, int mean, int n, + int *return_size) { + int sum = 0; + for (int i = 0; i < rolls_size; i++) + sum += rolls[i]; + int target = mean * (rolls_size + n); + int diff = target - sum; + if (diff < n || diff > 6 * n) { + *return_size = 0; + return NULL; + } + int *ans = malloc(n * sizeof(int)); + *return_size = n; + for (int i = 0; i < n; i++) + ans[i] = diff / n; + diff -= n * (diff / n); + int pos = 0; + while (diff) { + if (diff > (6 - ans[pos])) { + diff -= (6 - ans[pos]); + ans[pos] = 6; + } else { + ans[pos] += diff; + diff = 0; + } + pos++; + } + return ans; +} + +int main() { + int r1[] = {3, 2, 4, 3}, r2[] = {1, 5, 6}, r3[] = {1, 2, 3, 4}; + int rs1[] = {}, rs2[] = {}, rs3[] = {}; + int *mr1 = missingRolls(r1, 4, 4, 2, rs1), + *mr2 = missingRolls(r2, 3, 3, 4, rs2), + *mr3 = missingRolls(r3, 4, 6, 4, rs3); + for (int i = 0; i < 2; i++) + printf("%d ", mr1[i]); // expect: 6 6 + printf("\n"); + for (int i = 0; i < 4; i++) + printf("%d ", mr2[i]); // expect: 2 3 2 2 + printf("\n"); + for (int i = 0; i < 1; i++) + printf("%d ", mr3[i]); // expect: null + printf("\n"); +} diff --git a/find_missing_observations.py b/find_missing_observations.py new file mode 100644 index 0000000..2707c67 --- /dev/null +++ b/find_missing_observations.py @@ -0,0 +1,43 @@ +# 2028. Find Missing Observations + +""" +you have observations of n + m 6 sided dice rolls withh each face numbered +from 1 to 6. n of the observations went missing and you only have the +observations of m rolls. fortunately, you have also calculated thhe average +value of the n + m rolls. you are given an integer array rolls of length m +where rolls[i] is the value of the i'th observation. you are also given the +two integers mean and n. return an array of length n containing thhe missing +observations such that the average value of the n + m rolls is exactly mean. +if there are multiple valid answers, return any of them. if no such array +exists, return an empty array. thhe average value of a set of k numbers is +the sum of the numbers divided by k. note that mean is an integer so the sum +of the n + m rolls should be divisble by n + m. +""" + + +class Solution(object): + def missingRolls(self, rolls, mean, n): + """ + :type rolls: List[int] + :type mean: int + :type n: int + :rtype: List[int] + """ + m = len(rolls) + curr = sum(rolls) + missing = mean * (n + m) - curr + if missing < n or missing > 6 * n: + return [] + + part, rem = divmod(missing, n) + ans = [part] * n + for i in range(rem): + ans[i] += 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.missingRolls(rolls=[3, 2, 4, 3], mean=4, n=2)) + print(obj.missingRolls(rolls=[1, 5, 6], mean=3, n=4)) + print(obj.missingRolls(rolls=[1, 2, 3, 4], mean=6, n=4)) diff --git a/find_mode_bst.c b/find_mode_bst.c new file mode 100644 index 0000000..1aa3d2d --- /dev/null +++ b/find_mode_bst.c @@ -0,0 +1,49 @@ +// 501. Find Mode in Binary Search Tree +#include "leetcode.h" + +/* + * given the 'root' of a binary search tree with duplicates, return all the + * 'modes(s)' (ie. the most frequently occured element in it). if the tree has + * more than one mode, return them in any order. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +void order(struct TreeNode *root, int *cnt, int a[2][10000], int *max) { + if (!root) + return; + order(root->left, cnt, a, max); + if (!a[1][*cnt]) { + a[0][*cnt] = root->val; + a[1][*cnt]++; + } else if (root->val != a[0][*cnt]) { + (*cnt)++; + a[0][*cnt] = root->val; + a[1][*cnt]++; + } else { + a[1][*cnt]++; + } + if (*max < a[1][*cnt]) + *max = a[1][*cnt]; + order(root->right, cnt, a, max); +} + +int *findMode(struct TreeNode *root, int *return_size) { + if (!root) + return NULL; + int a[2][10000] = {0}; + int *max = (int *)malloc(sizeof(int)); + int *cnt = (int *)malloc(sizeof(int)); + *max = 0, *cnt = 0; + order(root, cnt, a, max); + int *ans = (int *)malloc(sizeof(int) * 10000); + *return_size = 0; + for (int i = 0; i <= *cnt; i++) + if (a[1][i] == *max) + ans[(*return_size)++] = a[0][i]; + return ans; +} diff --git a/find_mode_bst.py b/find_mode_bst.py new file mode 100644 index 0000000..b53ed61 --- /dev/null +++ b/find_mode_bst.py @@ -0,0 +1,44 @@ +# 501. Find Mode in Binary Search Tree + +""" +given the 'root' of a binary search tree with duplicates, return all the +'modes(s)' (ie. the most frequently occured element in it). if the tree has +more than one mode, return them in any order. +""" + + +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + prev = None + max_cnt = 0 + curr_cnt = 0 + ans = [] + + def dfs(self, node): + if not node: + return + self.dfs(node.left) + self.curr_cnt = 1 if node.val != self.prev else self.curr_cnt + 1 + if self.curr_cnt == self.max_cnt: + self.ans.append(node.val) + elif self.curr_cnt > self.max_cnt: + self.ans = [node.val] + self.max_cnt = self.curr_cnt + self.prev = node.val + self.dfs(node.right) + + def findMode(self, root): + self.dfs(root) + return self.ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.findMode([1, None, 2, 2])) # expect: 2 + print(obj.findMode([0])) # expect: 0 diff --git a/find_mountain.c b/find_mountain.c new file mode 100644 index 0000000..91d11c1 --- /dev/null +++ b/find_mountain.c @@ -0,0 +1,91 @@ +// 1095. Find in Mountain Array +#include <limits.h> +#include <math.h> +#include <stdbool.h> +#include <stdlib.h> + +/* + * 1. find peak and record location and value that's already been queried, and + * verify if target has happened + * 2. if target has happened and idx <= peak, exit and return ans + * 3. query right of mountain and return true if target is found + * 4. query left of mountain and return true if target is found + * 5. if target is not found, return -1 + */ + +int get(MountainArray *, int index); +int length(MountainArray *); + +int find_peak(MountainArray *mountain_arr, int len, int *data, bool *flag, + int target, int *idx) { + int left = 0, right = len - 1, mid, l, m, r; + while (left < right) { + mid = (left + right) / 2; + m = get(mountain_arr, mid); + flag[mid] = true; + data[mid] = m; + if (m == target) + *idx = fmin(*idx, mid); + r = get(mountain_arr, mid + 1); + flag[mid + 1] = true; + data[mid + 1] = r; + if (r == target) + *idx = fmin(*idx, mid + 1); + if (m < r) + left = mid + 1; + else { + l = get(mountain_arr, mid - 1); + flag[mid - 1] = true; + data[mid - 1] = l; + if (l == target) + *idx = fmin(*idx, mid - 1); + if (m > l) + return mid; + else + right = mid - 1; + } + } + return left; +} + +int find_val(MountainArray *mountain_arr, int begin, int end, int val, + int *data, bool *flag, bool up) { + int left = begin, right = end, tmp; + while (left < right) { + int mid = left + (right - left) / 2; + if (flag[mid]) + tmp = data[mid]; + else + tmp = get(mountain_arr, mid); + if (tmp == val) + return mid; + if (tmp > val) { + if (up) + right = mid - 1; + else + left = mid + 1; + } + } + if (get(mountain_arr, left) == val) + return left; + else + return -1; +} + +int findInMountainArray(int target, MountainArray *mountain_arr) { + int len = length(mountain_arr), *idx = malloc(sizeof(int)), ans; + int *data = malloc(len * sizeof(int)); + bool *flag = calloc(len, sizeof(bool)); + *idx = INT_MAX; + int peak = find_peak(mountain_arr, len, data, flag, target, idx); + if (*idx <= peak) { + ans = *idx; + goto exit; + } + ans = find_val(mountain_arr, 0, peak, target, data, flag, true); + if (ans == -1) + ans = find_val(mountain_arr, peak + 1, len - 1, target, data, flag, false); +exit: + free(data), free(flag); + return ans; +} diff --git a/find_mountain.py b/find_mountain.py new file mode 100644 index 0000000..b9b374d --- /dev/null +++ b/find_mountain.py @@ -0,0 +1,39 @@ +# 1095. Find in Mountain Array + +""" +1. find peak and record location and value that's already been queried, and verify if target has happened +2. if target has happened and idx <= peak, exit and return ans +3. query right of mountain and return true if target is found +4. query left of mountain and return true if target is found +5. if target is not found, return -1 +""" + +class Solution(object): + def findInMountainArray(self, target, A): + n = A.length() + l, r = 0, n - 1 + while l < r: + m = (l + r) / 2 + if A.get(m) < A.get(m + 1): + l = peak = m + 1 + else: + r = m + l, r = 0, peak + while l <= r: + m = (l + r) / 2 + if A.get(m) < target: + l = m + 1 + elif A.get(m) > target: + r = m - 1 + else: + return m + l, r = peak, n - 1 + while l <= r: + m = (l + r) / 2 + if A.get(m) > target: + l = m + 1 + elif A.get(m) < target: + r = m - 1 + else: + return m + return -1 diff --git a/find_orig_array_double.cpp b/find_orig_array_double.cpp new file mode 100644 index 0000000..a434616 --- /dev/null +++ b/find_orig_array_double.cpp @@ -0,0 +1,19 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> findOriginalArray(vector<int> &changed) { + int count[100001] = {}, i = 0; + vector<int> ans; + for (auto n : changed) + ++count[n]; + for (int i = 0; i <= 50000; ++i) + if (count[i]) { + if (--count[i * 2] < 0 || --count[i] < 0) + return {}; + ans.push_back(i--); + } + return accumulate(begin(count) + 50000, end(count), 0ll) ? vector<int>() + : ans; + } +}; diff --git a/find_orig_prefix_xor.c b/find_orig_prefix_xor.c new file mode 100644 index 0000000..f07d68d --- /dev/null +++ b/find_orig_prefix_xor.c @@ -0,0 +1,31 @@ +// 2433. Find The Original Array of Prefix Xor +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array 'pref' of size 'n'. find and return the array 'arr' of + * size 'n' that satisfies 'pref[i] = arr[0] ^ arr[1] ^ ... ^ arr[i]'. note that + * '^' denotes the bitwise xor operator. it can be proven that the answer is + * unique + */ + +int *findArray(int *pref, int pref_size, int *return_size) { + int *ans = malloc(pref_size * sizeof(int)); + *return_size = pref_size; + ans[0] = pref[0]; + for (int i = 1; i < pref_size; i++) + ans[i] = pref[i - 1] ^ pref[i]; + return ans; +} + +int main() { + int p1[] = {5, 2, 0, 3, 1}, p2[] = {13}; + int rs1[] = {}, rs2[] = {}; + int *fa1 = findArray(p1, 5, rs1), *fa2 = findArray(p2, 1, rs2); + for (int i = 0; i < 5; i++) + printf("%d ", fa1[i]); // expect: 5 7 2 3 2 + printf("\n"); + for (int i = 0; i < 1; i++) + printf("%d ", fa2[i]); // expect: 13 + printf("\n"); +} diff --git a/find_orig_prefix_xor.py b/find_orig_prefix_xor.py new file mode 100644 index 0000000..d92df0e --- /dev/null +++ b/find_orig_prefix_xor.py @@ -0,0 +1,20 @@ +# 2433. Find The Original Array of Prefix Xor + +""" +given an integer array 'pref' of size 'n'. find and return the array 'arr' of +size 'n' that satisfies 'pref[i] = arr[0] ^ arr[1] ^ ... ^ arr[i]'. note that +'^' denotes the bitwise xor operator. it can be proven that the answer is +unique +""" + +class Solution(object): + def findArray(self, pref): + for i in range(len(pref) - 1, 0, -1): + pref[i] ^= pref[i - 1] + return pref + + +if __name__ == "__main__": + obj = Solution() + print(obj.findArray([5,2,0,3,1])) # expect: 5 7 2 3 2 + print(obj.findArray([13])) # expect: 13 diff --git a/find_palindrome_fixed_length.c b/find_palindrome_fixed_length.c new file mode 100644 index 0000000..37acf74 --- /dev/null +++ b/find_palindrome_fixed_length.c @@ -0,0 +1,45 @@ +// 2217. Find Palindrome With Fixed Length +#include "leetcode.h" + +/* + * given an integer array 'queries' and a positive integer 'intLength', return + * an array 'ans' where 'ans[i]' is either the 'queries[i]'th smallest positive + * palindreom of length 'intLength' or -1 if no such palindrome exists. + */ + +long long reverse(int num, int n) { + long long res = 0; + if (n % 2) + num /= 10; + while (num) { + res = res * 10 + num % 10; + num /= 10; + } + return res; +} + +long long *kthPalindrome(int *queries, int queriesSize, int intLength, + int *returnSize) { + long long *ans = (long long *)malloc(queriesSize * sizeof(long long)); + *returnSize = queriesSize; + int n = (intLength + 1) / 2, min = pow(10, n - 1), max = pow(10, n) - 1, + mul = pow(10, n - intLength % 2); + for (int i = 0; i < queriesSize; i++) + ans[i] = min + queries[i] - 1 > max + ? -1 + : (long long)(min + queries[i] - 1) * mul + + reverse(min + queries[i] - 1, intLength); + return ans; +} + +int main() { + int q1[] = {1, 2, 3, 4, 5, 90}, q2[] = {2, 4, 6}, rs1, rs2; + long long *kp1 = kthPalindrome(q1, ARRAY_SIZE(q1), 3, &rs1); + long long *kp2 = kthPalindrome(q2, ARRAY_SIZE(q2), 4, &rs2); + for (int i = 0; i < rs1; i++) + printf("%lld ", kp1[i]); // expect: 101,111,121,131,141,999 + printf("\n"); + for (int i = 0; i < rs2; i++) + printf("%lld ", kp2[i]); // expect: 1111,1331,1551 + printf("\n"); +} diff --git a/find_palindrome_fixed_length.py b/find_palindrome_fixed_length.py new file mode 100644 index 0000000..0c9ed80 --- /dev/null +++ b/find_palindrome_fixed_length.py @@ -0,0 +1,28 @@ +# 2217. Find Palindrome With Fixed Length + +""" +given an integer array 'queries' and a positive integer 'intLength', return +an array 'ans' where 'ans[i]' is either the 'queries[i]'th smallest positive +palindreom of length 'intLength' or -1 if no such palindrome exists. +""" + + +class Solution(object): + def kthPalindrome(self, queries, intLength): + """ + :type queries: List[int] + :type intLength: int + :rtype: List[int] + """ + base = 10 ** ((intLength - 1) / 2) + ans = [q - 1 + base for q in queries] + for i, a in enumerate(ans): + a = str(a) + str(a)[-1 - intLength % 2 :: -1] + ans[i] = int(a) if len(a) == intLength else -1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.kthPalindrome(queries=[1, 2, 3, 4, 5, 90], intLength=3)) + print(obj.kthPalindrome(queries=[2, 4, 6], intLength=4)) diff --git a/find_path_exist_graph.c b/find_path_exist_graph.c new file mode 100644 index 0000000..d52dfa9 --- /dev/null +++ b/find_path_exist_graph.c @@ -0,0 +1,47 @@ +// 1971. Find if Path Exists in Graph +#include "leetcode.h" + +/* + * there is a bidirectional graph with 'n' vertices where each vertex is labeled + * from 0 to 'n - 1' inclusive. the edges in the graph are rpresented as a 2d + * integer array 'edges', where each 'edgies[i] = [ui, vi]', denotes a + * bidirectional edge between vertex 'ui' and vertex 'vi'. every vertex pair is + * connected by at most one edge, and no vertex has an edge to itself. + */ + +bool validPath(int n, int **edges, int edgesSize, int *edgesColSize, int source, + int destination) { + if (source == destination) + return 1; + bool vis_map[n], stk_map[n]; + for (int i = 0; i < n; i++) { + stk_map[i] = 0; + vis_map[i] = 0; + } + int stk[n]; + uint pt = -1; + stk[++pt] = source; + stk_map[source] = 1; + while (pt != -1) { + while (vis_map[stk[pt]]) + pt--; + vis_map[stk[pt]] = 1; + int top = stk[pt--]; + stk_map[top] = 0; + for (int i = 0; i < edgesSize; i++) + for (int j = 0; j < *edgesColSize; j++) + if (edges[i][j] == top) { + int vertex = edges[i][*edgesColSize - j - 1]; + if (vertex == destination) + return 1; + if (!vis_map[vertex] && !stk_map[vertex]) { + stk[++pt] = vertex; + stk_map[vertex] = 1; + } + edges[i][j] = n; + edges[i][*edgesColSize - j - 1] = n; + break; + } + } + return vis_map[destination]; +} diff --git a/find_path_exist_graph.py b/find_path_exist_graph.py new file mode 100644 index 0000000..d3501b1 --- /dev/null +++ b/find_path_exist_graph.py @@ -0,0 +1,49 @@ +# 1971. Find if Path Exists in Graph +from collections import defaultdict + +""" +there is a bidirectional graph with 'n' vertices where each vertex is labeled +from 0 to 'n - 1' inclusive. the edges in the graph are rpresented as a 2d +integer array 'edges', where each 'edgies[i] = [ui, vi]', denotes a +bidirectional edge between vertex 'ui' and vertex 'vi'. every vertex pair is +connected by at most one edge, and no vertex has an edge to itself. +""" + + +class Solution(object): + def validPath(self, n, edges, source, destination): + """ + :type n: int + :type edges: List[List[int]] + :type source: int + :type destination: int + :rtype: bool + """ + neighbors = defaultdict(list) + for n1, n2 in edges: + neighbors[n1].append(n2) + neighbors[n2].append(n1) + + def dfs(node, destination, seen): + if node == destination: + return True + if node in seen: + return False + seen.add(node) + for n in neighbors[node]: + if dfs(n, destination, seen): + return True + return False + + seen = set() + return dfs(source, destination, seen) + + +if __name__ == "__main__": + obj = Solution() + print(obj.validPath(n=3, edges=[[0, 1], [1, 2], [2, 0]], source=0, destination=2)) + print( + obj.validPath( + n=6, edges=[[0, 1], [0, 2], [3, 5], [5, 4], [4, 3]], source=0, destination=5 + ) + ) diff --git a/find_path_graph.cpp b/find_path_graph.cpp new file mode 100644 index 0000000..0fae12b --- /dev/null +++ b/find_path_graph.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" + +class Solution { +public: + bool validPath(int n, vvd(int) & edges, int source, int destination) { + vector<int> ds(n, -1); + for (auto &e : edges) { + int p1 = find(ds, e[0]), p2 = find(ds, e[1]); + if (p1 != p2) + ds[p2] = p1; + } + return find(ds, source) == find(ds, destination); + } + +private: + int find(vector<int> &ds, int i) { + return ds[i] < 0 ? i : ds[i] = find(ds, ds[i]); + } +}; + +int main() { + Solution obj; + vvd(int) edges = {{0, 1}, {1, 2}, {2, 0}}; + if (obj.validPath(3, edges, 0, 2)) + cout << "true"; + else + cout << "false"; +} diff --git a/find_path_graph.rs b/find_path_graph.rs new file mode 100644 index 0000000..a74a654 --- /dev/null +++ b/find_path_graph.rs @@ -0,0 +1,48 @@ +struct Solution; + +impl Solution { + pub fn valid_path(n: i32, edges: Vec<Vec<i32>>, source: i32, destination: i32) -> bool { + let n: usize = n as usize; + let mut roots: Vec<usize> = { + let mut ans: Vec<usize> = vec![0; n]; + for i in 0..n { + ans[i] = i; + } + ans + }; + let mut ranks: Vec<usize> = vec![1; n]; + for e in edges { + let u = e[0] as usize; + let v = e[1] as usize; + Self::union(u, v, &mut roots, &mut ranks); + } + Self::find(source as usize, &mut roots) == Self::find(destination as usize, &mut roots) + } + fn union(x: usize, y: usize, roots: &mut Vec<usize>, ranks: &mut Vec<usize>) { + let (root_x, root_y) = (Self::find(x, roots), Self::find(y, roots)); + if root_x == root_y { + return; + } + if ranks[x] > ranks[y] { + roots[root_y] = root_x; + ranks[root_x] += 1; + } else { + roots[root_x] = root_y; + ranks[root_y] += 1; + } + } + fn find(x: usize, roots: &mut Vec<usize>) -> usize { + let mut x = x; + while x != roots[x] { + roots[x] = roots[roots[x]]; + x = roots[x]; + } + x + } +} + +fn main() { + let (n, source, destination) = (3, 0, 2); + let edges = vec![vec![0,1], vec![1,2], vec![2,0]]; + print!("{}", Solution::valid_path(n, edges, source, destination)); +} diff --git a/find_peak_element.c b/find_peak_element.c new file mode 100644 index 0000000..9803f70 --- /dev/null +++ b/find_peak_element.c @@ -0,0 +1,45 @@ +// 162. Find Peak Element +#include "leetcode.h" + +/* + * a peak element is an element that is strictly greater than its neighbours. + * given a 0 indexed array 'nums', find a peak element and return its index. if + * the array contains multiple peaks, return the index to any of the peaks. you + * may imagine that 'nums[-1] = nums[n] = -inf' in other words, an element is + * always considered to be strictly greater than a neighbour that is outside the + * array. you must write an algorithm that runs in 'O(log n)' time. + */ + +int findPeakElement(int *nums, int numsSize) { + if (numsSize == 1) + return 0; + if (numsSize == 2) + return nums[0] > nums[1] ? 0 : 1; + int left = 0, right = numsSize - 1, mid; + while (left < right) { + mid = (left + right) / 2; + if (!mid) + break; + if (nums[mid] > nums[mid + 1] && nums[mid] > nums[mid - 1]) + return mid; + else if (nums[mid] > nums[mid - 1]) + left = mid + 1; + else + right = mid - 1; + } + if (right < numsSize - 1 && right) { + if (nums[right] > nums[right + 1] && nums[right] > nums[right - 1]) + return right; + } else if (left < numsSize - 1 && left) { + if (nums[left] > nums[left + 1] && nums[left] > nums[left - 1]) + return left; + } else + return !left ? left : right; + return 0; +} + +int main() { + int n1[] = {1, 2, 3, 1}, n2[] = {1, 2, 1, 3, 5, 6, 4}; + printf("%d\n", findPeakElement(n1, ARRAY_SIZE(n1))); // expect: 2 + printf("%d\n", findPeakElement(n2, ARRAY_SIZE(n2))); // expect: 5 +} diff --git a/find_peak_element.py b/find_peak_element.py new file mode 100644 index 0000000..18ef2f9 --- /dev/null +++ b/find_peak_element.py @@ -0,0 +1,34 @@ +# 162. Find Peak Element + +""" +a peak element is an element that is strictly greater than its neighbours. +given a 0 indexed array 'nums', find a peak element and return its index. if +the array contains multiple peaks, return the index to any of the peaks. you +may imagine that 'nums[-1] = nums[n] = -inf' in other words, an element is +always considered to be strictly greater than a neighbour that is outside the +array. you must write an algorithm that runs in 'O(log n)' time. +""" + + +class Solution(object): + def findPeakElement(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + left, right = 0, len(nums) - 1 + while left < right - 1: + mid = (left + right) / 2 + if nums[mid] > nums[mid + 1] and nums[mid] > nums[mid - 1]: + return mid + if nums[mid] < nums[mid + 1]: + left = mid + 1 + else: + right = mid - 1 + return left if nums[left] >= nums[right] else right + + +if __name__ == "__main__": + obj = Solution() + print(obj.findPeakElement(nums=[1, 2, 3, 1])) + print(obj.findPeakElement(nums=[1, 2, 1, 3, 5, 6, 4])) diff --git a/find_pivot_integer.c b/find_pivot_integer.c new file mode 100644 index 0000000..53175ec --- /dev/null +++ b/find_pivot_integer.c @@ -0,0 +1,28 @@ +// 2485. Find the Pivot Integer +#include "leetcode.h" + +/* + * given a positive integer 'n', find the pivot integer 'x' such that the sum of + * all elements between 1 and 'x' inclusively equals the sum of all elements + * between 'x' and 'n' inclusively. return the pivot integer 'x'. if no such + * integer exists, return -1. it is guaranteed that there will be at most one + * pivot index for the given input. + */ + +int pivotInteger(int n) { + int l = 1, r = n, sum = n * (n + 1) / 2; + while (l < r) { + int m = (l + r) / 2; + if (m * m - sum < 0) + l = m + 1; + else + r = m; + } + return !(l * l - sum) ? l : -1; +} + +int main() { + printf("%d\n", pivotInteger(8)); // expect: 6 + printf("%d\n", pivotInteger(1)); // expect: 1 + printf("%d\n", pivotInteger(4)); // expect: -1 +} diff --git a/find_pivot_integer.py b/find_pivot_integer.py new file mode 100644 index 0000000..f99a295 --- /dev/null +++ b/find_pivot_integer.py @@ -0,0 +1,30 @@ +# 2485. Find the Pivot Integer +from math import sqrt + +""" +given a positive integer 'n', find the pivot integer 'x' such that the sum of +all elements between 1 and 'x' inclusively equals the sum of all elements +between 'x' and 'n' inclusively. return the pivot integer 'x'. if no such +integer exists, return -1. it is guaranteed that there will be at most one +pivot index for the given input. +""" + + +class Solution(object): + def pivotInteger(self, n): + """ + :type n: int + :rtype: int + """ + tmp = (n * n + n) // 2 + sqr = int(sqrt(tmp)) + if sqr * sqr == tmp: + return sqr + return -1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.pivotInteger(8)) + print(obj.pivotInteger(1)) + print(obj.pivotInteger(4)) diff --git a/find_player_zero_one_loss.cpp b/find_player_zero_one_loss.cpp new file mode 100644 index 0000000..75c0e15 --- /dev/null +++ b/find_player_zero_one_loss.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + vvd(int) findWinners(vvd(int) & matches) { + map<int, int> lost; + for (auto m : matches) { + if (!lost.count(m[0])) + lost[m[0]] = 0; + lost[m[1]]++; + } + vector<int> zero, ones; + for (auto [k, l] : lost) { + if (l == 0) + zero.push_back(k); + if (l == 1) + ones.push_back(k); + } + return {zero, ones}; + } +}; diff --git a/find_player_zero_one_loss.rs b/find_player_zero_one_loss.rs new file mode 100644 index 0000000..a0ae44e --- /dev/null +++ b/find_player_zero_one_loss.rs @@ -0,0 +1,14 @@ +use std::collections::BTreeMap; +struct Solution; + +impl Solution { + pub fn find_winners(matches: Vec<Vec<i32>>) -> Vec<Vec<i32>> { + let mut lost: BTreeMap<i32, i32> = matches.into_iter().fold(BTreeMap::new(), |mut hm, m| { + hm.entry(m[0]).or_insert(0); + *hm.entry(m[1]).or_insert(0) += 1; + hm + }); + return vec![lost.iter().filter(|(_, l)| **l == 0).map(|(&i, _)| i).collect(), + lost.iter().filter(|(_, l)| **l == 1).map(|(&i, _)| i).collect()]; + } +} diff --git a/find_players_zero_loss.c b/find_players_zero_loss.c new file mode 100644 index 0000000..269789e --- /dev/null +++ b/find_players_zero_loss.c @@ -0,0 +1,37 @@ +// 2225. Find Players With Zero or One Losses +#include "leetcode.h" + +/* + * given an integer array 'matches' where 'matches[i] = [winner[i], loser[i]]' + * indicates a defeated player 'loser[i]' in a match. return a list 'answer' of + * size 2 where 'answer[0]' is a list of all players that have not lost any + * matches. 'answer[1]' is a list of all players that have lost exactly one + * match. the values in the two lists should be returned in increasing order. + */ + +int cmp(const void *a, const void *b) { + return *(const int *)a - *(const int *)b; +} + +int **findWinners(int **matches, int matches_size, int *matches_col_size, + int *return_size, int **return_col_size) { + int losers[100001] = {0}; + *return_size = 2; + int **ans = (int **)malloc((*return_size) * sizeof(int)); + *return_col_size = (int *)calloc((*return_size), sizeof(int)); + for (int i = 0; i < *return_size; i++) + ans[i] = (int *)malloc(matches_size * sizeof(int)); + for (int i = 0; i < matches_size; i++) + losers[matches[i][1]]++; + for (int i = 0; i < matches_size; i++) { + if (losers[matches[i][1]] == 1) + ans[1][*return_col_size[1]++] = matches[i][1]; + if (losers[matches[i][0]] == 0) { + ans[0][*return_col_size[0]++] = matches[i][0]; + losers[matches[i][0]] = -1; + } + } + qsort(ans[0], *return_col_size[0], sizeof(int), cmp); + qsort(ans[1], *return_col_size[1], sizeof(int), cmp); + return ans; +} diff --git a/find_players_zero_loss.py b/find_players_zero_loss.py new file mode 100644 index 0000000..428e306 --- /dev/null +++ b/find_players_zero_loss.py @@ -0,0 +1,49 @@ +# 2225. Find Players With Zero or One Losses + +""" +given an integer array 'matches' where 'matches[i] = [winner[i], loser[i]]' +indicates a defeated player 'loser[i]' in a match. return a list 'answer' of +size 2 where 'answer[0]' is a list of all players that have not lost any +matches. 'answer[1]' is a list of all players that have lost exactly one +match. the values in the two lists should be returned in increasing order. +""" + + +class Solution(object): + def findWinners(self, matches): + """ + :type matches: List[List[int]] + :rtype: List[List[int]] + """ + losses = [0] * 100001 + for winner, loser in matches: + if losses[winner] == 0: + losses[winner] = -1 + if losses[loser] == -1: + losses[loser] = 1 + else: + losses[loser] += 1 + zero_loss = [i for i in range(1, 100001) if losses[i] == -1] + one_loss = [i for i in range(1, 100001) if losses[i] == 1] + return [zero_loss, one_loss] + + +if __name__ == "__main__": + obj = Solution() + print( + obj.findWinners( + matches=[ + [1, 3], + [2, 3], + [3, 6], + [5, 6], + [5, 7], + [4, 5], + [4, 8], + [4, 9], + [10, 4], + [10, 9], + ] + ) + ) + print(obj.findWinners(matches=[[2, 3], [1, 3], [5, 4], [6, 4]])) diff --git a/find_polygon_largest_perimeter.c b/find_polygon_largest_perimeter.c new file mode 100644 index 0000000..6372eb9 --- /dev/null +++ b/find_polygon_largest_perimeter.c @@ -0,0 +1,34 @@ +// 2971. Find Polygon With the Largest Perimeter +#include "leetcode.h" + +/* + * given an arry of positive integers 'nums' of length 'n'. a polygon is a + * closed plane figure that has at least 3 sides. the longest side of a polygon + * is smaller than the sum of its other sides. conversely, if you have 'k (k >= + * 3)' positive real numbers then there always exists a polygon with 'k' sides + * whose lengths are 'a1,a2,...ak'. the perimeter of a polygon is the sum of + * lengths of its sides. return the largest possible perimeter of a polygon + * whose sides can be formed from 'nums' or '-1' if it is not possible to create + * a polygon. + */ + +int cmp(const void *a, const void *b) { return *(int *)b - *(int *)a; } + +long long largestPerimeter(int *nums, int nums_size) { + long long ans = -1, sums[nums_size - 1]; + qsort(nums, nums_size, sizeof(int), cmp); + sums[nums_size - 2] = nums[nums_size - 2] + nums[nums_size - 1]; + for (int i = nums_size - 3; i >= 0; i--) { + sums[i] = nums[i] + sums[i + 1]; + if (nums[i] < sums[i + 1]) + ans = sums[i]; + } + return ans; +} + +int main() { + int n1[] = {5, 5, 5}, n2[] = {1, 12, 1, 2, 5, 50, 3}, n3[] = {5, 5, 50}; + printf("%lld\n", largestPerimeter(n1, ARRAY_SIZE(n1))); // expect: 15 + printf("%lld\n", largestPerimeter(n2, ARRAY_SIZE(n2))); // expect: 12 + printf("%lld\n", largestPerimeter(n3, ARRAY_SIZE(n3))); // expect: -1 +} diff --git a/find_polygon_largest_perimeter.py b/find_polygon_largest_perimeter.py new file mode 100644 index 0000000..571301f --- /dev/null +++ b/find_polygon_largest_perimeter.py @@ -0,0 +1,32 @@ +# 2971. Find Polygon With the Largest Perimeter + +""" +given an arry of positive integers 'nums' of length 'n'. a polygon is a +closed plane figure that has at least 3 sides. the longest side of a polygon +is smaller than the sum of its other sides. conversely, if you have 'k (k >= +3)' positive real numbers then there always exists a polygon with 'k' sides +whose lengths are 'a1,a2,...ak'. the perimeter of a polygon is the sum of +lengths of its sides. return the largest possible perimeter of a polygon +whose sides can be formed from 'nums' or '-1' if it is not possible to create +a polygon. +""" + + +class Solution(object): + def largestPerimeter(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + nums.sort() + curr = sum(nums) + while nums and curr <= nums[-1] * 2: + curr -= nums.pop() + return sum(nums) if len(nums) > 2 else -1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.largestPerimeter(nums=[5, 5, 5])) + print(obj.largestPerimeter(nums=[1, 12, 1, 2, 5, 50, 3])) + print(obj.largestPerimeter(nums=[5, 5, 50])) diff --git a/find_replace_pattern.c b/find_replace_pattern.c new file mode 100644 index 0000000..64dc015 --- /dev/null +++ b/find_replace_pattern.c @@ -0,0 +1,48 @@ +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +bool check(char *word, char *lookup, char *q) { + memset(lookup, -1, 26); + for (int i = 0; word[i] != '\0'; ++i) { + if (lookup[word[i] - 'a'] == -1) + lookup[word[i] - 'a'] = i; + if (q[i] != lookup[word[i] - 'a']) + return false; + } + return true; +} + +// note the returned array must be malloc'd (assume caller free()'s) + +char **findAndReplacePattern(char **words, int wordsSize, char *pattern, + int *returnSize) { + char lookup[26]; + memset(lookup, -1, 26); + char q[50] = {0}; + char **ans = malloc(sizeof(char **) * wordsSize); + size_t len = strlen(pattern); + for (int i = 0; i < len; ++i) { + if (lookup[pattern[i] - 'a'] == -1) + lookup[pattern[i] - 'a'] = i; + q[i] = lookup[pattern[i] - 'a']; + } + int sz = 0; + for (int i = 0; i < wordsSize; ++i) { + if (check(words[i], lookup, q)) { + char *k = malloc(sizeof(char) * (len + 1)); + memcpy(k, words[i], len + 1); + ans[sz++] = k; + } + } + *returnSize = sz; + return ans; +} + +int main() { + char *words1[] = {"abc", "deq", "mee", "aqq", "dkd", "ccc"}, + *words2[] = {"a", "b", "c"}; + char pattern1[] = {"abb"}, pattern2[] = {"a"}; +} diff --git a/find_replace_pattern.cpp b/find_replace_pattern.cpp new file mode 100644 index 0000000..a00bfcb --- /dev/null +++ b/find_replace_pattern.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class Solution { +public: + vector<string> findAndReplacePattern(vector<string> &words, string pattern) { + ans.resize(0); + codex.clear(); + cipher = pattern; + for (int i = 0; i < pattern.size(); i++) + cipher[i] = translate(cipher[i]); + for (auto &word : words) + compare(word); + return ans; + } + +private: + vector<string> ans; + unordered_map<char, char> codex; + string cipher; + char translate(char &c) { + if (codex.find(c) == codex.end()) + codex[c] = (char)(97 + codex.size()); + return codex[c]; + } + void compare(string &word) { + codex.clear(); + for (int i = 0; i < word.size(); i++) + if (translate(word[i]) != cipher[i]) + return; + ans.push_back(word); + } +}; diff --git a/find_safest_path_grid.cpp b/find_safest_path_grid.cpp new file mode 100644 index 0000000..226d3c9 --- /dev/null +++ b/find_safest_path_grid.cpp @@ -0,0 +1,89 @@ +// 2812. Find the Safest Path in a Grid +#include "leetcode.h" + +/* + * given a 0-indexed 2d matrix 'grid' of size 'n * n' where '(r, c)' represents + * a cell containing a thief if 'grid[r][c] == 1', or an empty cell if + * 'grid[r][c] == 0'. you are initially positioned at cell '(0, 0)'. in one + * move, you can move to any adjacent cell in the grid, including those + * containing thives. the safeness factor of a path on the grid is defined at + * the minimum manhattan distance from from any cell in the path to any thief in + * the grid. return the maximum safeness factor of all paths leading to cell '(n + * - 1, n - 1)'. + */ + +class Solution { +private: + int n, dir[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}}; + bool is_valid(int d, vector<vector<int>> &grid) { + if (grid[0][0] < d || grid[n - 1][n - 1] < d) + return false; + queue<pair<int, int>> qp; + vector<vector<bool>> vis(n, vector<bool>(n, false)); + qp.push({0, 0}); + vis[0][0] = true; + while (qp.empty()) { + auto [x, y] = qp.front(); + qp.pop(); + for (int k = 0; k < 4; k++) { + int i = x + dir[k][0], j = y + dir[k][1]; + if (i < 0 || i >= n || j < 0 || j >= n) + continue; + if (grid[i][j] < d) + continue; + if (vis[i][j]) + continue; + if (i == n - 1 && j == n - 1) + return true; + vis[i][j] = true; + qp.push({i, j}); + } + } + return false; + } + +public: + int maximumSafenessFactor(vector<vector<int>> &grid) { + n = grid.size(); + if (grid[0][0] || grid[n - 1][n - 1]) + return 0; + queue<pair<int, int>> qp; + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + if (grid[i][j]) + qp.push({i, j}); + while (!qp.empty()) { + int len = qp.size(); + for (int l = 0; l < len; l++) { + auto [x, y] = qp.front(); + qp.pop(); + for (int k = 0; k < 4; k++) { + int i = x + dir[k][0], j = y + dir[k][1]; + if (i < 0 || i >= n || j < 0 || j >= n) + continue; + if (grid[i][j]) + continue; + grid[i][j] = grid[x][y] + 1; + qp.push({i, j}); + } + } + } + int left = 0, right = 2 * n, mid; + while (left < right) { + mid = right - (right - left) / 2; + if (is_valid(mid, grid)) + left = mid; + else + right = mid - 1; + } + return left - 1; + } +}; + +int main() { + vvd(int) g1 = {{1, 0, 0}, {0, 0, 0}, {0, 0, 1}}, + g2 = {{0, 0, 1}, {0, 0, 0}, {0, 0, 0}}; + Solution obj; + printf("%d\n", obj.maximumSafenessFactor(g1)); // expect: 0 + printf("%d\n", obj.maximumSafenessFactor(g2)); // expect: 2 +} diff --git a/find_safest_path_grid.py b/find_safest_path_grid.py new file mode 100644 index 0000000..d615e43 --- /dev/null +++ b/find_safest_path_grid.py @@ -0,0 +1,64 @@ +# 2812. Find the Safest Path in a Grid +import heapq + +""" +given a 0-indexed 2d matrix 'grid' of size 'n n' where '(r, c)' represents +a cell containing a thief if 'grid[r][c] == 1', or an empty cell if +'grid[r][c] == 0'. you are initially positioned at cell '(0, 0)'. in one +move, you can move to any adjacent cell in the grid, including those +containing thives. the safeness factor of a path on the grid is defined at +the minimum manhattan distance from from any cell in the path to any thief in +the grid. return the maximum safeness factor of all paths leading to cell '(n +- 1, n - 1)'. +""" + + +class Solution(object): + def maximumSafenessFactor(self, grid): + """ + :type grid: List[List[int]] + :rtype: int + """ + a = [] + depth, m, n = 0, len(grid), len(grid[0]) + for i in range(m): + for j in range(n): + if grid[i][j] == 1: + a.append([i, j]) + vis = [[0 for j in range(n)] for i in range(m)] + dist = [[0 for j in range(n)] for i in range(m)] + while a: + b = [] + for i, j in a: + if not vis[i][j]: + vis[i][j] = 1 + dist[i][j] = depth + for x, y in [[i + 1, j], [i - 1, j], [i, j + 1], [i, j - 1]]: + if 0 <= x < m and 0 <= y < n: + b.append([x, y]) + a = b + depth += 1 + vis = [[0 for j in range(n)] for i in range(m)] + pq = [[-dist[0][0], 0, 0]] + while pq: + d, i, j = heapq.heappop(pq) + if vis[i][j]: + continue + vis[i][j] = 1 + if i == m - 1 and j == n - 1: + return -d + for x, y in [[i + 1, j], [i - 1, j], [i, j + 1], [i, j - 1]]: + if 0 <= x < m and 0 <= y < n: + heapq.heappush(pq, [-min(-d, dist[x][y]), x, y]) + return -1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.maximumSafenessFactor(grid=[[1, 0, 0], [0, 0, 0], [0, 0, 1]])) + print(obj.maximumSafenessFactor(grid=[[0, 0, 1], [0, 0, 0], [0, 0, 0]])) + print( + obj.maximumSafenessFactor( + grid=[[0, 0, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0], [1, 0, 0, 0]] + ) + ) diff --git a/find_score_arr_mark.c b/find_score_arr_mark.c new file mode 100644 index 0000000..fc2a402 --- /dev/null +++ b/find_score_arr_mark.c @@ -0,0 +1,57 @@ +// 2593. Find Score of an Array After Marking All Elements +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array 'nums' consisting of positive integers. starting with 'score = + * 0', apply the following algorithm + * - choose the smallest integer of the array that is not marked. if there is a + * tie, choose the one with the smallest index + * - add the value of the chosen integer to 'score' + * - mark the chosen element and its two adjacent elements if they exist + * - repeat until all the array elements are marked + * return the score you get after applying the above algorithm + */ + +struct pair { + int val; + int idx; +}; + +int cmp(const void *a, const void *b) { + const struct pair p_a = *(const struct pair *)a; + const struct pair p_b = *(const struct pair *)b; + if (p_a.val == p_b.val) + return p_a.idx - p_b.idx; + return p_a.val - p_b.val; +} + +long long findScore(int *nums, int nums_size) { + if (nums_size == 1) + return (long long)nums[0]; + struct pair *arr = (struct pair *)calloc(nums_size, sizeof(struct pair)); + bool *is_marked = (bool *)calloc(nums_size, sizeof(bool)); + for (int i = 0; i < nums_size; i++) { + arr[i].val = nums[i]; + arr[i].idx = i; + } + qsort(arr, nums_size, sizeof(struct pair), cmp); + long long ans = 0; + for (int i = 0; i < nums_size; i++) + if (!is_marked[arr[i].idx]) { + ans += arr[i].val; + if (arr[i].idx + 1 < nums_size) + is_marked[arr[i].idx + 1] = true; + if (arr[i].idx - 1 >= 0) + is_marked[arr[i].idx - 1] = true; + } + free(arr), free(is_marked); + return ans; +} + +int main() { + int n1[] = {2, 1, 3, 4, 5, 2}, n2[] = {2, 3, 5, 1, 3, 2}; + printf("%lld\n", findScore(n1, 6)); // expect: 7 + printf("%lld\n", findScore(n2, 6)); // expect: 5 +} diff --git a/find_score_arr_mark.cpp b/find_score_arr_mark.cpp new file mode 100644 index 0000000..42f2e6a --- /dev/null +++ b/find_score_arr_mark.cpp @@ -0,0 +1,40 @@ +// 2593. Find Score of an Array After Marking All Elements +#include "leetcode.h" + +/* + * given an array 'nums' consisting of positive integers. starting with 'score = + * 0', apply the following algorithm + * - choose the smallest integer of the array that is not marked. if there is a + * tie, choose the one with the smallest index + * - add the value of the chosen integer to 'score' + * - mark the chosen element and its two adjacent elements if they exist + * - repeat until all the array elements are marked + * return the score you get after applying the above algorithm + */ + +class Solution { +public: + long long findScore(vector<int> &nums) { + long long ans = 0; + set<pair<int, int>> s; + for (int i = 0; i < nums.size(); ++i) + s.insert({nums[i], i}); + for (auto i : s) + if (nums[i.second]) { + nums[i.second] = 0; + if (i.second - 1 >= 0) + nums[i.second - 1] = 0; + if (i.second + 1 < nums.size()) + nums[i.second + 1] = 0; + ans += i.first; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {2, 1, 3, 4, 5, 2}, n2 = {2, 3, 5, 1, 3, 2}; + printf("%lld\n", obj.findScore(n1)); // expect: 7 + printf("%lld\n", obj.findScore(n2)); // expect: 5 +} diff --git a/find_smallest_letter.c b/find_smallest_letter.c new file mode 100644 index 0000000..c79deca --- /dev/null +++ b/find_smallest_letter.c @@ -0,0 +1,36 @@ +// 744. Find Smallest Letter Greater Than Target +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* given an array of characters 'letters' that is sorted in non-decreasing + * order, and a character 'target'. there are at least two different characters + * in 'letters'. return the smallest character in 'letters' that is + * lexicographically greater than 'target'. if such a character does not exist, + * return the first character in 'letters'. + */ + +char nextGreatestLetter(char *letters, int letters_size, char target) { + int start = 0, end = letters_size - 1, mid; + while (start < end) { + mid = start + (end - start) / 2; + if (letters[mid] - target < 0) + start = mid + 1; + else if (letters[mid] - target > 0) + end = mid; + else + break; + } + while (mid < letters_size - 1 && letters[mid] <= target) + mid++; + char ans = letters[mid]; + return letters[mid] <= target && mid == letters_size - 1 ? letters[0] : ans; +} + +int main() { + char l1_2[] = {'c', 'f', 'j'}; + char l3[] = {'x', 'x', 'y', 'y'}; + printf("%c\n", nextGreatestLetter(l1_2, 3, 'a')); // expect: c + printf("%c\n", nextGreatestLetter(l1_2, 3, 'c')); // expect: f + printf("%c\n", nextGreatestLetter(l1_2, 4, 'z')); // expect: x +} diff --git a/find_smallest_letter.cpp b/find_smallest_letter.cpp new file mode 100644 index 0000000..01a5562 --- /dev/null +++ b/find_smallest_letter.cpp @@ -0,0 +1,34 @@ +// 744. Find Smallest Letter Greater Than Target +#include "leetcode.h" + +/* + * given an array of characters 'letters' that is sorted in non-decreasing + * order, and a character 'target'. there are at least two different characters + * in 'letters'. return the smallest character in 'letters' that is + * lexicographically greater than 'target'. if such a character does not exist, + * return the first character in 'letters'. + */ + +class Solution { +public: + char nextGreatestLetter(vector<char> &letters, char target) { + int low = 0, high = letters.size() - 1; + while (low < high) { + int mid = low + (high - low) / 2; + if (letters[mid] <= target) + low = mid + 1; + else + high = mid; + } + return letters[low] > target ? letters[low] : letters[0]; + } +}; + +int main() { + Solution obj; + vector<char> l1_2 = {'c', 'f', 'j'}; + vector<char> l3 = {'x', 'x', 'y', 'y'}; + printf("%c", obj.nextGreatestLetter(l1_2, 'a')); // expect: c + printf("%c", obj.nextGreatestLetter(l1_2, 'c')); // expect: f + printf("%c", obj.nextGreatestLetter(l3, 'z')); // expect: x +} diff --git a/find_town_judge.c b/find_town_judge.c new file mode 100644 index 0000000..2b22ce9 --- /dev/null +++ b/find_town_judge.c @@ -0,0 +1,48 @@ +// 997. Find the Town Judge +#include "leetcode.h" + +/* + * in a town, there are 'n' people labeled from 1 to 'n'. there is a rumor that + * one of these people is secretly the town judge. if the town judge exists, + * then: the town judge trusts nobody. everybody (except the judge) trusts the + * judge. given: array 'trust' where 'trust[i]' = [ai, bi] representing the the + * person labeled ai trusts the person labeled bi. return label of judge, if + * they exist. + */ + +int findJudge(int n, int **trust, int trustSize, int *trustColSize) { + int candidate = -1; + bool arr[n + 1]; + for (int i = 0; i <= n; i++) + arr[i] = false; + for (int i = 0; i < trustSize; i++) + arr[trust[i][0]] = true; + for (int i = 1; i <= n; i++) + if (!arr[i]) { + candidate = i; + break; + } + if (candidate == -1) + return -1; + for (int i = 1; i <= n; i++) + arr[i] = false; + for (int i = 0; i < trustSize; i++) + if (trust[i][1] == candidate) + arr[trust[i][0]] = true; + bool ans = true; + for (int i = 1; i <= n; i++) { + if (i == candidate) + continue; + ans &= arr[i]; + } + return ans ? candidate : -1; +} + +int main() { + int trust1[][2] = {{1, 2}}, trustColSize1[] = {1}; + int trust2[][2] = {{1, 3}, {2, 3}}, trustColSize2[] = {2}; + int trust3[][2] = {{1, 3}, {2, 3}, {3, 1}}, trustColSize3[] = {3}; + printf("%d\n", findJudge(2, trust1, 1, trustColSize1)); // expect: 2 + printf("%d\n", findJudge(3, trust2, 2, trustColSize1)); // expect: 3 + printf("%d\n", findJudge(3, trust3, 3, trustColSize1)); // expect: -1 +} diff --git a/find_town_judge.cpp b/find_town_judge.cpp new file mode 100644 index 0000000..70cefdf --- /dev/null +++ b/find_town_judge.cpp @@ -0,0 +1,46 @@ +// 997. Find the Town Judge +#include "leetcode.h" + +/* + * in a town, there are 'n' people labeled from 1 to 'n'. there is a rumor that + * one of these people is secretly the town judge. if the town judge exists, + * then: the town judge trusts nobody. everybody (except the judge) trusts the + * judge. given: array 'trust' where 'trust[i]' = [ai, bi] representing the the + * person labeled ai trusts the person labeled bi. return label of judge, if + * they exist. + */ + +class Solution { +public: + int findJudge(int n, vvd(int) trust) { + vector<unordered_set<int>> graph(n + 1, unordered_set<int>()); + for (auto &edge : trust) { + int a = edge[0], b = edge[1]; + graph[a].insert(b); // a trusts b + } + int townJudge = -1; + for (int i = 1; i <= n; ++i) + if (graph[i].size() == 0) { + townJudge = i; + break; + } + if (townJudge == -1) + return -1; + for (int i = 1; i <= n; ++i) { + if (i == townJudge) + continue; + if (!graph[i].count(townJudge)) + return -1; + } + return townJudge; + } +}; + +int main() { + Solution obj; + vvd(int) trust1 = {{1, 2}}, trust2 = {{1, 3}, {2, 3}}, + trust3 = {{1, 3}, {2, 3}, {3, 1}}; + cout << obj.findJudge(2, trust1) << endl; // expect: 2 + cout << obj.findJudge(3, trust2) << endl; // expect: 3 + cout << obj.findJudge(3, trust3) << endl; // expect: -1 +} diff --git a/find_town_judge.py b/find_town_judge.py new file mode 100644 index 0000000..7a65fd7 --- /dev/null +++ b/find_town_judge.py @@ -0,0 +1,33 @@ +# 997. Find the Town Judge + +""" +in a town, there are 'n' people labeled from 1 to 'n'. there is a rumor that +one of these people is secretly the town judge. if the town judge exists, then: +the town judge trusts nobody. everybody (except the judge) trusts the judge. +given: array 'trust' where 'trust[i]' = [ai, bi] representing the the person +labeled ai trusts the person labeled bi. return label of judge, if they exist. +""" + + +class Solution(object): + def findJudge(self, n, trust): + """ + :type n: int + :type trust: List[List[int]] + :rtype: int + """ + cnt = [0] * (n + 1) + for i, j in trust: + cnt[i] -= 1 + cnt[j] += 1 + for i in range(1, n + 1): + if cnt[i] == n - 1: + return i + return -1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.findJudge(n=2, trust=[[1, 2]])) + print(obj.findJudge(n=3, trust=[[1, 3], [2, 3]])) + print(obj.findJudge(n=3, trust=[[1, 3], [2, 3], [3, 1]])) diff --git a/find_unique_binary_str.c b/find_unique_binary_str.c new file mode 100644 index 0000000..e7e0541 --- /dev/null +++ b/find_unique_binary_str.c @@ -0,0 +1,31 @@ +// 1980. Find Unique Binary String +#include "leetcode.h" + +/* + * given an array of strings 'nums' containing 'n' unique binary strings each of + * length 'n', return a binary string of length 'n' that does not appear in + * 'nums'. if there are multiple answers, you may return any of them. + */ + +// char *findDifferentBinaryString(char **nums, int nums_size) { +char *findDifferentBinaryString(int nums_size, + char nums[nums_size][nums_size]) { + char *ans = malloc(nums_size + 1); + int j = 0; + for (int i = 0; i < nums_size; i++) { + if (nums[i][i] == '0') + ans[j++] = '1'; + else + ans[j++] = '0'; + } + ans[j] = '\0'; + return j ? ans : ""; +} + +int main() { + char n1[2][2] = {{"01"}, {"10"}}, n2[2][2] = {{"00"}, {"01"}}, + n3[3][3] = {{"111"}, {"011"}, {"001"}}; + printf("%s\n", findDifferentBinaryString(2, n1)); // expect: 11 + printf("%s\n", findDifferentBinaryString(2, n2)); // expect: 11 + printf("%s\n", findDifferentBinaryString(3, n3)); // expect: 101 +} diff --git a/find_unique_binary_str.py b/find_unique_binary_str.py new file mode 100644 index 0000000..6866870 --- /dev/null +++ b/find_unique_binary_str.py @@ -0,0 +1,29 @@ +# 1980. Find Unique Binary String + +""" +given an array of strings 'nums' containing 'n' unique binary strings each of +length 'n', return a binary string of length 'n' that does not appear in +'nums'. if there are multiple answers, you may return any of them. +""" + + +class Solution(object): + def findDifferentBinaryString(self, nums): + """ + :type nums: List[str] + :rtype: str + """ + s = set([int(i, 2) for i in nums]) + max_len = len(nums[0]) + for i in range(pow(2, max_len)): + if i not in s: + r = bin(i)[2:] + return "0" * (max_len - len(r)) + r + return "-1" + + +if __name__ == "__main__": + obj = Solution() + print(obj.findDifferentBinaryString(["01", "10"])) # expect: 11 + print(obj.findDifferentBinaryString(["00", "01"])) # expect: 11 + print(obj.findDifferentBinaryString(["111", "011", "001"])) # expect: 101 diff --git a/find_winner_arr_game.c b/find_winner_arr_game.c new file mode 100644 index 0000000..e29004d --- /dev/null +++ b/find_winner_arr_game.c @@ -0,0 +1,33 @@ +// 1535. Find the Winner of an Array Game +#include "leetcode.h" + +/* + * given an integer array 'arr' of distinct integers and an integer 'k', a game + * will be played between the first two elements of the array (ie. 'arr[0]' and + * 'arr[1]'). in eah round of the game, we compare 'arr[0]' with 'arr[1]', the + * larger integer wins and remains at position 0, and the smaller integer moves + * to the end of the array. the game ends when an integer wins 'k' consecutive + * rounds. return the integer which will win the game. it is guaranteed that + * there will be a winner of the game. + */ + +int getWinner(int *arr, int arr_size, int k) { + int max = arr[0], cnt = 0; + for (int i = 1; i < arr_size; i++) { + if (arr[i] < max) + cnt++; + else { + cnt = 1; + max = arr[i]; + } + if (cnt == k) + return max; + } + return max; +} + +int main() { + int a1[] = {2, 1, 3, 5, 4, 6, 7}, a2[] = {3, 2, 1}; + printf("%d\n", getWinner(a1, ARRAY_SIZE(a1), 2)); // expect: 5 + printf("%d\n", getWinner(a2, ARRAY_SIZE(a2), 10)); // expect: 3 +} diff --git a/find_winner_arr_game.py b/find_winner_arr_game.py new file mode 100644 index 0000000..33ffa39 --- /dev/null +++ b/find_winner_arr_game.py @@ -0,0 +1,31 @@ +# 1535. Find the Winner of an Array Game + +""" +given an integer array 'arr' of distinct integers and an integer 'k', a game +will be played between the first two elements of the array (ie. 'arr[0]' and +'arr[1]'). in eah round of the game, we compare 'arr[0]' with 'arr[1]', the +larger integer wins and remains at position 0, and the smaller integer moves +to the end of the array. the game ends when an integer wins 'k' consecutive +rounds. return the integer which will win the game. it is guaranteed that +there will be a winner of the game. +""" + + +class Solution(object): + def getWinner(self, arr, k): + curr = arr[0] + win = 0 + for i in range(1, len(arr)): + if arr[i] > curr: + curr = arr[i] + win = 0 + win += 1 + if win == k: + break + return curr + + +if __name__ == "__main__": + obj = Solution() + print(obj.getWinner([2, 1, 3, 5, 4, 6, 7], 2)) # expect: 5 + print(obj.getWinner([3, 2, 1], 2)) # expect: 3 diff --git a/first_last_sorted_array.cpp b/first_last_sorted_array.cpp new file mode 100644 index 0000000..3f4168a --- /dev/null +++ b/first_last_sorted_array.cpp @@ -0,0 +1,47 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> searchRange(vector<int> &nums, int target) { + int s = 0, e = nums.size() - 1; + vector<int> ans(2, -1); + // first position + while (s <= e) { + int m = s + (e - s) / 2; + if (nums[m] < target) + s = m + 1; + else if (nums[m] > target) + e = m - 1; + else { + if (m == s || nums[m] != nums[m - 1]) { + ans[0] = m; + break; + } else { + e = m - 1; + ans[0] = m - 1; + } + } + } + // second position + s = 0, e = nums.size() - 1; + while (s <= e) { + int m = s + (e - s) / 2; + if (nums[m] < target) + s = m + 1; + else if (nums[m] > target) + e = m - 1; + else { + if (m == e || nums[m] != nums[m + 1]) { + ans[1] = m; + break; + } else { + s = m + 1; + ans[1] = m + 1; + } + } + } + return ans; + } +}; + +int main() {} diff --git a/first_missing_pos.cpp b/first_missing_pos.cpp new file mode 100644 index 0000000..5955ded --- /dev/null +++ b/first_missing_pos.cpp @@ -0,0 +1,17 @@ +#include "leetcode.h" + +class Solution { +public: + int firstMissingPositive(vector<int> &nums) { + int n = nums.size(); + for (int i = 0; i < n; i++) + while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) + swap(nums[i], nums[nums[i] - 1]); + for (int i = 0; i < n; i++) + if (nums[i] != i + 1) + return i + 1; + return n + 1; + } +}; + +int main() {} diff --git a/first_missing_positive.c b/first_missing_positive.c new file mode 100644 index 0000000..638c0b3 --- /dev/null +++ b/first_missing_positive.c @@ -0,0 +1,40 @@ +// 41. First Missing Positive +#include "leetcode.h" + +/* + * given an unsorted integer array 'nums', return the smallest missing positive + * number. you must implement an algorithm that runs in O(n) time and uses O(1) + * auxiliary space. + */ + +int firstMissingPositive(int *nums, int nums_size) { + int x = 0; + for (int i = 0; i < nums_size; i++) + if (nums[i] == 1) { + x = 1; + break; + } + if (!x) + return 1; + if (nums_size == 1) + return 2; + for (int i = 0; i < nums_size; i++) + if (nums[i] <= 0 || nums[i] > nums_size) + nums[i] = 1; + for (int i = 0; i < nums_size; ++i) { + int y = abs(nums[i]); + if (nums[y - 1]) + nums[y - 1] *= -1; + } + for (int i = 0; i < nums_size; ++i) + if (nums[i]) + return i + 1; + return nums_size + 1; +} + +int main() { + int n1[] = {1, 2, 0}, n2[] = {3, 4, -1, 1}, n3[] = {7, 8, 9, 11, 12}; + printf("%d\n", firstMissingPositive(n1, 3)); // expect: 3 + printf("%d\n", firstMissingPositive(n2, 4)); // expect: 2 + printf("%d\n", firstMissingPositive(n3, 5)); // expect: 1 +} diff --git a/first_missing_positive.cpp b/first_missing_positive.cpp new file mode 100644 index 0000000..48fc05d --- /dev/null +++ b/first_missing_positive.cpp @@ -0,0 +1,12 @@ +#include "leetcode.h" +#include <vector> + +class Solution { +public: + vector<int> firstMissingPositive(vector<int> &nums) {} +}; + +int main() { + Solution obj; + vector<int> nums1 = {1, 2, 0}, nums2 = {} +} diff --git a/first_missing_positive.py b/first_missing_positive.py new file mode 100644 index 0000000..8166acf --- /dev/null +++ b/first_missing_positive.py @@ -0,0 +1,33 @@ +# 41. First Missing Positive + +""" +given an unsorted integer array 'nums', return the smallest missing positive +number. you must implement an algorithm that runs in O(n) time and uses O(1) +auxiliary space. +""" + + +class Solution(object): + def firstMissingPositive(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + nums.append(0) + n = len(nums) + for i in range(len(nums)): + if nums[i] < 0 or nums[i] >= n: + nums[i] = 0 + for i in range(len(nums)): + nums[nums[i] % n] += n + for i in range(1, len(nums)): + if nums[i] / n == 0: + return i + return n + + +if __name__ == "__main__": + obj = Solution() + print(obj.firstMissingPositive([1, 2, 0])) + print(obj.firstMissingPositive([3, 4, -1, 1])) + print(obj.firstMissingPositive([7, 8, 9, 11, 12])) diff --git a/first_missing_positive.rs b/first_missing_positive.rs new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/first_missing_positive.rs diff --git a/first_unique_char_string.c b/first_unique_char_string.c new file mode 100644 index 0000000..27ae3a7 --- /dev/null +++ b/first_unique_char_string.c @@ -0,0 +1,29 @@ +// 387. First Unique Character in a String +#include "leetcode.h" + +/* + * given a string 's', find the first non-repeating character in it and return + * its index. if it does not exist, return -1 + */ + +int firstUniqChar(char *s) { + int cnt[26], n = strlen(s); + memset(cnt, 0, sizeof(int) * 26); + for (int i = 0; i < n; i++) { + char c = s[i]; + cnt[c - 'a'] += 1; + } + for (int i = 0; i < n; i++) { + char c = s[i]; + if (cnt[c - 'a'] == 1) + return i; + } + return -1; +} + +int main() { + char *s1 = "leetcode", *s2 = "loveleetcode", *s3 = "aabb"; + printf("%d\n", firstUniqChar(s1)); // expect: 0 + printf("%d\n", firstUniqChar(s2)); // expect: 2 + printf("%d\n", firstUniqChar(s3)); // expect: -1 +} diff --git a/first_unique_char_string.cpp b/first_unique_char_string.cpp new file mode 100644 index 0000000..5f55821 --- /dev/null +++ b/first_unique_char_string.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + int firstUniqChar(string s) { + unordered_map<char, pair<int, int>> ump; + int idx = s.size(); + for (int i = 0; i < s.size(); i++) { + ump[s[i]].first++; + ump[s[i]].second = i; + } + for (const auto &[c, p] : ump) + if (p.first == 1) + idx = min(idx, p.second); + return idx == s.size() ? -1 : idx; + } +}; + +int main() { + Solution obj; + cout << obj.firstUniqueChar("loveleetcode"); +} diff --git a/first_unique_char_string.py b/first_unique_char_string.py new file mode 100644 index 0000000..6909b5a --- /dev/null +++ b/first_unique_char_string.py @@ -0,0 +1,28 @@ +# 387. First Unique Character in a String + +""" +given a string 's', find the first non-repeating character in it and return +its index. if it does not exist, return -1 +""" + + +class Solution(object): + def firstUniqChar(self, s): + """ + :type s: str + :rtype: int + """ + m = {} + for c in s: + m[c] = m.get(c, 0) + 1 + for i in range(len(s)): + if m[s[i]] == 1: + return i + return -1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.firstUniqChar("leetcode")) + print(obj.firstUniqChar("loveleetcode")) + print(obj.firstUniqChar("aabb")) diff --git a/flatten_binary_to_linked.cpp b/flatten_binary_to_linked.cpp new file mode 100644 index 0000000..82751c7 --- /dev/null +++ b/flatten_binary_to_linked.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + void flatten(TreeNode *root) { + if (root) + helper(root); + } + +private: + TreeNode *head = nullptr; + void helper(TreeNode *node) { + if (node->right) + helper(node->right); + if (node->left) + helper(node->left); + node->left = nullptr; + node->right = head; + head = node; + } +}; diff --git a/flatten_nested_iterator.c b/flatten_nested_iterator.c new file mode 100644 index 0000000..57103a7 --- /dev/null +++ b/flatten_nested_iterator.c @@ -0,0 +1,81 @@ +// 341. Flatten Nested List Iterator +#include <stdbool.h> +#include <stdlib.h> + +/** + * ********************************************************************* + * // This is the interface that allows for creating nested lists. + * // You should not implement it, or speculate about its implementation + * ********************************************************************* + * + * // Return true if this NestedInteger holds a single integer, rather than a + * nested list. bool NestedIntegerIsInteger(struct NestedInteger *); + * + * // Return the single integer that this NestedInteger holds, if it holds a + * single integer + * // The result is undefined if this NestedInteger holds a nested list + * int NestedIntegerGetInteger(struct NestedInteger *); + * + * // Return the nested list that this NestedInteger holds, if it holds a nested + * list + * // The result is undefined if this NestedInteger holds a single integer + * struct NestedInteger **NestedIntegerGetList(struct NestedInteger *); + * + * // Return the nested list's size that this NestedInteger holds, if it holds a + * nested list + * // The result is undefined if this NestedInteger holds a single integer + * int NestedIntegerGetListSize(struct NestedInteger *); + * }; + */ + +bool NestedIntegerIsInteger(struct NestedInteger *); +int NestedIntegerGetInteger(struct NestedInteger *); +struct NestedInteger **NestedIntegerGetList(struct NestedInteger *); +int NestedIntegerGetListSize(struct NestedInteger *); + +struct NestedIterator { + int *list; + int cur; + int n; +}; + +void process(int *list, int *idx, struct NestedInteger *nestedList) { + if (NestedIntegerIsInteger(nestedList)) { + list[*idx] = NestedIntegerGetInteger(nestedList); + *idx = *idx + 1; + return; + } + struct NestedInteger **newNestedList = NestedIntegerGetList(nestedList); + int newnestedListSize = NestedIntegerGetListSize(nestedList); + for (int i = 0; i < newnestedListSize; i++) { + process(list, idx, newNestedList[i]); + } +} + +struct NestedIterator *nestedIterCreate(struct NestedInteger **nestedList, + int nestedListSize) { + struct NestedIterator *ret = + (struct NestedIterator *)malloc(sizeof(struct NestedIterator)); + ret->list = malloc(50000 * sizeof(int)); + int id = 0; + for (int i = 0; i < nestedListSize; i++) { + process(ret->list, &id, nestedList[i]); + } + ret->list = realloc(ret->list, id * sizeof(int)); + ret->cur = 0; + ret->n = id; + return ret; +} + +bool nestedIterHasNext(struct NestedIterator *iter) { + return ((iter->cur) < (iter->n)); +} + +int nestedIterNext(struct NestedIterator *iter) { + return (iter->list[iter->cur++]); +} + +void nestedIterFree(struct NestedIterator *iter) { + free(iter->list); + free(iter); +} diff --git a/flatten_nested_iterator.cpp b/flatten_nested_iterator.cpp new file mode 100644 index 0000000..4a6f93c --- /dev/null +++ b/flatten_nested_iterator.cpp @@ -0,0 +1,33 @@ +#include "leetcode.h" + +class NestedIterator { +public: + NestedIterator(vector<NestedInteger> &nestedList) { + int n = nestedList.size(); + for (int i = n - 1; i >= 0; --i) + nodes.push(nestedList[i]); + } + int next() { + int ans = nodes.top().getInteger(); + nodes.pop(); + return ans; + } + bool hasNext() { + while (!nodes.empty()) { + NestedInteger curr = nodes.top(); + if (curr.isInteger()) + return true; + nodes.pop(); + vector<NestedInteger> &adj = curr.getList(); + int n = adj.size(); + for (int i = n - 1; i >= 0; --i) + nodes.push(adj[i]); + } + return false; + } + +private: + stack<NestedInteger> nodes; +}; + +int main() {} diff --git a/flatten_nested_iterator.py b/flatten_nested_iterator.py new file mode 100644 index 0000000..1c9042c --- /dev/null +++ b/flatten_nested_iterator.py @@ -0,0 +1,54 @@ +# """ +# This is the interface that allows for creating nested lists. +# You should not implement it, or speculate about its implementation +# """ +# class NestedInteger(object): +# def isInteger(self): +# """ +# @return True if this NestedInteger holds a single integer, rather than a nested list. +# :rtype bool +# """ +# +# def getInteger(self): +# """ +# @return the single integer that this NestedInteger holds, if it holds a single integer +# Return None if this NestedInteger holds a nested list +# :rtype int +# """ +# +# def getList(self): +# """ +# @return the nested list that this NestedInteger holds, if it holds a nested list +# Return None if this NestedInteger holds a single integer +# :rtype List[NestedInteger] +# """ + + +class NestedIterator(object): + def __init__(self, nestedList): + self.stack = [[nestedList, 0]] + + def next(self): + self.hasNext() + nestedList, i = self.stack[-1] + self.stack[-1][1] += 1 + return nestedList[i].getInteger() + + def hasNext(self): + s = self.stack + while s: + nestedList, i = s[-1] + if i == len(nestedList): + s.pop() + else: + x = nestedList[i] + if x.isInteger(): + return True + s[-1][1] += 1 + s.append([x.getList(), 0]) + return False + + +# Your NestedIterator object will be instantiated and called as such: +# i, v = NestedIterator(nestedList), [] +# while i.hasNext(): v.append(i.next()) diff --git a/flip_string_monotone_increase.c b/flip_string_monotone_increase.c new file mode 100644 index 0000000..6b2c9ee --- /dev/null +++ b/flip_string_monotone_increase.c @@ -0,0 +1,23 @@ +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int minFlipsMonoIncr(char *s) { + int n = strlen(s), *dp = malloc((n + 1) * sizeof(int)); + dp[0] = 0; + for (int i = 0; i < n; i++) + dp[i + 1] = dp[i] + (s[i] == '1'); + int min = INT_MAX; + for (int i = 1; i <= n + 1; i++) + min = fmin(min, 2 * dp[i - 1] + n - i + 1 - dp[n]); + return min; +} + +int main() { + char s1[] = {"00110"}, s2[] = {"010110"}, s3[] = {"00011000"}; + printf("%c\n", minFlipsMonoIncr(s1)); + printf("%c\n", minFlipsMonoIncr(s2)); + printf("%c\n", minFlipsMonoIncr(s3)); +} diff --git a/flip_string_monotone_increase.cpp b/flip_string_monotone_increase.cpp new file mode 100644 index 0000000..35e0e0c --- /dev/null +++ b/flip_string_monotone_increase.cpp @@ -0,0 +1,36 @@ +#include "leetcode.h" + +/* + * a binary string is monotone increasing if it consists of some number + * of 0's (none is valid), followed by some number of 1's (none is valid) + * given: binary string 's'. you can flip 's[i]' changing for 0 to 1 or vice + * versa. return the minimum number of flips to make 's' monotone increasing. + */ + +class Solution { +public: + int minFlipsMonoIncr(string s) { + int flips = 0, cnt = 0; + for (auto i : s) { + if (i == '1') + cnt++; + else + flips++; + flips = min(flips, cnt); + } + return flips; + } +}; + +int main() { + Solution obj; + cout << obj.minFlipsMonoIncr("00110") << endl; + // expect: 1 + // flip last digit to get 00111 + cout << obj.minFlipsMonoIncr("010110") << endl; + // expect: 2 + // flip s[1] s[5] to get 000111 + cout << obj.minFlipsMonoIncr("00011000") << endl; + // expect: 2 + // flip s[3] s[4] to get 00000000 +} diff --git a/freedom_trail.cpp b/freedom_trail.cpp new file mode 100644 index 0000000..2763f8c --- /dev/null +++ b/freedom_trail.cpp @@ -0,0 +1,55 @@ +// 514. Freedom Trail +#include "leetcode.h" + +/* + * in the video game fallout 4, the quest "road to freeom" requires players to + * reach a metal dial call the "freedom trail ring" and use the dial to spell a + * specific keyword to open the door. given a string 'rint' that represents the + * code engraved on the outer ring and another string 'key' that represents the + * keyword that needs to be spelled, return the minimum number of steps to spell + * all of the characters in the keyword. initially, the first character of the + * ring is aligned at "12:00" diretion. you should spell all the characters in + * 'key' one by rotating 'ring' clockwise or anticlockwise to make each + * character of the string aligned at the "12:00" direction and then by pressing + * the center button. at the stage of rotating the ring to spell the key + * character 'key[i]' you can rotate the ring clockwise or anticlockwise by one + * place, which counts as one step. the final purpose of the rotation is to + * align one of 'ring's characters at "12:00" direction, where this character + * must equal 'key[i]' + */ + +class Solution { +public: + int findRotateSteps(string ring, string key) { + int n = ring.size(); + unordered_map<char, vector<int>> idx_map; + for (int i = 0; i < n; ++i) + idx_map[ring[i]].push_back(i); + vector<vector<pair<int, int>>> dp(key.size()); + for (int i : idx_map[key[0]]) { + int dist = min(i, n - i); + dp[0].push_back({i, dist}); + } + int min_sum = INT_MAX; + for (int i = 1; i < key.size(); ++i) { + for (int idx : idx_map[key[i]]) { + int min_dist = INT_MAX; + for (auto &pair : dp[i - 1]) { + int abs_dist = abs(pair.first - idx); + int dist = min(abs_dist, n - abs_dist); + min_dist = min(min_dist, dist + pair.second); + } + dp[i].push_back({idx, min_dist}); + if (i == key.size() - 1) + min_sum = min(min_dist, min_sum); + } + } + return min_sum + key.size(); + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.findRotateSteps("godding", "gd")); // expect: 4 + printf("%d\n", obj.findRotateSteps("godding", "godding")); // expect: 13 +} diff --git a/freedom_trail.py b/freedom_trail.py new file mode 100644 index 0000000..d923805 --- /dev/null +++ b/freedom_trail.py @@ -0,0 +1,55 @@ +# 514. Freedom Trail +from collections import defaultdict + +""" +in the video game fallout 4, the quest road to freedom requires players to +reach a metal dial called the freedom trail ring and use the dial to spell a +specific keyword to open the door. given a string 'ring' that represents the +code engraved on the outer ring and anotherstring 'key' that represents the +keyword that needs to be spelled, return the minimum number of steps to spell +all the characters in keyword. initially, the first character of the ring is +aligned at the "12:00" direction. you should spell all the characters in +'key' one by one by rotating 'ring' clockwise or counterclockwise to make +each character of the string 'key' aligned at the "12:00" direction and then +by pressing the centre button. +""" + + +class Solution(object): + def findRotateSteps(self, ring, key): + """ + :type ring: str + :type key: str + :rtype: int + """ + idx, n, dp, pre = ( + defaultdict(list), + len(ring), + [0] * len(ring), + key[0], + ) + for i, c in enumerate(ring): + idx[c].append(i) + for i in idx[key[0]]: + dp[i] = min(i, n - i) + 1 + for c in key[1:]: + for i in idx[c]: + dp[i] = ( + min( + ( + dp[j] + min(i - j, j + n - i) + if i >= j + else dp[j] + min(j - i, i + n - j) + ) + for j in idx[pre] + ) + + 1 + ) + pre = c + return min(dp[i] for i in idx[key[-1]]) + + +if __name__ == "__main__": + obj = Solution() + print(obj.findRotateSteps("godding", "gd")) + print(obj.findRotateSteps("godding", "godding")) diff --git a/freq_most_freq_element.c b/freq_most_freq_element.c new file mode 100644 index 0000000..e78d403 --- /dev/null +++ b/freq_most_freq_element.c @@ -0,0 +1,38 @@ +// 1838. Frequency of the Most Frequent Element +#include "leetcode.h" + +/* + * the frequency of an element is the number of times it occurs in an array. you + * are given an integer array 'nums' and an integer 'k'. in one operation, you + * can shoose an index of 'nums' and increment the element at the index by 1. + * return the maximum possible frequency of an element after performing at most + * 'k' operations + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int maxFrequency(int *nums, int nums_size, int k) { + int left = 0, right = 0; + qsort(nums, nums_size, sizeof(int), cmp); + long long *dp = malloc((nums_size + 1) * sizeof(long long)); + dp[0] = 0; + for (int i = 1; i < nums_size; i++) + dp[i] = nums[i - 1] + dp[i - 1]; + long long opt = 0; + while (right < nums_size - 1) { + right++; + opt = (long long)nums[right] * (right - left + 1) - + (dp[right + 1] - dp[left]); + if (opt > k) + left++; + } + free(dp); + return right - left + 1; +} + +int main() { + int n1[] = {1, 2, 4}, n2[] = {1, 4, 8, 13}, n3[] = {3, 9, 6}; + printf("%d\n", maxFrequency(n1, ARRAY_SIZE(n1), 5)); // expect: 3 + printf("%d\n", maxFrequency(n2, ARRAY_SIZE(n2), 5)); // expect: 2 + printf("%d\n", maxFrequency(n3, ARRAY_SIZE(n3), 2)); // expect: 1 +} diff --git a/freq_most_freq_element.py b/freq_most_freq_element.py new file mode 100644 index 0000000..d071a11 --- /dev/null +++ b/freq_most_freq_element.py @@ -0,0 +1,33 @@ +# 1838. Frequency of the Most Frequent Element + +""" +the frequency of an element is the number of times it occurs in an array. you +are given an integer array 'nums' and an integer 'k'. in one operation, you +can shoose an index of 'nums' and increment the element at the index by 1. +return the maximum possible frequency of an element after performing at most +'k' operations +""" + + +class Solution(object): + def maxFrequency(self, nums, k): + """ + :type nums: List[int] + :type k: int + :rtype: int + """ + i = 0 + nums.sort() + for j in range(len(nums)): + k += nums[j] + if k < nums[j] * (j - i + 1): + k -= nums[i] + i += 1 + return j - i + 1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxFrequency([1, 2, 4], 5)) + print(obj.maxFrequency([1, 4, 8, 13], 5)) + print(obj.maxFrequency([3, 9, 6], 2)) diff --git a/frog_jump.c b/frog_jump.c new file mode 100644 index 0000000..645a1d1 --- /dev/null +++ b/frog_jump.c @@ -0,0 +1,78 @@ +// 403. Frog Jump +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * a frog is crossing a river. the river is divided into some number of units + * and at each unit, there may or may not exist a stone. the frog can jump on a + * stone, but it must not jump into the water. given a list of 'stones' + * positions in (units) in sorted ascending order, determine if the frog can + * cross the river by landing on the last stone. initially, the frog is on the + * first stone and assumes the frist just must be 1 unit. if the frog's last + * jump was k units, its next jujp must be either 'k - 1' or 'k + 1' units. the + * frog can only jump in the forward direction. + */ + +bool dfs(int *stones, int stones_size, int t, long long **hash, int x) { + if (stones_size == 1) + return true; + int p = -1, c = -1, n = -1; + long long val = (stones[0] << 10) + t; + long long d = val; + while (1) { + if (!hash[d % x]) + break; + else if (hash[d % x][0] == val) + return false; + else + d++; + } + for (int i = 1; i < stones_size; i++) { + if (stones[i] == stones[0] + t + 1) + n = i; + if (stones[i] == stones[0] + t) + c = i; + if (stones[i] == stones[0] + t - 1) + p = i; + if (stones[i] > stones[0] + t + 1) + break; + } + if (n != -1 && dfs(stones + n, stones_size - n, t + 1, hash, x)) + return true; + if (c != -1 && dfs(stones + c, stones_size - c, t, hash, x)) + return true; + if (p != -1 && dfs(stones + p, stones_size - p, t - 1, hash, x)) + return true; + d = val; + while (1) { + if (!hash[d % x]) { + hash[d % x] = malloc(sizeof(long long)); + hash[d % x][0] = val; + break; + } else + d++; + } + return false; +} + +bool canCross(int *stones, int stones_size) { + if (stones[0] || stones[1] != 1) + return false; + int x = 100 * stones_size; + long long **hash = calloc(x, sizeof(long long *)); + bool ans = dfs(stones + 1, stones_size - 1, 1, hash, x); + for (int i = 0; i < x; i++) { + if (!hash[i]) + continue; + free(hash[i]); + } + free(hash); + return ans; +} + +int main() { + int s1[] = {0, 1, 3, 5, 6, 8, 12, 17}, s2[] = {0, 1, 2, 3, 4, 8, 9, 11}; + printf("%d\n", canCross(s1, 8)); // expect: 1 + printf("%d\n", canCross(s2, 8)); // expect: 0 +} diff --git a/frog_jump.cpp b/frog_jump.cpp new file mode 100644 index 0000000..0b40565 --- /dev/null +++ b/frog_jump.cpp @@ -0,0 +1,47 @@ +// 403. Frog Jump +#include "leetcode.h" + +/* + * a frog is crossing a river. the river is divided into some number of units + * and at each unit, there may or may not exist a stone. the frog can jump on a + * stone, but it must not jump into the water. given a list of 'stones' + * positions in (units) in sorted ascending order, determine if the frog can + * cross the river by landing on the last stone. initially, the frog is on the + * first stone and assumes the frist just must be 1 unit. if the frog's last + * jump was k units, its next jujp must be either 'k - 1' or 'k + 1' units. the + * frog can only jump in the forward direction. + */ + +class Solution { + bool process(vector<int> &stones, map<int, int> &mp, int i, int k, + vvd(int) & dp) { + if (i == stones.size() - 1) + return dp[i][k] = 1; + if (dp[i][k] != -1) + return dp[i][k]; + for (int t = k - 1; t <= k + 1; t++) + if (t && mp.find(stones[i] + t) != mp.end()) { + int idx = mp[stones[i] + t]; + if (process(stones, mp, idx, t, dp)) + return dp[i][k] = 1; + } + return dp[i][k] = 0; + } + +public: + bool canCross(vector<int> &stones) { + int n = stones.size(); + map<int, int> mp; + for (int i = 0; i < n; i++) + mp[stones[i]] = i; + vvd(int) dp(n + 1, vector<int>(n + 1, -1)); + return process(stones, mp, 0, 0, dp); + } +}; + +int main() { + Solution obj; + vector<int> s1 = {0, 1, 3, 5, 6, 8, 12, 17}, s2 = {0, 1, 2, 3, 4, 8, 9, 11}; + printf("%d\n", obj.canCross(s1)); // expect: 1 + printf("%d\n", obj.canCross(s2)); // expect: 0 +} diff --git a/frog_jump.py b/frog_jump.py new file mode 100644 index 0000000..0de82ce --- /dev/null +++ b/frog_jump.py @@ -0,0 +1,31 @@ +class Solution(object): + def canCross(self, stones): + """ + :type stones: List[int] + :rtype bool + """ + self.memo = set() + target = stones[-1] + stones = set(stones) + ans = self.bt(stones, 1, 1, target) + return ans + + def bt(self, stones, curr, speed, target): + if (curr, speed) in self.memo: + return False + if curr == target: + return True + if curr > target or curr < 0 or speed <= 0 or curr not in stones: + return False + candidate = [speed - 1, speed, speed + 1] + for c in candidate: + if (curr + c) in stones: + if self.bt(stones, curr + c, c, target): + return True + self.memo.add((curr, speed)) + return False + +if __name__ == "__main__": + obj = Solution() + print(obj.canCross([0,1,3,5,6,8,12,17])) # expect: True + print(obj.canCross([0,1,2,3,4,8,9,11])) # expect: False diff --git a/fruit_into_baskets.c b/fruit_into_baskets.c new file mode 100644 index 0000000..17316e5 --- /dev/null +++ b/fruit_into_baskets.c @@ -0,0 +1,43 @@ +// 904. Fruit Into Baskets +#include <stdio.h> +#include <stdlib.h> + +/* + * you are visiting a farm that has a single row of fruit trees arranged from + * left t oright. the trees are represented by an integer array 'fruits' where + * 'fruits[i]' is the type of fruit the i'th tree produces. you want to collect + * as much fruit as possible. however, the owner has some strict rules that you + * must follow: you can only have two baskets and each can only hoold a single + * type of fruit (unlimited quantity). starting from any tree, you must pick + * exacty one fruit from every tree while moving to the right. once you reach a + * tree with fruit that cannot fit in your baskets, you must stop. given the int + * array 'fruits', return the maximum number of fruits you can pick + */ + +int totalFruit(int *fruits, int fruitsSize) { + int n = fruitsSize, type = 0, left = 0, right = 0; + int *hash = calloc(n, sizeof(int)); + while (right < fruitsSize) { + if (hash[fruits[right]] == 0) + type++; + hash[fruits[right]]++; + right++; + if (type > 2) { + if (hash[fruits[left]] == 1) + type--; + hash[fruits[left]]--; + left++; + } + } + free(hash); + return right - left; +} + +int main() { + int fruits1[] = {1, 2, 1}, fs1 = 3; + int fruits2[] = {0, 1, 2, 2}, fs2 = 4; + int fruits3[] = {1, 2, 3, 2, 2}, fs3 = 5; + printf("%d\n", totalFruit(fruits1, fs1)); // expect: 3 + printf("%d\n", totalFruit(fruits2, fs2)); // expect: 3 + printf("%d\n", totalFruit(fruits3, fs3)); // expect: 4 +} diff --git a/fruit_into_baskets.cpp b/fruit_into_baskets.cpp new file mode 100644 index 0000000..e613659 --- /dev/null +++ b/fruit_into_baskets.cpp @@ -0,0 +1,41 @@ +// 904. Fruit Into Baskets +#include "leetcode.h" + +/* + * you are visiting a farm that has a single row of fruit trees arranged from + * left t oright. the trees are represented by an integer array 'fruits' where + * 'fruits[i]' is the type of fruit the i'th tree produces. you want to collect + * as much fruit as possible. however, the owner has some strict rules that you + * must follow: you can only have two baskets and each can only hoold a single + * type of fruit (unlimited quantity). starting from any tree, you must pick + * exacty one fruit from every tree while moving to the right. once you reach a + * tree with fruit that cannot fit in your baskets, you must stop. given the int + * array 'fruits', return the maximum number of fruits you can pick + */ + +class Solution { +public: + int totalFruit(vector<int> &fruits) { + int n = fruits.size(), ans = 0; + unordered_map<int, int> cnt; + for (int l = 0, r = 0; r < n; ++r) { + cnt[fruits[r]]++; + while (cnt.size() > 2) { + if (--cnt[fruits[l]] == 0) + cnt.erase(fruits[l]); + ++l; + } + ans = max(ans, r - l + 1); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> fruits1 = {1, 2, 1}, fruits2 = {0, 1, 2, 2}, + fruits3 = {1, 2, 3, 2, 2}; + cout << obj.totalFruit(fruits1) << endl; // expect: 3 + cout << obj.totalFruit(fruits2) << endl; // expect: 3 + cout << obj.totalFruit(fruits3) << endl; // expect: 4 +} diff --git a/furthest_building_reach.c b/furthest_building_reach.c new file mode 100644 index 0000000..f5ee496 --- /dev/null +++ b/furthest_building_reach.c @@ -0,0 +1,80 @@ +// 1642. Furthest Building You Can Reach +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array 'heights' representing the heights of buildings, some + * 'bricks' and some 'ladders'. you start your journey from building 0 and move + * to the next building by possibly using bricks or ladders. while moving from + * building 'i' to building 'i + 1' (0-indexed): + * - if the current building's height is greater than or equal to the height of + * next building, you do not need a ladder or bricks + * - if the current building's height is less than the next building's height, + * you can either use one ladder or '(h[i + 1] - h[i])' bricks return the + * furthest building index (0-indexed) you can reach if you use the given + * ladders and bricks optimally + */ + +int heap[100000], heap_cnt; + +void insert(int val) { + int now = heap_cnt; + heap[now] = val; + heap_cnt++; + while (now >= 1) { + int p = (now - 1) / 2; + if (heap[now] < heap[p]) { + int tmp = heap[now]; + heap[now] = heap[p]; + heap[p] = tmp; + now = p; + } else + break; + } +} + +int pop() { + int res = heap[0], now = 0; + heap[0] = heap[--heap_cnt]; + while (now * 2 + 1 < heap_cnt) { + int tmp, next_pos = now; + if (heap[now] > heap[now * 2 + 1]) + next_pos = now * 2 + 1; + if (now * 2 + 2 < heap_cnt && heap[next_pos] > heap[now * 2 + 2]) + next_pos = now * 2 + 2; + if (now == next_pos) + break; + tmp = heap[now]; + heap[now] = heap[next_pos]; + heap[next_pos] = tmp; + now = next_pos; + } + return res; +} + +int furthestBuilding(int *heights, int heights_size, int bricks, int ladders) { + int cnt = 0; + heap_cnt = 0; + for (int i = 0; i < heights_size - 1; i++) { + if (heights[i] > heights[i + 1]) + continue; + insert(heights[i + 1] - heights[i]); + if (cnt < ladders) + cnt++; + else { + int min = pop(); + if (min > bricks) + return i; + bricks -= min; + } + } + return heights_size - 1; +} + +int main() { + int h1[] = {4, 2, 7, 6, 9, 14, 12}, h2[] = {4, 12, 2, 7, 3, 18, 20, 3, 19}, + h3[] = {14, 3, 19, 3}; + printf("%d\n", furthestBuilding(h1, 7, 5, 1)); // expect: 4 + printf("%d\n", furthestBuilding(h2, 9, 10, 2)); // expect: 7 + printf("%d\n", furthestBuilding(h3, 4, 17, 0)); // expect: 3 +} diff --git a/furthest_building_reach.cpp b/furthest_building_reach.cpp new file mode 100644 index 0000000..6baff33 --- /dev/null +++ b/furthest_building_reach.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class Solution { +public: + int furthestBuilding(vector<int> &heights, int bricks, int ladders) { + int n = heights.size() - 1; + priority_queue<int> pq; + for (int i = 0; i < n; i++) { + int diff = heights[i + 1] - heights[i]; + if (diff > 0) { + if (ladders) + pq.push(-diff), ladders--; + else if (!pq.empty() && diff > -pq.top()) { + pq.push(-diff); + bricks += pq.top(); + pq.pop(); + } else + bricks -= diff; + if (bricks < 0) + return i; + } + } + return n; + } +}; + +int main() { + Solution obj; + vector<int> heights = {4, 2, 7, 6, 9, 14, 12}; + int bricks = 5, ladders = 1; + cout << obj.furthestBuilding(heights, bricks, ladders); +} diff --git a/furthest_building_reach.py b/furthest_building_reach.py new file mode 100644 index 0000000..7fb2a81 --- /dev/null +++ b/furthest_building_reach.py @@ -0,0 +1,36 @@ +# 1642. Furthest Building You Can Reach +import heapq + +""" +given an integer array 'heights' representing the heights of buildings, some +'bricks' and some 'ladders'. you start your journey from building 0 and move +to the next building by possibly using bricks or ladders. while moving from +building 'i' to building 'i + 1' (0-indexed): +- if the current building's height is greater than or equal to the height of +next building, you do not need a ladder or bricks +- if the current building's height is less than the next building's height, +you can either use one ladder or '(h[i + 1] - h[i])' bricks return the +furthest building index (0-indexed) you can reach if you use the given +ladders and bricks optimally +""" + + +class Solution(object): + def furthestBuilding(self, heights, bricks, ladders): + heap = [] + for i in range(len(heights) - 1): + d = heights[i + 1] - heights[i] + if d > 0: + heapq.heappush(heap, d) + if len(heap) > ladders: + bricks -= heapq.heappop(heap) + if bricks < 0: + return i + return len(heights) - 1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.furthestBuilding([4, 2, 7, 6, 9, 14, 12], 5, 1)) # expect: 4 + print(obj.furthestBuilding([4, 12, 2, 7, 3, 18, 20, 3, 19], 10, 2)) # expect: 7 + print(obj.furthestBuilding([14, 3, 19, 3], 17, 0)) # expect: 3 diff --git a/game_of_life.cpp b/game_of_life.cpp new file mode 100644 index 0000000..86c9d53 --- /dev/null +++ b/game_of_life.cpp @@ -0,0 +1,37 @@ +#include <bits/stdc++.h> +using namespace std; + +class Solution { +public: + void gameOfLife(vector<vector<int>> &board) { + vector<int> waysX = {0, 0, 1, 1, 1, -1, -1, -1}; + vector<int> waysY = {1, -1, 1, -1, 0, 0, 1, -1}; + for (int row = 0; row < board.size(); row++) { + for (int col = 0; col < board[0].size(); col++) { + int live = 0; + for (int i = 0; i < 8; i++) { + int currX = row + waysX[i], currY = col + waysY[i]; + if (isNeighbor(currX, currY, board) && abs(board[currX][currY]) == 1) + live++; + } + if (board[row][col] == 1 && (live < 2 || live > 3)) + board[row][col] = -1; + if (board[row][col] == 0 && live == 3) + board[row][col] = 2; + } + } + for (int row = 0; row < board.size(); row++) + for (int col = 0; col < board[0].size(); col++) + if (board[row][col] >= 1) + board[row][col] = 1; + else + board[row][col] = 0; + } + +private: + bool isNeighbor(int x, int y, vector<vector<int>> &board) { + return (x >= 0 && x < board.size() && y >= 0 && y < board[0].size()); + } +}; + +int main() {} diff --git a/gas_station.cpp b/gas_station.cpp new file mode 100644 index 0000000..2fdc7fb --- /dev/null +++ b/gas_station.cpp @@ -0,0 +1,25 @@ +#include "leetcode.h" + +class Solution { +public: + int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { + int n = gas.size(), totalSurplus = 0, surplus = 0, start = 0; + for (int i = 0; i < n; i++) { + totalSurplus += gas[i] - cost[i]; + surplus += gas[i] - cost[i]; + if (surplus < 0) { + surplus = 0; + start = i + 1; + } + } + return (totalSurplus < 0) ? -1 : start; + } +}; + +int main() { + Solution obj; + vector<int> gas1 = {1, 2, 3, 4, 5}, gas2 = {2, 3, 4}, cost1 = {3, 4, 5, 1, 2}, + cost2 = {3, 4, 3}; + cout << obj.canCompleteCircuit(gas1, cost1) << endl; // expect: 3 + cout << obj.canCompleteCircuit(gas2, cost1) << endl; // expect: -1 +} diff --git a/gas_station.rs b/gas_station.rs new file mode 100644 index 0000000..0554f5b --- /dev/null +++ b/gas_station.rs @@ -0,0 +1,26 @@ +struct Solution; + +impl Solution { + pub fn can_complete_circuit(gas: Vec<i32>, cost: Vec<i32>) -> i32 { + let (mut sum, mut idx, mut min) = (0, 0, 0); + for i in 0..gas.len() { + sum += gas[i] - cost[i]; + if sum < min { + min = sum; + idx = i + 1; + } + } + if sum < 0 { + -1 + } else { + idx as i32 + } + } +} + +fn main() { + let (gas1, gas2) = (vec![1,2,3,4,5], vec![2,3,4]); + let (cost1, cost2) = (vec![3,4,5,1,2], vec![3,4,3]); + println!("{}", Solution::can_complete_circuit(gas1, cost1)); //expect: 3 + println!("{}", Solution::can_complete_circuit(gas2, cost2)); //expect: -1 +} diff --git a/gen_parentheses.cpp b/gen_parentheses.cpp new file mode 100644 index 0000000..4271beb --- /dev/null +++ b/gen_parentheses.cpp @@ -0,0 +1,21 @@ +#include <bits/stdc++.h> +using namespace std; + +class Solution { +public: + vector<string> result; + void helper(int open, int close, int n, string curr) { + if (curr.length() == n * 2) + result.push_back(curr); + if (open < n) + helper(open + 1, close, n, curr + '('); + if (close < open) + helper(open, close + 1, n, curr + ')'); + } + vector<string> generateParenthesis(int n) { + helper(0, 0, n, ""); + return result; + } +}; + +int main() {} diff --git a/get_equal_substr_budget.c b/get_equal_substr_budget.c new file mode 100644 index 0000000..0a515f8 --- /dev/null +++ b/get_equal_substr_budget.c @@ -0,0 +1,40 @@ +// 1208. Get Equal Substrings Within Budget +#include "leetcode.h" + +/* + * you are given two strings 's' and 't' of the same length and an integer + * 'maxCost'. you want to change 's' to 't'. changing the i'th character of 's' + * to the i'th character of 't' costs '|s[i] - t[i]|'. return the maximum length + * of a substring of 's' that can be changed to be the same as the corresponding + * substring of 't' with a cost less than or equal to 'maxCost'. if there is no + * substring from 's' that can be changed to its corresponding substring from + * 't', return 0 + */ + +int equalSubstring(char *s, char *t, int maxCost) { + int n = strlen(s), ans = 0, sum = 0, l = 0, r; + char *diff = (char *)malloc(n * sizeof(char)); + for (int i = 0; i < n; i++) + diff[i] = abs(s[i] - t[i]); + for (r = 0; r < n; r++) { + sum += diff[r]; + if (sum > maxCost) { + ans = fmax(ans, r - l); + while (sum > maxCost) { + sum -= diff[l]; + l++; + } + } + } + ans = fmax(ans, r - l); + free(diff); + return ans; +} + +int main() { + char *s1 = "abcd", *t1 = "bcdf", *s2 = "abcd", *t2 = "cdef", *s3 = "abcd", + *t3 = "acde"; + printf("%d\n", equalSubstring(s1, t1, 3)); // expect: 3 + printf("%d\n", equalSubstring(s2, t2, 3)); // expect: 1 + printf("%d\n", equalSubstring(s3, t3, 0)); // expect: 1 +} diff --git a/get_equal_substr_budget.py b/get_equal_substr_budget.py new file mode 100644 index 0000000..5bca2a1 --- /dev/null +++ b/get_equal_substr_budget.py @@ -0,0 +1,35 @@ +# 1208. Get Equal Substrings Within Budget + +""" +you are given two strings 's' and 't' of the same length and an integer +'maxCost'. you want to change 's' to 't'. changing the i'th character of 's' +to the i'th character of 't' costs '|s[i] - t[i]|'. return the maximum length +of a substring of 's' that can be changed to be the same as the corresponding +substring of 't' with a cost less than or equal to 'maxCost'. if there is no +substring from 's' that can be changed to its corresponding substring from +'t', return 0 +""" + + +class Solution(object): + def equalSubstring(self, s, t, maxCost): + """ + :type s: str + :type t: str + :type maxCost: int + :rtype: int + """ + i = 0 + for j in range(len(s)): + maxCost -= abs(ord(s[j]) - ord(t[j])) + if maxCost < 0: + maxCost += abs(ord(s[i]) - ord(t[i])) + i += 1 + return j - i + 1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.equalSubstring(s="abcd", t="bcdf", maxCost=3)) + print(obj.equalSubstring(s="abcd", t="cdef", maxCost=3)) + print(obj.equalSubstring(s="abcd", t="acde", maxCost=0)) diff --git a/graph_bipartite.cpp b/graph_bipartite.cpp new file mode 100644 index 0000000..b37972d --- /dev/null +++ b/graph_bipartite.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> vis, col; + bool isBipartite(vector<vector<int>> &graph) { + int n = graph.size(); + vis.resize(n); + col.resize(n); + for (int i = 0; i < n; i++) + if (vis[i] == 0 && dfs(i, 0, graph) == false) + return false; + return true; + } + +private: + bool dfs(int v, int c, vector<vector<int>> &graph) { + vis[v] = 1; + col[v] = c; + for (int child : graph[v]) + if (vis[child] == 0) { + if (dfs(child, c ^ 1, graph) == false) + return false; + } else if (col[v] == col[child]) + return false; + return true; + } +}; + +int main() {} diff --git a/greatest_common_div_string.c b/greatest_common_div_string.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/greatest_common_div_string.c diff --git a/greatest_common_div_string.cpp b/greatest_common_div_string.cpp new file mode 100644 index 0000000..420eb10 --- /dev/null +++ b/greatest_common_div_string.cpp @@ -0,0 +1,36 @@ +// 1071. Greatest Common Divisor of Strings +#include "leetcode.h" + +/* + * for two strings 's' & 't', we say 't' divides 's' if and only if s = t + ... + * + t ie. 't' is concatenated with itself one or more times given two strings + * 'str1' & 'str2', return largest string 'x' such that 'x' divides both 'str1' + * & 'str2' + */ + +class Solution { +public: + string gcdOfStrings(string str1, string str2) { + /* first check if finding gcd is even possible + * eg. ABAB + AB == AB + ABAB + * LEET + CODE != CODE + LEET + */ + if (str1 + str2 == str2 + str1) { + // get gcd of string sizes + // eg. ABAB (4) and AB (2), gcd = 2 + int gcd = __gcd(str1.size(), str2.size()); + // return substring of (either) string + // beginning at element 0 and a length of gcd + return str1.substr(0, gcd); + // if gcd isn't possible, return empty string + } else + return ""; + } +}; + +int main() { + Solution obj; + cout << obj.gcdOfStrings("ABCABC", "ABC") << endl; // expect: ABC + cout << obj.gcdOfStrings("ABABAB", "ABAB") << endl; // expect: AB + cout << obj.gcdOfStrings("LEET", "CODE") << endl; // expect: n/a +} diff --git a/greatest_common_div_trav.c b/greatest_common_div_trav.c new file mode 100644 index 0000000..b46320c --- /dev/null +++ b/greatest_common_div_trav.c @@ -0,0 +1,21 @@ +// 2709. Greatest Common Divisor Traversal +#include "leetcode.h" + +/* + * given a 0-indexed integer array 'nums' and you are allowed to traverse + * between its indices, you can traverse between index 'i' and index 'j', 'i != + * j' if and only if 'gcd(nums[i], nums[j]) > 1' where 'gcd' is the greatest + * common divisor. your task is to determine if for every pair of indices 'i' + * and 'j' in 'nums' where 'i < j', there exists a sequence of traversals that + * can take use from 'i' to 'j'. return true if it is possible to traverse + * between all such pairs of indices or false otherwise. + */ + +bool canTraverseAllPairs(int *nums, int numsSize) {} + +int main() { + int n1[] = {2, 3, 6}, n2[] = {3, 9, 5}, n3[] = {4, 3, 12, 8}; + printf("%d\n", canTraverseAllPairs(n1, ARRAY_SIZE(n1))); // expect: 1 + printf("%d\n", canTraverseAllPairs(n2, ARRAY_SIZE(n2))); // expect: 0 + printf("%d\n", canTraverseAllPairs(n3, ARRAY_SIZE(n3))); // expect: 1 +} diff --git a/greatest_common_div_trav.py b/greatest_common_div_trav.py new file mode 100644 index 0000000..41fe547 --- /dev/null +++ b/greatest_common_div_trav.py @@ -0,0 +1,68 @@ +# 2709. Greatest Common Divisor Traversal + +""" +given a 0-indexed integer array 'nums' and you are allowed to traverse +between its indices, you can traverse between index 'i' and index 'j', 'i != +j' if and only if 'gcd(nums[i], nums[j]) > 1' where 'gcd' is the greatest +common divisor. your task is to determine if for every pair of indices 'i' +and 'j' in 'nums' where 'i < j', there exists a sequence of traversals that +can take use from 'i' to 'j'. return true if it is possible to traverse +between all such pairs of indices or false otherwise. +""" + + +class Solution(object): + def canTraverseAllPairs(self, nums): + """ + :type nums: List[int] + :rtype: bool + """ + n = len(nums) + if n == 1: + return True + f = [_ for _ in range(0, n)] + num = [1] * n + + def getf(x: int) -> int: + if f[x] == x: + return x + f[x] = getf(f[x]) + return f[x] + + def merge(x: int, y: int): + x, y = getf(x), getf(y) + if x == y: + return + if num[x] < num[y]: + x, y = y, x + f[y] = x + num[x] += num[y] + + have = {} + for i in range(0, n): + x = nums[i] + if x == 1: + return False + d = 2 + while d * d <= x: + if x % d == 0: + if d in have: + merge(i, have[d]) + else: + have[d] = i + while x % d == 0: + x //= d + d += 1 + if x > 1: + if x in have: + merge(i, have[x]) + else: + have[x] = i + return num[getf(0)] == n + + +if __name__ == "__main__": + obj = Solution() + print(obj.canTraverseAllPairs([2, 3, 6])) + print(obj.canTraverseAllPairs([3, 9, 5])) + print(obj.canTraverseAllPairs([4, 3, 12, 8])) diff --git a/greatest_sum_div_three.c b/greatest_sum_div_three.c new file mode 100644 index 0000000..c08d2bc --- /dev/null +++ b/greatest_sum_div_three.c @@ -0,0 +1,58 @@ +// 1262. Greatest Sum Divisible by Three +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array 'nums', return the maximum possible sum of elements of + * the array such that it is divisible by three + */ + +int maxSumDivThree(int *nums, int nums_size) { + int sum = 0, oneone = INT_MAX, onetwo = INT_MAX, twoone = INT_MAX, + twotwo = INT_MAX, rem = 0; + for (int i = 0; i < nums_size; i++) { + sum += nums[i]; + rem += nums[i] % 3; + if (nums[i] % 3 == 1) { + if (nums[i] <= oneone) { + onetwo = oneone; + oneone = nums[i]; + } else if (nums[i] < onetwo) + onetwo = nums[i]; + } else if (nums[i] % 3 == 2) { + if (nums[i] <= twoone) { + twotwo = twoone; + twoone = nums[i]; + } else if (nums[i] < twotwo) + twotwo = nums[i]; + } + } + rem %= 3; + if (rem == 1) { + if (oneone != INT_MAX && twoone != INT_MAX && twotwo != INT_MAX) + return sum - fmin(oneone, twoone + twotwo); + else if (oneone != INT_MAX) + return sum - oneone; + else + return 0; + } else if (rem == 2) { + if (oneone != INT_MAX && onetwo != INT_MAX && twoone != INT_MAX) + return sum - fmin(oneone + onetwo, twoone); + else if (twoone != INT_MAX) + return sum - twoone; + else if (oneone != INT_MAX && onetwo != INT_MAX) + return sum - oneone - onetwo; + else + return 0; + } else + return sum; +} + +int main() { + int n1[] = {3, 6, 5, 1, 8}, n2[] = {4}, n3[] = {1, 2, 3, 4, 4}; + printf("%d\n", maxSumDivThree(n1, 5)); // expect: 18 + printf("%d\n", maxSumDivThree(n2, 1)); // expect: 0 + printf("%d\n", maxSumDivThree(n3, 5)); // expect: 12 +} diff --git a/greatest_sum_div_three.cpp b/greatest_sum_div_three.cpp new file mode 100644 index 0000000..c828e58 --- /dev/null +++ b/greatest_sum_div_three.cpp @@ -0,0 +1,43 @@ +// 1262. Greatest Sum Divisible by Three +#include "leetcode.h" + +/* + * given an integer array 'nums', return the maximum possible sum of elements of + * the array such that it is divisible by three + */ + +class Solution { +public: + int maxSumDivThree(vector<int> &nums) { + int f1 = 10001, s1 = 10001, f2 = 10001, s2 = 10001, sum = 0; + for (int i = 0; i < nums.size(); i++) { + sum += nums[i]; + if (nums[i] % 3 == 1) { + if (nums[i] < f1) { + s1 = f1; + f1 = nums[i]; + } else if (nums[i] < s1) + s1 = nums[i]; + } else if (nums[i] % 3 == 2) { + if (nums[i] < f2) { + s2 = f2; + f2 = nums[i]; + } else if (nums[i] < s2) + s2 = nums[i]; + } + } + if (!(sum % 3)) + return sum; + if (sum % 3 == 1) + return sum - min(f1, f2 + s2); + return sum - min(f2, f1 + s1); + } +}; + +int main() { + Solution obj; + vector<int> n1 = {3, 6, 5, 1, 8}, n2 = {4}, n3 = {1, 2, 3, 4, 4}; + printf("%d\n", obj.maxSumDivThree(n1)); // expect: 18 + printf("%d\n", obj.maxSumDivThree(n2)); // expect: 0 + printf("%d\n", obj.maxSumDivThree(n3)); // expect: 12 +} diff --git a/group_anagrams.c b/group_anagrams.c new file mode 100644 index 0000000..61da31b --- /dev/null +++ b/group_anagrams.c @@ -0,0 +1,81 @@ +// 49. Group Anagrams +#include "leetcode.h" + +/* + * given an array of strings 'strs', group the anagrams together . you can + * return the answer in any order. an anagram is a word or phrase formed by + * rearranging the letters of a different word or phrase, typically using all + * the original letters exactly once. + */ + +int cmp_int(const void *a, const void *b) { + int *arr1 = *(int **)a; + int *arr2 = *(int **)b; + if (arr1[2] == arr2[2]) + return arr1[1] - arr2[1]; + return arr1[2] - arr2[2]; +} + +int cmp_str(const void *a, const void *b) { return *(char *)a - *(char *)b; } + +uint rshash(char *str) { + uint a = 63689, b = 378551, hash = 0; + while (*str) { + hash = hash * a + (*str++); + a *= b; + } + return hash & 0x7FFFFFFF; +} + +int hash(char *s) { + int n = strlen(s); + char *tmp = malloc((n + 1) * sizeof(char)); + strcpy(tmp, s); + qsort(tmp, n, sizeof(char), cmp_str); + int res = rshash(tmp); + free(tmp); + return res; +} + +char ***groupAnagrams(char **strs, int strs_size, int *return_size, + int **return_col_size) { + int i, j; + int **len_table = malloc(strs_size * sizeof(int *)); + for (i = 0; i < strs_size; i++) { + len_table[i] = malloc(3 * sizeof(int)); + len_table[i][0] = i; + len_table[i][1] = strlen(strs[i]); + len_table[i][2] = hash(strs[i]); + } + qsort(len_table, strs_size, sizeof(int *), cmp_int); + int l = len_table[0][1], cnt = 1, idx = 0; + char ***ans = malloc(10000 * sizeof(char **)); + *return_col_size = malloc(10000 * sizeof(int)); + for (i = 1; i < strs_size; i++) { + if (len_table[i][2] == len_table[i - 1][2]) + cnt++; + else { + l = len_table[i - 1][1]; + ans[idx] = malloc(cnt * sizeof(char *)); + return_col_size[0][idx] = cnt; + for (int j = 0; j < cnt; j++) { + ans[idx][j] = malloc((l + 1) * sizeof(char)); + strcpy(ans[idx][j], strs[len_table[i - 1 - j][0]]); + } + idx++; + cnt = 1; + } + } + ans[idx] = malloc(cnt * sizeof(char *)); + l = len_table[i - 1][1]; + return_col_size[0][idx] = cnt; + for (int j = 0; j < cnt; j++) { + ans[idx][j] = malloc((l + 1) * sizeof(char)); + strcpy(ans[idx][j], strs[len_table[i - 1 - j][0]]); + } + idx++; + *return_size = idx; + *return_col_size = realloc(*return_col_size, idx * sizeof(int)); + ans = realloc(ans, idx * sizeof(char **)); + return ans; +} diff --git a/group_anagrams.cpp b/group_anagrams.cpp new file mode 100644 index 0000000..a2a7c8a --- /dev/null +++ b/group_anagrams.cpp @@ -0,0 +1,18 @@ +#include "leetcode.h" + +class Solution { +public: + vvd(string) groupAnagrams(vector<string> &strs) { + map<array<int, 26>, vector<string>> groups; + for (string s : strs) { + array<int, 26> hash = {0}; + for (char c : s) + ++hash[c - 'a']; + groups[hash].push_back(s); + } + vvd(string) ans; + for (auto [hash, group] : groups) + ans.push_back(group); + return ans; + } +}; diff --git a/group_anagrams.py b/group_anagrams.py new file mode 100644 index 0000000..5457089 --- /dev/null +++ b/group_anagrams.py @@ -0,0 +1,29 @@ +# 49. Group Anagrams +from collections import defaultdict + +""" +given an array of strings 'strs', group the anagrams together . you can +return the answer in any order. an anagram is a word or phrase formed by +rearranging the letters of a different word or phrase, typically using all +the original letters exactly once. +""" + + +class Solution(object): + def groupAnagrams(self, strs): + """ + :type strs: List[str] + :rtype: List[List[str]] + """ + anagram_map = defaultdict(list) + for word in strs: + sorted_word = "".join(sorted(word)) + anagram_map[sorted_word].append(word) + return list(anagram_map.values()) + + +if __name__ == "__main__": + obj = Solution() + print(obj.groupAnagrams(strs=["eat", "tea", "tan", "ate", "nat", "bat"])) + print(obj.groupAnagrams(strs=[""])) + print(obj.groupAnagrams(strs=["a"])) diff --git a/group_anagrams.rs b/group_anagrams.rs new file mode 100644 index 0000000..212fc15 --- /dev/null +++ b/group_anagrams.rs @@ -0,0 +1,15 @@ +use std::collections::HashMap; +struct Solution; + +impl Solution { + pub fn group_anagrams(strs: Vec<String>) -> Vec<Vec<String>> { + let mut groups = HashMap::new(); + for s in strs { + let hash = s.bytes().fold([0;26], |mut h, b| { + h[(b - b'a') as usize] += 1; h + }); + groups.entry(hash).or_insert_with(Vec::new).push(s); + } + groups.into_values().collect() + } +} diff --git a/group_equivalent_string.c b/group_equivalent_string.c new file mode 100644 index 0000000..4380140 --- /dev/null +++ b/group_equivalent_string.c @@ -0,0 +1,71 @@ +// 893. Groups of Special-Equivalent Strings +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given an array of strings of the same length 'words'. in one move you can + * swap any two even inexed characters or any two odd indexed characters of a + * string 'words[i]'. two strings are special equivalent if after any number of + * moves, 'words[i] == wods[j]'. return the number of groups of special + * equivalent strings from words + */ + +int numSpecialEquivGroups(char **words, int words_size) { + const int s_len = strlen(words[0]); + const int e_len = 26, max_shift = 61; + char entries[1001][e_len]; + uint64_t sigs[1000]; + int32_t next[1000], back[1000], hashes[256]; + int size = 0; + memset(hashes, 0xFF, 256 * sizeof(int32_t)); + for (int i = 0; i < words_size; ++i) { + char *tmp = entries[size]; + uint64_t sig = 0; + uint8_t hash = 0; + memset(tmp, 0, e_len); + for (int j = 0; j < s_len; j += 2) { + int k = words[i][j] - 'a'; + tmp[k]++; + sig |= 1 << k; + } + for (int j = 1; j < s_len; j += 2) { + int k = words[i][j] - 'a'; + tmp[k] += 0x10; + sig |= 1 << (k + e_len); + } + for (int j = 0, shift = e_len * 2; shift < max_shift && j < s_len; ++j) + if (tmp[j]) { + sig |= tmp[2] << shift; + shift += 4; + } + for (int j = 0; j < e_len; ++j) { + int rotate = j & 0x1F; + unsigned char mask = (tmp[j] << rotate) | (tmp[j] >> (8 - rotate)); + hash ^= mask; + } + bool found = false; + for (int e = hashes[hash]; found == false && e != -1; e = next[e]) + found = sigs[e] == sig && memcmp(entries[e], tmp, e_len) == 0; + if (!found) { + sigs[size] = sig; + if (hashes[hash] == -1) + hashes[hash] = size; + else + next[back[hash]] = size; + back[hash] = size; + next[size] = -1; + ++size; + } + } + return size; +} + +int main() { + char w1[6][4] = {"abcd", "cdab", "cbad", "xyzz", "zzxy", "zzyx"}; + char w2[6][3] = {"abc", "acb", "bac", "bca", "cab", "cba"}; + printf("%d\n", numSpecialEquivGroups(w1, 6)); // expect: 3 + printf("%d\n", numSpecialEquivGroups(w2, 6)); // expect: 3 +} diff --git a/group_ppl_size.c b/group_ppl_size.c new file mode 100644 index 0000000..4281336 --- /dev/null +++ b/group_ppl_size.c @@ -0,0 +1,58 @@ +// 1282. Group the People Given the Group Size They Belong To +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * there are 'n' people that are split into some unknown number of groups. each + * person is labeled with a unique id from 0 to 'n - 1'. you are given an + * integer array 'group_sizes' where 'group_sizes[i]' is the size of the group + * that person 'i' is in. for example if 'group_sizes[i] = 3', then person 1 + * must be in a groiup size of 3. return a list of groups such that each person + * 'i' is in a group of size 'group_sizes[i]'. each person should appear in + * exactly one group, and every person must be in a group. if there are multiple + * answers, return any of them. it is guaranteed that there will be at least one + * valid solution for the given input. + */ + +int **groupThePeople(int *group_sizes, int group_sizes_size, int *return_size, + int **return_col_size) { + int table[group_sizes_size + 1][group_sizes_size + 1], + col[group_sizes_size + 1]; + memset(table, 0, sizeof(table)); + memset(col, 0, sizeof(col)); + int **ans = (int **)malloc(sizeof(int *) * group_sizes_size); + *return_size = 0; + *return_col_size = (int *)malloc(sizeof(int) * group_sizes_size); + for (int i = 0; i < group_sizes_size; i++) { + table[group_sizes[i]][col[group_sizes[i]]] = i; + col[group_sizes[i]]++; + } + for (int i = 0; i <= group_sizes_size; i++) { + int k = 0; + while (col[i]) { + ans[*return_size] = (int *)malloc(sizeof(int) * i); + (*return_col_size)[*return_size] = i; + for (int j = 0; j < i; j++) { + ans[*return_size][j] = table[i][k++]; + col[i]--; + } + (*return_size)++; + } + } + return ans; +} + +int main() { + int gs1[] = {3, 3, 3, 3, 3, 1, 3}, gs2[] = {2, 1, 3, 3, 3, 2}; + int **gtp1 = groupThePeople(gs1, 7, NULL, NULL); + int **gtp2 = groupThePeople(gs2, 6, NULL, NULL); + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + printf("%d ", gtp1[i][j]); + printf("\n"); + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + printf("%d ", gtp2[i][j]); + printf("\n"); +} diff --git a/group_ppl_size.py b/group_ppl_size.py new file mode 100644 index 0000000..daeb5df --- /dev/null +++ b/group_ppl_size.py @@ -0,0 +1,28 @@ +# 1282. Group the People Given the Group Size They Belong To +import collections + +""" +there are 'n' people that are split into some unknown number of groups. each +person is labeled with a unique id from 0 to 'n - 1'. you are given an +integer array 'group_sizes' where 'group_sizes[i]' is the size of the group +that person 'i' is in. for example if 'group_sizes[i] = 3', then person 1 +must be in a groiup size of 3. return a list of groups such that each person +'i' is in a group of size 'group_sizes[i]'. each person should appear in +exactly one group, and every person must be in a group. if there are multiple +answers, return any of them. it is guaranteed that there will be at least one +valid solution for the given input. +""" + + +class Solution(object): + def groupThePeople(self, group_sizes): + count = collections.defaultdict(list) + for i, size in enumerate(group_sizes): + count[size].append(i) + return [l[i : i + s] for s, l in count.items() for i in xrange(0, len(l), s)] + + +if __name__ == "__main__": + obj = Solution() + print(obj.groupThePeople([3, 3, 3, 3, 3, 1, 3])) # expect: [[5],[0,1,2],[3,4,6]] + print(obj.groupThePeople([2, 1, 3, 3, 3, 2])) # expecct: [[1],[0,5],[2,3,4]] diff --git a/guess_number_high_low.cpp b/guess_number_high_low.cpp new file mode 100644 index 0000000..d31ca99 --- /dev/null +++ b/guess_number_high_low.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + int guessNumber(int n) { + int left = 1, right = n, mid = n / 2; + while (left <= right) { + int ans = guess(mid); // guess is api call + if (!ans) + return mid; + left = ans < 0 ? left : mid + 1; + right = ans < 0 ? mid - 1 : right; + mid = left + (right - left) / 2; + } + return -1; + } +}; + +int main() { + Solution obj; + cout << obj.guessNumber(10); +} diff --git a/guess_number_high_low.rs b/guess_number_high_low.rs new file mode 100644 index 0000000..4cd717b --- /dev/null +++ b/guess_number_high_low.rs @@ -0,0 +1,22 @@ +struct Solution; + +impl Solution { + unsafe fn guessNumber(n: i32) -> i32 { + let (mut s, mut n) = (1, n as i64); + while s <= n { + let x = (n + s) / 2; + let g = guess(x as i32); + match g { + 0 => return x as i32, + 1 => s = x + 1, + -1 => n = x - 1, + _ => unreachable!() + } + } + unreachable!() + } +} + +fn main() { + print!("{}", Solution::guessNumber(10)); +} diff --git a/h_index.c b/h_index.c new file mode 100644 index 0000000..9e944de --- /dev/null +++ b/h_index.c @@ -0,0 +1,34 @@ +// 274. H-Index +#include "leetcode.h" + +/* + * given an array of integers 'citations' where 'citations[i]' is the number of + * citations a researcher received for their i'th paper, return the researchers + * h-index. according to the definition of h-index on wikipedia: the h-index is + * given as the maximum value of 'h' such that the given researcher published at + * least 'h' papers that have each been cited 'h' times. + */ + +int hIndex(int *citations, int citations_size) { + int dp[citations_size + 1]; + for (int i = 0; i < citations_size + 1; i++) + dp[i] = 0; + for (int i = 0; i < citations_size; i++) { + if (citations[i] < citations_size) + dp[citations[i]]++; + else + dp[citations_size]++; + } + for (int i = citations_size, acc = 0; i >= 0; i--) { + acc += dp[i]; + if (acc >= i) + return i; + } + return 0; +} + +int main() { + int c1[] = {3, 0, 6, 1, 5}, c2[] = {1, 3, 1}; + printf("%d\n", hIndex(c1, ARRAY_SIZE(c1))); // expect: 3 + printf("%d\n", hIndex(c2, ARRAY_SIZE(c2))); // expect: 1 +} diff --git a/h_index.py b/h_index.py new file mode 100644 index 0000000..b8d1fda --- /dev/null +++ b/h_index.py @@ -0,0 +1,31 @@ +# 274. H-Index +from itertools import accumulate + +""" +given an array of integers 'citations' where 'citations[i]' is the number of +citations a researcher received for their i'th paper, return the researchers +h-index. according to the definition of h-index on wikipedia: the h-index is +given as the maximum value of 'h' such that the given researcher published at +least 'h' papers that have each been cited 'h' times. +""" + + +class Solution(object): + def hIndex(self, citations): + """ + :type citations: List[int] + :rtype: int + """ + n = len(citations) + buckets = [0] * (n + 1) + for i in citations: + buckets[min(i, n)] += 1 + accum = list(accumulate(buckets[1:][::-1]))[::-1] + compr = [accum[i] >= i + 1 for i in range(n)] + return (compr + [0]).index(0) + + +if __name__ == "__main__": + obj = Solution() + print(obj.hIndex([3, 0, 6, 1, 5])) + print(obj.hIndex([1, 3, 1])) diff --git a/hand_of_straights.c b/hand_of_straights.c new file mode 100644 index 0000000..1c84079 --- /dev/null +++ b/hand_of_straights.c @@ -0,0 +1,60 @@ +// 846. Hand of Straights +#include "leetcode.h" + +/* + * alice has some number of cards and she wants to rearrange the cards into + * groups so that each group is of size 'groupSize' and consists of 'groupSize' + * consecutive cards. given an integer array 'hand' where 'hand[i]' is the value + * written on the i'th card and an integer 'groupSize', return true if she can + * rearrange the cards or false otherwise. + */ + +struct pair { + int num; + int cnt; +}; + +int cmp(const void *a, const void *b) { + return *(const int *)a - *(const int *)b; +} + +bool isNStraightHand(int *hand, int handSize, int groupSize) { + if (handSize % groupSize) + return false; + if (groupSize == 1) + return true; + qsort(hand, handSize, sizeof(int), cmp); + struct pair *arr = (struct pair *)calloc(handSize, sizeof(struct pair)); + arr[0].num = hand[0]; + arr[0].cnt = 1; + int idx = 0; + for (int i = 1; i < handSize; i++) { + if (hand[i] != arr[idx].num) + idx++; + arr[idx].num = hand[i]; + arr[idx].cnt++; + } + int pos = 0; + for (int i = 0; i < handSize; i++) { + while (pos < idx && !arr[pos].cnt) + pos++; + if (arr[pos].num == hand[i] && arr[pos].cnt) + for (int j = 0; j < groupSize; j++) { + int tar = hand[i] + j; + if (arr[pos + j].cnt && arr[pos + j].num == tar) + arr[pos + j].cnt--; + else { + free(arr); + return false; + } + } + } + free(arr); + return true; +} + +int main() { + int h1[] = {1, 2, 3, 6, 2, 3, 4, 7, 8}, h2[] = {1, 2, 3, 4, 5}; + printf("%d\n", isNStraightHand(h1, ARRAY_SIZE(h1), 3)); // expect: 1 + printf("%d\n", isNStraightHand(h2, ARRAY_SIZE(h2), 4)); // expect: 0 +} diff --git a/hand_of_straights.cpp b/hand_of_straights.cpp new file mode 100644 index 0000000..b08c7fa --- /dev/null +++ b/hand_of_straights.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + bool isNStraightHand(vector<int> &hand, int groupSize) { + if (hand.size() % groupSize != 0) + return false; + map<int, int> m; + for (auto &card : hand) + m[card]++; + for (int i = 0; i < groupSize; i++) { + int curr = m.begin()->first; + if (m[curr + i] == 0) + return false; + else if (--m[curr + i] < 1) + m.erase(curr + i); + } + return true; + } +}; + +int main() { + Solution obj; + vector<int> hand = {1, 2, 3, 6, 2, 3, 4, 7, 8}; + int groupSize = 3; + if (obj.isNStraightHand(hand, groupSize)) + cout << "true"; + else + cout << "false"; +} diff --git a/hand_of_straights.py b/hand_of_straights.py new file mode 100644 index 0000000..4b5ea9f --- /dev/null +++ b/hand_of_straights.py @@ -0,0 +1,33 @@ +# 846. Hand of Straights +from collections import Counter + +""" +alice has some number of cards and she wants to rearrange the cards into +groups so that each group is of size 'groupSize' and consists of 'groupSize' +consecutive cards. given an integer array 'hand' where 'hand[i]' is the value +written on the i'th card and an integer 'groupSize', return true if she can +rearrange the cards or false otherwise. +""" + + +class Solution(object): + def isNStraightHand(self, hand, groupSize): + """ + :type hand: List[int] + :type groupSize: int + :rtype: bool + """ + c = Counter(hand) + for i in sorted(c): + if c[i] > 0: + for j in range(groupSize)[::-1]: + c[i + j] -= c[i] + if c[i + j] < 0: + return False + return True + + +if __name__ == "__main__": + obj = Solution() + print(obj.isNStraightHand(hand=[1, 2, 3, 6, 2, 3, 4, 7, 8], groupSize=3)) + print(obj.isNStraightHand(hand=[1, 2, 3, 4, 5], groupSize=4)) diff --git a/happy_number.cpp b/happy_number.cpp new file mode 100644 index 0000000..e946b96 --- /dev/null +++ b/happy_number.cpp @@ -0,0 +1,37 @@ +#include "leetcode.h" + +class Solution { +public: + bool isHappy(int n) { + int slow, fast; + slow = fast = n; + do { + slow = square(slow); + for (int i = 0; i < 2; i++) + fast = square(fast); + } while (slow != fast); + if (slow == 1) + return 1; + else + return 0; + } + +private: + int square(int n) { + int num = 0, tmp; + while (n) { + tmp = n % 10; + num += tmp * tmp; + n /= 10; + } + return num; + } +}; + +int main() { + Solution obj; + if (obj.isHappy(19)) + cout << "true"; + else + cout << "false"; +} diff --git a/height_checker.c b/height_checker.c new file mode 100644 index 0000000..a752d9f --- /dev/null +++ b/height_checker.c @@ -0,0 +1,38 @@ +// 1051. Height Checker +#include "leetcode.h" + +/* + * a school is trying to take an annual photo of all the students. the students + * are asked to stand in a single file line in non decreasing order by height. + * let this ordering be represented by the integer array 'expected' where + * 'expected[i]' is the expected height of the i'th student in line. you are + * given an integer array 'heights' representing the current order that the + * students are standing in. each 'heights[i]' is the height of the i'th student + * in line. return the number of indices where 'heights[i] != expected[i]' + */ + +int cmp(const void *a, const void *b) { + long aa = *(int *)a, bb = *(int *)b; + return aa - bb; +} + +int heightChecker(int *heights, int heightsSize) { + if (heightsSize < 2) + return 0; + int *expected = (int *)malloc(sizeof(int) * heightsSize); + memcpy(expected, heights, sizeof(int) * heightsSize); + qsort(expected, heightsSize, sizeof(int), cmp); + int diff = 0; + for (int i = 0; i < heightsSize; i++) + if (heights[i] != expected[i]) + diff++; + free(expected); + return diff; +} + +int main() { + int h1[] = {1, 1, 4, 2, 1, 3}, h2[] = {5, 1, 2, 3, 4}, h3[] = {1, 2, 3, 4, 5}; + printf("%d\n", heightChecker(h1, ARRAY_SIZE(h1))); // expect: 3 + printf("%d\n", heightChecker(h2, ARRAY_SIZE(h2))); // expect: 5 + printf("%d\n", heightChecker(h3, ARRAY_SIZE(h3))); // expect: 0 +} diff --git a/height_checker.py b/height_checker.py new file mode 100644 index 0000000..8443737 --- /dev/null +++ b/height_checker.py @@ -0,0 +1,42 @@ +# 1051. Height Checker + +""" +a school is trying to take an annual photo of all the students. the students +are asked to stand in a single file line in non decreasing order by height. +let this ordering be represented by the integer array 'expected' where +'expected[i]' is the expected height of the i'th student in line. you are +given an integer array 'heights' representing the current order that the +students are standing in. each 'heights[i]' is the height of the i'th student +in line. return the number of indices where 'heights[i] != expected[i]' +""" + + +class Solution(object): + def heightChecker(self, heights): + """ + :type heights: List[int] + :rtype: int + """ + max_nr = max(heights) + cnt = [0] * (max_nr + 1) + for n in heights: + cnt[n] += 1 + sum_cnt = [0] * (max_nr + 1) + for i, n in enumerate(cnt[1:], start=1): + sum_cnt[i] = n + sum_cnt[i - 1] + output = [0] * len(heights) + for i in range(len(heights) - 1, -1, -1): + output[sum_cnt[heights[i]] - 1] = heights[i] + sum_cnt[heights[i]] -= 1 + ans = 0 + for i, n in enumerate(heights): + if n != output[i]: + ans += 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.heightChecker(heights=[1, 1, 4, 2, 1, 3])) + print(obj.heightChecker(heights=[5, 1, 2, 3, 4])) + print(obj.heightChecker(heights=[1, 2, 3, 4, 5])) diff --git a/house_robber.c b/house_robber.c new file mode 100644 index 0000000..f479a95 --- /dev/null +++ b/house_robber.c @@ -0,0 +1,37 @@ +// 198. House Robber +#include "leetcode.h" + +/* + * you are a professional robber planning to rob houses along a stree. each + * house has a certain amount of money stashed, the only constraint topping you + * from robbing each of them is that the adjacent houses have security systems + * connected and it will automatically contact the police if two adjacent houses + * were broken into on the same night. given an integer array 'nums' + * representing the amount of money each house has, return the maximum amount of + * money you can rob without alerting the police. + */ + +int rob(int *nums, int nums_size) { + int *dp = malloc(sizeof(int) * nums_size); + if (!nums_size) + return 0; + for (int i = 0; i < nums_size; i++) { + switch (i) { + case 0: + dp[i] = nums[0]; + break; + case 1: + dp[i] = fmax(nums[i], dp[i - 1]); + break; + default: + dp[i] = fmax(nums[i] + dp[i - 2], dp[i - 1]); + } + } + return dp[nums_size - 1]; +} + +int main() { + int n1[] = {1, 2, 3, 1}, n2[] = {2, 7, 9, 3, 1}; + printf("%d\n", rob(n1, ARRAY_SIZE(n1))); // expect: 4 + printf("%d\n", rob(n2, ARRAY_SIZE(n2))); // expect: 12 +} diff --git a/house_robber.cpp b/house_robber.cpp new file mode 100644 index 0000000..a08aa54 --- /dev/null +++ b/house_robber.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + int rob(vector<int> &nums) { + // space-optimized dynamic programming approach + int prev = 0, prev2 = 0, curr = 0; + for (auto i : nums) { + curr = max(prev, i + prev2); + prev2 = prev; + prev = curr; + } + return curr; + } +}; + +int main() { + Solution obj; + vector<int> nums = {1, 2, 3, 1}; + cout << obj.rob(nums); // expect 4 +} diff --git a/house_robber.py b/house_robber.py new file mode 100644 index 0000000..1a13c0c --- /dev/null +++ b/house_robber.py @@ -0,0 +1,32 @@ +# 198. House Robber + +""" +you are a professional robber planning to rob houses along a stree. each +house has a certain amount of money stashed, the only constraint topping you +from robbing each of them is that the adjacent houses have security systems +connected and it will automatically contact the police if two adjacent houses +were broken into on the same night. given an integer array 'nums' +representing the amount of money each house has, return the maximum amount of +money you can rob without alerting the police. +""" + + +class Solution(object): + def rob(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + if len(nums) == 1: + return nums[0] + dp = [*nums] + dp[1] = max(nums[0], nums[1]) + for i in range(2, len(nums)): + dp[i] = max(dp[i - 1], nums[i] + dp[i - 2]) + return dp[-1] + + +if __name__ == "__main__": + obj = Solution() + print(obj.rob([1, 2, 3, 1])) + print(obj.rob([2, 7, 9, 3, 1])) diff --git a/house_robber.rs b/house_robber.rs new file mode 100644 index 0000000..ce4afd9 --- /dev/null +++ b/house_robber.rs @@ -0,0 +1,18 @@ +struct Solution; + +impl Solution { + pub fn rob(nums: Vec<i32>) -> i32 { + let (mut prev, mut prev2) = (0,0); + for n in nums { + let curr = std::cmp::max(n + prev2, prev); + prev2 = prev; + prev = curr; + } + prev + } +} + +fn main() { + let nums = vec![1,2,3,1]; + print!("{}", Solution::rob(nums)); //expect 4 +} diff --git a/idx_first_occur_str.c b/idx_first_occur_str.c new file mode 100644 index 0000000..3b09c26 --- /dev/null +++ b/idx_first_occur_str.c @@ -0,0 +1,49 @@ +// 28. Find the Index of the First Occurrence in a String +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given two strings 'needle' and 'haystack', return index of the first + * occurrence of 'needle' in 'haystack', or -1 if 'needle' is not part of + * 'haystack' + */ + +int cmp(char *s, int i, char *p, int n_bytes) { + int j = 0; + while (n_bytes--) { + if (*(s + i) != *(p + j)) + return -1; + ++i; + ++j; + } + return 0; +} + +int strStr(char *haystack, char *needle) { + int s_len = strlen(haystack), n_len = strlen(needle); + if (!s_len) { + if (!n_len) + return 0; + return -1; + } + if (!n_len) + return 0; + int err = 0; + for (int i = 0; i < s_len; ++i) { + if (haystack[i] == needle[0]) { + err = cmp(haystack, i, needle, n_len); + if (err) + continue; + return i; + } + } + return -1; +} + +int main() { + char hs1[] = "sadbutsad", n1[] = "sad"; + char hs2[] = "leetcode", n2[] = "leeto"; + printf("%d\n", strStr(hs1, n1)); // expect: 0 + printf("%d\n", strStr(hs2, n2)); // expect: 0 +} diff --git a/idx_first_occur_str.cpp b/idx_first_occur_str.cpp new file mode 100644 index 0000000..0f24457 --- /dev/null +++ b/idx_first_occur_str.cpp @@ -0,0 +1,51 @@ +// 28. Find the Index of the First Occurrence in a String +#include "leetcode.h" +#include <vector> + +/* + * given two strings 'needle' and 'haystack', return index of the first + * occurrence of 'needle' in 'haystack', or -1 if 'needle' is not part of + * 'haystack' + */ + +class Solution { +public: + int strStr(string haystack, string needle) { + int m = haystack.size(), n = needle.size(); + if (!n) + return 0; + vector<int> lps = kmp(needle); + for (int i = 0, j = 0; i < m;) { + if (haystack[i] == needle[j]) + i++, j++; + if (j == n) + return i - j; + if (i < m && haystack[i] != needle[j]) + j ? j = lps[j - 1] : i++; + } + return -1; + } + +private: + // kmp algorithm: + // http://jakeboxer.com/blog/2009/12/13/the-knuth-morris-pratt-algorithm-in-my-own-words/ + vector<int> kmp(string needle) { + int n = needle.size(); + vector<int> lps(n, 0); + for (int i = 1, len = 0; i < n;) { + if (needle[i] == needle[len]) + lps[i++] = ++len; + else if (len) + len = lps[len - 1]; + else + lps[i++] = 0; + } + return lps; + } +}; + +int main() { + Solution obj; + cout << obj.strStr("sadbutsad", "sad") << endl; // expect: 0 + cout << obj.strStr("leetcode", "leeto") << endl; // expect: -1 +} diff --git a/image_overlap.cpp b/image_overlap.cpp new file mode 100644 index 0000000..43527db --- /dev/null +++ b/image_overlap.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + int largestOverlap(vvd(int) & img1, vvd(int) & img2) { + vector<int> la, lb; + int n = img1.size(); + unordered_map<int, int> count; + for (int i = 0; i < n * n; ++i) + if (img1[i / n][i % n] == 1) + la.push_back(i / n * 100 + i % n); + for (int i = 0; i < n * n; ++i) + if (img2[i / n][i % n] == 1) + lb.push_back(i / n * 100 + i % n); + for (int i : la) + for (int j : lb) + count[i - j]++; + int ans = 0; + for (auto it : count) + ans = max(ans, it.second); + return ans; + } +}; diff --git a/image_overlap.rs b/image_overlap.rs new file mode 100644 index 0000000..fa6fbd6 --- /dev/null +++ b/image_overlap.rs @@ -0,0 +1,35 @@ +impl Solution { + pub fn largest_overlap(img1: Vec<Vec<i32>>, img2: Vec<Vec<i32>>) -> i32 { + let mut ans = 0; + for i in 0..img1[0].len() { + for j in 00..img1.len() { + ans = ans.max(Solution::shift_and_compare(&img1, &img2, j, i)); + } + } + ans + } + + fn shift_and_compare(img1: &[Vec<i32>],img2: &[Vec<i32>], x_shift: usize, y_shift: usize) -> i32 { + let (mut counter, cols, rows) = ((0,0), img1.len(), img1[0].len()); + for i in 0..cols { + for j in 0..rows { + if img1[i][j] == 1 { + let ii = i + y_shift; + let jj = j + x_shift; + if ii < rows && jj < cols && img2[ii][jj] == 1 { + counter.0 += 1; + } + } + if img2[i][j] == 1 { + let ii = i + y_shift; + let jj = j + x_shift; + if ii < rows && jj < cols && img2[ii][jj] == 1 { + counter.1 += 1; + } + } + } + } + counter.0.max(counter.1) + } +} + diff --git a/image_smoother.c b/image_smoother.c new file mode 100644 index 0000000..969b031 --- /dev/null +++ b/image_smoother.c @@ -0,0 +1,36 @@ +// 661. Image Smoother +#include "leetcode.h" + +/* + * an image smoother is a filter of the size 3 x 3 that can be applied to each + * cell of an image by rounding down the average of the cell and the eight + * surrounding cells (ie. the average of the nine cells in the blue smoother). + * if one or more of the surrounding cells of a cell is not present, we do not + * consider it in the average (ie. the average of the four cells in the red + * smoother). given an m x n integer matrix 'img' representing the grayscale of + * an image, return the image after applying the smoother on each cell of it + */ + +int **imageSmoother(int **M, int MRowSize, int MColSize, int **columnSizes, + int *returnSize) { + int **ans = calloc(MColSize, sizeof(int)); + *returnSize = MColSize; + *columnSizes = calloc(MColSize, sizeof(int)); + for (int i = 0; i < MColSize; i++) { + (*columnSizes)[i] = MColSize; + ans[i] = calloc(MColSize, sizeof(int)); + } + int cnt; + for (int i = 0; i < MRowSize; i++) + for (int j = 0; j < MColSize; j++) { + cnt = 0; + for (int x = i - 1; x <= i + 1; x++) + for (int y = j - 1; y <= j + 1; y++) + if (x >= 0 && x < MRowSize && y >= 0 && y < MColSize) { + ans[i][j] += M[x][y]; + cnt++; + } + ans[i][j] /= cnt; + } + return ans; +} diff --git a/image_smoother.py b/image_smoother.py new file mode 100644 index 0000000..00c9431 --- /dev/null +++ b/image_smoother.py @@ -0,0 +1,39 @@ +# 661. Image Smoother +from copy import deepcopy + +""" +an image smoother is a filter of the size 3 x 3 that can be applied to each +cell of an image by rounding down the average of the cell and the eight +surrounding cells (ie. the average of the nine cells in the blue smoother). +if one or more of the surrounding cells of a cell is not present, we do not +consider it in the average (ie. the average of the four cells in the red +smoother). given an m x n integer matrix 'img' representing the grayscale of +an image, return the image after applying the smoother on each cell of it +""" + + +class Solution(object): + def imageSmoother(self, img): + """ + :type img: List[List[int]] + :rtype: List[List[int]] + """ + x_len = len(img) + y_len = len(img[0]) if x_len else 0 + ans = deepcopy(img) + for x in range(x_len): + for y in range(y_len): + neighbours = [ + img[_x][_y] + for _x in (x - 1, x, x + 1) + for _y in (y - 1, y, y + 1) + if 0 <= _x < x_len and 0 <= _y < y_len + ] + ans[x][y] = sum(neighbours) // len(neighbours) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.imageSmoother(img=[[1, 1, 1], [1, 0, 1], [1, 1, 1]])) + print(obj.imageSmoother(img=[[100, 200, 100], [200, 50, 200], [100, 200, 100]])) diff --git a/implement_queue_stacks.c b/implement_queue_stacks.c new file mode 100644 index 0000000..755b178 --- /dev/null +++ b/implement_queue_stacks.c @@ -0,0 +1,75 @@ +// 232. Implement Queue using Stacks +#include "leetcode.h" + +/* + * implement a fifo queue using only two stacks. the implemented queue should + * support all the functions of a normal queue: push, peek, pop, and empty. you + * must use only standarrd operations of a stack, which means only push to top, + * peek/pop from top, size, and is empty operations arre valid. depending on + * your language, the stack may not be supported natively. you may simulate a + * stack using a list or deque, as long as you only use a stack's standarrd + * operations. + */ + +typedef struct { + int arr[100]; + int head; + int tail; + int cnt; +} MyQueue; + +MyQueue *myQueueCreate() { + MyQueue *obj = malloc(sizeof(MyQueue)); + obj->head = 0; + obj->tail = 0; + obj->cnt = 0; + return obj; +} + +void myQueuePush(MyQueue *obj, int x) { + if (obj == NULL) + return; + + obj->cnt++; + obj->arr[obj->tail] = x; + obj->tail = (obj->tail + 1) % 100; +} + +int myQueuePop(MyQueue *obj) { + if (obj == NULL) + return NULL; + + obj->cnt--; + obj->head = (obj->head + 1) % 100; + return (obj->arr[(obj->head - 1) % 100]); +} + +int myQueuePeek(MyQueue *obj) { + if (obj == NULL) + return NULL; + + return obj->arr[obj->head]; +} + +bool myQueueEmpty(MyQueue *obj) { + if (obj == NULL) + return false; + + return (obj->cnt ? false : true); +} + +void myQueueFree(MyQueue *obj) { + if (obj == NULL) + return; + free(obj); +} + +/* + * Your MyQueue struct will be instantiated and called as such: + * MyQueue* obj = myQueueCreate(); + * myQueuePush(obj, x); + * int parram_2 = myQueuePop(obj); + * int parram_3 = myQueuePeek(obj); + * bool parram_4 = myQueueEmpty(obj); + * myQueueFree(obj); + */ diff --git a/implement_queue_stacks.cpp b/implement_queue_stacks.cpp new file mode 100644 index 0000000..551ce9f --- /dev/null +++ b/implement_queue_stacks.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class MyQueue { +public: + stack<int> input, output; + void push(int x) { input.push(x); } + int pop() { + int x = output.top(); + peek(); + return x; + } + int peek() { + if (output.empty()) + while (input.size()) + output.push(input.top()), input.pop(); + return output.top(); + } + bool empty() { return input.empty() && output.empty(); } +}; + +int main() { + MyQueue *obj = new MyQueue(); + obj->push(2); + int param_2 = obj->pop(); + int param_3 = obj->peek(); + bool param_4 = obj->empty(); + cout << param_2 << endl << param_3 << endl; + if (param_4) + cout << "true"; + else + cout << "endl"; +} diff --git a/implement_queue_stacks.py b/implement_queue_stacks.py new file mode 100644 index 0000000..2f7cd57 --- /dev/null +++ b/implement_queue_stacks.py @@ -0,0 +1,53 @@ +# 232. Implement Queue using Stacks + +""" +implement a fifo queue using only two stacks. the implemented queue should +support all the functions of a normal queue: push, peek, pop, and empty. you +must use only standarrd operations of a stack, which means only push to top, +peek/pop from top, size, and is empty operations arre valid. depending on your +language, the stack may not be supported natively. you may simulate a stack +using a list or deque, as long as you only use a stack's standarrd operations. +""" + + +class MyQueue(object): + def __init__(self): + self.in_stk = [] + self.out_stk = [] + + def push(self, x): + """ + :type x: int + :rtype: None + """ + self.in_stk.append(x) + + def pop(self): + """ + :rtype: int + """ + self.peek() + return self.out_stk.pop() + + def peek(self): + """ + :rtype: int + """ + if not self.out_stk: + while self.in_stk: + self.out_stk.append(self.in_stk.pop()) + return self.out_stk[-1] + + def empty(self): + """ + :rtype: bool + """ + return not self.in_stk and not self.out_stk + + +# Your MyQueue object will be instantiated and called as such: +# obj = MyQueue() +# obj.push(x) +# param_2 = obj.pop() +# param_3 = obj.peek() +# param_4 = obj.empty() diff --git a/implement_stack_queues.c b/implement_stack_queues.c new file mode 100644 index 0000000..7860822 --- /dev/null +++ b/implement_stack_queues.c @@ -0,0 +1,139 @@ +// 225. Implement Stack using Queues +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * implement a last in, first out (LIFO) stack using only two queues. the + * implemented stack should support all the functions of a normal stack ('push', + * 'top', 'pop', and 'empty'). implement the 'stack' class + * - void push(int x) pushes element 'x' to the top of the stack + * - int pop() removes the element on the top of the stack and returns it + * - int top() returns the element on the top of the stack + * - bool empty() returns 'true' if the stack is empty, 'false' otherwise + * notes: + * - you must use only standard operations of a queue, which means that only + * push to back, peek/pop from front, size, and is empty are valid operations. + * - depending on your language, the queue may not be supported natively. you + * may simulate a queue using a list of dequeu (double ended queue) as long as + * you only use a queue's standard operations. + */ + +typedef struct { + int *q; + int size; + int front; + int rear; +} queue; + +typedef struct { + queue *q1; + queue *q2; +} stack; + +int queue_empty(queue *q) { + if (q->front == -1 && q->rear == -1) { + printf("\nqueue is EMPTY\n"); + return 1; + } + return 0; +} + +int queue_full(queue *q) { + if (q->rear == q->size - 1) + return 1; + return 0; +} + +int queue_top(queue *q) { + if (queue_empty(q)) + return -1; + return q->q[q->front]; +} + +int queue_pop(queue *q) { + if (queue_empty(q)) + return -1; + int data = q->q[q->front]; + if (q->front == q->rear) + q->front = q->rear = -1; + else + q->front++; + return data; +} + +void queue_push(queue *q, int val) { + if (queue_full(q)) { + printf("\nqueue is FULL\n"); + return; + } + if (queue_empty(q)) { + q->front++; + q->rear++; + } else { + q->rear++; + } + q->q[q->rear] = val; +} + +queue *queue_create(int max_size) { + queue *q = (queue *)malloc(sizeof(queue)); + q->front = q->rear = -1; + q->size = max_size; + q->q = (int *)malloc(sizeof(int) * max_size); + return q; +} + +void stackCreate(stack *stk, int max_size) { + stack **s = (stack **)stk; + *s = (stack *)malloc(sizeof(stack)); + (*s)->q1 = queue_create(max_size); + (*s)->q2 = queue_create(max_size); +} + +void stackPush(stack *obj, int x) { + stack **s = (stack **)obj; + queue_push((*s)->q2, x); + while (!queue_empty((*s)->q1)) { + int data = queue_pop((*s)->q1); + queue_push((*s)->q2, data); + } + queue *tmp = (*s)->q1; + (*s)->q1 = (*s)->q2; + (*s)->q2 = tmp; +} + +int stackPop(stack *obj) { + stack **s = (stack **)obj; + return queue_pop((*s)->q1); +} + +int stackTop(stack *obj) { + stack **s = (stack **)obj; + if (!queue_empty((*s)->q1)) + return queue_top((*s)->q1); + return -1; +} + +bool stackEmpty(stack *obj) { + stack **s = (stack **)obj; + if (queue_empty((*s)->q1)) + return true; + return false; +} + +void stackFree(stack *obj) { + stack **s = (stack **)obj; + free((*s)->q1); + free((*s)->q2); + free((*s)); +} + +int main() { + stack *obj = stackCreate(); + stackPush(obj, 1); + stackPush(obj, 2); + printf("%d\n", stackTop(obj)); // expect: 2 + printf("%d\n", stackPop(obj)); // expect: 2 + printf("%d\n", stackEmpty(obj)); // expect: 0 +} diff --git a/implement_strstr.cpp b/implement_strstr.cpp new file mode 100644 index 0000000..4c888c2 --- /dev/null +++ b/implement_strstr.cpp @@ -0,0 +1,19 @@ +#include "leetcode.h" + +class Solution { +public: + int strStr(string haystack, string needle) { + int m = haystack.size(), n = needle.size(); + for (int i = 0; i <= m - n; i++) { + int j; + for (j = 0; j < n; j++) + if (haystack[i + j] != needle[j]) + break; + if (j == n) + return i; + } + return -1; + } +}; + +int main() {} diff --git a/increasing_seach_tree.cpp b/increasing_seach_tree.cpp new file mode 100644 index 0000000..cfe97ec --- /dev/null +++ b/increasing_seach_tree.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + TreeNode *increasingBST(TreeNode *root) { + TreeNode *temp; + TreeNode *ans = new TreeNode(); + temp = ans; + inOrder(ans, root); + return temp->right; + } + +private: + void inOrder(TreeNode *&ans, TreeNode *root) { + if (!root) + return; + inOrder(ans, root->left); + ans->right = new TreeNode(root->val); + ans = ans->right; + inOrder(ans, root->right); + } +}; + +int main() {} diff --git a/increasing_triplet_subsequence.cpp b/increasing_triplet_subsequence.cpp new file mode 100644 index 0000000..41a9f0e --- /dev/null +++ b/increasing_triplet_subsequence.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + bool increasingTriplet(vector<int> &nums) { + int one = INT_MAX, two = INT_MAX; + for (auto n : nums) { + if (n <= one) + one = n; + else if (n <= two) + two = n; + else + return true; + } + return false; + } +}; + +int main() { + Solution obj; + vector<int> nums = {1, 2, 3, 4, 5}; + if (obj.increasingTriplet(nums)) + cout << "true"; + else + cout << "false"; +} diff --git a/inform_employees.c b/inform_employees.c new file mode 100644 index 0000000..d9df5d7 --- /dev/null +++ b/inform_employees.c @@ -0,0 +1,65 @@ +// 1376. Time Needed to Inform All Employees +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * a company has 'n' employees with a unique id for each employee from 0 to 'n - + * 1'. the head of the company is the one with the 'head_id'. each employee has + * one direct manager given the 'manager' array where 'manager[i]' is the direct + * manager of the i'th employee, 'manager[head_id] = -1'. also it is guaranteed + * that the subordination relations have a tree structure. the head of the + * company wants to inform all the company employees of an urgent piece of new. + * he will inform his direct subordinates, and they will inform their + * subordinates and so on until all the employees know about the urgent news. + * the i'th employee needs 'inform_time[i]' minutes to inform all of his direct + * subordinates (ie. after 'inform_time[i]' minutes, all his direct subordinates + * can start spreading the news) return the number of minutes needed to inform + * all the employees about the urget news. + */ + +int numOfMinutes(int n, int head_id, int *manager, int manager_size, + int *inform_time, int inform_time_size) { + if (n == 1) + return 0; + int *cn = calloc(n, sizeof(int)); + for (int i = 0; i < n; i++) { + if (i == head_id) + continue; + cn[manager[i]]++; + } + int *min_time = malloc(n * sizeof(int)); + for (int i = 0; i < n; i++) + min_time[i] = INT_MIN; + int *stack = malloc(n * sizeof(int)); + int head = 0, idx = 0; + for (int i = 0; i < n; i++) + if (!cn[i]) { + min_time[i] = 0; + stack[idx] = i; + idx++; + } + while (head < idx) { + int emp = stack[head], mag = manager[emp]; + head++; + if (mag >= 0) { + cn[mag]--; + min_time[mag] = fmax(min_time[mag], inform_time[mag] + min_time[emp]); + if (!cn[mag]) { + stack[idx] = mag; + idx++; + } + } + } + int ans = min_time[head_id]; + free(cn), free(stack), free(min_time); + return ans; +} + +int main() { + int m1[] = {-1}, m2[] = {2, 2, -1, 2, 2, 2}; + int it1[] = {0}, it2[] = {0, 0, 1, 0, 0, 0}; + printf("%d\n", numOfMinutes(1, 0, m1, 1, it1, 1)); // expect: 0 + printf("%d\n", numOfMinutes(6, 2, m2, 6, it2, 6)); // expect: 1 +} diff --git a/inform_employees.cpp b/inform_employees.cpp new file mode 100644 index 0000000..700ccc3 --- /dev/null +++ b/inform_employees.cpp @@ -0,0 +1,44 @@ +// 1376. Time Needed to Inform All Employees +#include "leetcode.h" + +/* + * a company has 'n' employees with a unique id for each employee from 0 to 'n - + * 1'. the head of the company is the one with the 'head_id'. each employee has + * one direct manager given the 'manager' array where 'manager[i]' is the direct + * manager of the i'th employee, 'manager[head_id] = -1'. also it is guaranteed + * that the subordination relations have a tree structure. the head of the + * company wants to inform all the company employees of an urgent piece of new. + * he will inform his direct subordinates, and they will inform their + * subordinates and so on until all the employees know about the urgent news. + * the i'th employee needs 'inform_time[i]' minutes to inform all of his direct + * subordinates (ie. after 'inform_time[i]' minutes, all his direct subordinates + * can start spreading the news) return the number of minutes needed to inform + * all the employees about the urget news. + */ + +class Solution { + int dfs(int i, vector<int> &manager, vector<int> &inform_time) { + if (manager[i] != -1) { + inform_time[i] += dfs(manager[i], manager, inform_time); + manager[i] = -1; + } + return inform_time[i]; + } + +public: + int numOfMinutes(int n, int head_id, vector<int> &manager, + vector<int> &inform_time) { + int ans = 0; + for (int i = 0; i < n; ++i) + ans = max(ans, dfs(i, manager, inform_time)); + return ans; + } +}; + +int main() { + Solution obj; + vector<int> m1 = {-1}, m2 = {2, 2, -1, 2, 2, 2}; + vector<int> it1 = {0}, it2 = {0, 0, 1, 0, 0, 0}; + printf("%d\n", obj.numOfMinutes(1, 0, m1, it1)); // expect: 0 + printf("%d\n", obj.numOfMinutes(6, 2, m2, it2)); // expect: 1 +} diff --git a/insert_delete_getrandom.c b/insert_delete_getrandom.c new file mode 100644 index 0000000..1c054bd --- /dev/null +++ b/insert_delete_getrandom.c @@ -0,0 +1,124 @@ +// 380. Insert Delete GetRandom O(1) +#include "leetcode.h" + +/* +Implement the RandomizedSet class: +RandomizedSet() Initializes the RandomizedSet object. +bool insert(int val) Inserts an item val into the set if not present. +Returns true if the item was not present, false otherwise. bool remove(int val) +Removes an item val from the set if present. Returns true if the item was +present, false otherwise. int getRandom() Returns a random element from the +current set of elements (it's guaranteed that at least one element exists when +this method is called). Each element must have the same probability of being +returned. +You must implement the functions of the class such that each function works in +average O(1) time complexity. +*/ + +typedef struct { + int val; + struct node *next; +} node; + +typedef struct { + node **lists; + int *counts; + int total; +} RandomizedSet; + +RandomizedSet *randomizedSetCreate() { + RandomizedSet *obj = (RandomizedSet *)malloc(sizeof(RandomizedSet)); + obj->lists = (node **)calloc(128, sizeof(node *)); + obj->counts = (int *)calloc(128, sizeof(int)); + obj->total = 0; + return obj; +} + +bool randomizedSetInsert(RandomizedSet *obj, int val) { + int key = abs(val) % 128; + node *new_node, *tmp_node, *pre_node; + if (obj->lists[key] == NULL) { + new_node = (node *)malloc(sizeof(node)); + new_node->val = val; + new_node->next = NULL; + obj->lists[key] = new_node; + } else { + tmp_node = obj->lists[key]; + while (tmp_node) { + pre_node = tmp_node; + if (tmp_node->val == val) + return false; + tmp_node = tmp_node->next; + } + if (tmp_node == NULL) { + new_node = (node *)malloc(sizeof(node)); + new_node->val = val; + new_node->next = NULL; + pre_node->next = new_node; + } + } + obj->counts[key]++; + obj->total++; + return true; +} + +bool randomizedSetRemove(RandomizedSet *obj, int val) { + node *pre_node, *tmp_node; + int key = abs(val) % 128; + if (obj->lists[key] == NULL) { + return false; + } else { + tmp_node = obj->lists[key]; + while (tmp_node) { + if (tmp_node->val == val) { + if (pre_node) + pre_node->next = tmp_node->next; + else + obj->lists[key] = tmp_node->next; + free(tmp_node); + obj->counts[key]--; + obj->total--; + return true; + } + pre_node = tmp_node; + tmp_node = tmp_node->next; + } + return false; + } +} + +int randomizedSetGetRandom(RandomizedSet *obj) { + int pos = rand() % obj->total; + int i, sum = 0, key = 0; + node *tmp_node; + + for (i = 0; i < 128; i++) { + if (pos >= obj->counts[i]) { + pos -= obj->counts[i]; + } else { + key = i; + break; + } + } + tmp_node = obj->lists[key]; + while (tmp_node && pos) { + tmp_node = tmp_node->next; + pos--; + } + return tmp_node->val; +} + +void randomizedSetFree(RandomizedSet *obj) { + int i; + node *pre_node, *tmp_node; + for (i = 0; i < 128; i++) { + tmp_node = obj->lists[i]; + while (tmp_node) { + pre_node = tmp_node; + tmp_node = tmp_node->next; + free(pre_node); + } + } + free(obj->counts); + free(obj); +} diff --git a/insert_delete_getrandom.cpp b/insert_delete_getrandom.cpp new file mode 100644 index 0000000..5bb76da --- /dev/null +++ b/insert_delete_getrandom.cpp @@ -0,0 +1,45 @@ +#include "leetcode.h" + +class RandomizedSet { +public: + bool insert(int val) { + if (data.count(val)) + return false; + data[val] = idxs.size(); + idxs.push_back(val); + return true; + } + bool remove(int val) { + if (!data.count(val)) + return false; + int lst = idxs.back(), pos = data[val]; + data[lst] = pos; + idxs[pos] = lst; + data.erase(val); + idxs.pop_back(); + return true; + } + int getRandom() { return idxs[rand() % idxs.size()]; } + +private: + unordered_map<int, int> data; + vector<int> idxs; +}; + +int main() { + RandomizedSet *obj = new RandomizedSet(); + bool param_1 = obj->insert(2); + bool param_2 = obj->remove(1); + int param_3 = obj->getRandom(); + cout << "param_1 (insert 2): "; + if (param_1) + cout << "true\n"; + else + cout << "false\n"; + cout << "param_2 (remove 1): "; + if (param_2) + cout << "true\n"; + else + cout << "false\n"; + cout << "param_3 (getRandom): " << param_3; +} diff --git a/insert_delete_getrandom.py b/insert_delete_getrandom.py new file mode 100644 index 0000000..a5a1fda --- /dev/null +++ b/insert_delete_getrandom.py @@ -0,0 +1,72 @@ +# 380. Insert Delete GetRandom O(1) +import random + +""" +Implement the RandomizedSet class: +RandomizedSet() Initializes the RandomizedSet object. +bool insert(int val) Inserts an item val into the set if not present. +Returns true if the item was not present, false otherwise. bool remove(int val) +Removes an item val from the set if present. Returns true if the item was +present, false otherwise. int getRandom() Returns a random element from the +current set of elements (it's guaranteed that at least one element exists when +this method is called). Each element must have the same probability of being +returned. +You must implement the functions of the class such that each function works in +average O(1) time complexity. +""" + + +class RandomizedSet(object): + def __init__(self): + self.lst = [] + self.idx_map = {} + + def search(self, val): + return val in self.idx_map + + def insert(self, val): + """ + :type val: int + :rtype: bool + """ + if self.search(val): + return False + self.lst.append(val) + self.idx_map[val] = len(self.lst) - 1 + return True + + def remove(self, val): + """ + :type val: int + :rtype: bool + """ + if not self.search(val): + return False + idx = self.idx_map[val] + self.lst[idx] = self.lst[-1] + self.idx_map[self.lst[-1]] = idx + del self.idx_map[val] + return True + + def getRandom(self): + """ + :rtype: int + """ + return random.choice(self.lst) + + +# Your RandomizedSet object will be instantiated and called as such: +# obj = RandomizedSet() +# param_1 = obj.insert(val) +# param_2 = obj.remove(val) +# param_3 = obj.getRandom() + +if __name__ == "__main__": + obj = RandomizedSet() + print(obj.insert(1)) + print(obj.remove(2)) + print(obj.insert(2)) + print(obj.getRandom()) + print(obj.remove(1)) + print(obj.insert(2)) + print(obj.getRandom()) diff --git a/insert_delete_getrandom.rs b/insert_delete_getrandom.rs new file mode 100644 index 0000000..12a772f --- /dev/null +++ b/insert_delete_getrandom.rs @@ -0,0 +1,55 @@ +extern crate rand; +use rand::{Rng, thread_rng, rngs::ThreadRng}; +use std::collections::HashMap; + +struct RandomizedSet { + rng: ThreadRng, + data: Vec<i32>, + idx_map: HashMap<i32, usize> +} + +impl RandomizedSet { + fn new() -> Self { + Self { + rng: thread_rng(), + data: vec![], + idx_map: HashMap::new() + } + } + fn insert(&mut self, val: i32) -> bool { + if self.idx_map.contains_key(&val) { + return false; + } + self.idx_map.insert(val, self.data.len()); + self.data.push(val); + true + } + fn remove(&mut self, val: i32) -> bool { + if self.idx_map.contains_key(&val) == false { + return false; + } + let i = self.idx_map.remove(&val).unwrap(); + if i != self.data.len() - 1 { + self.data[i] = self.data[self.data.len() - 1]; + (*self.idx_map.get_mut(&self.data[i]).unwrap()) = i; + } + self.data.pop(); + true + } + fn get_random(&mut self) -> i32 { + if self.data.len() == 0 { + panic!(":P") + } + self.data[self.rng.gen_range(0, self.data.len())] + } +} + +fn main() { + let obj = RandomizedSet::new(); + let ret_1: bool = obj.insert(2); + let ret_2: bool = obj.remove(1); + let ret_3: i32 = obj.get_random(); + println!("param_1 (insert 2): {}", ret_1); + println!("param_2 (remove 1): {}", ret_2); + print!("param_3 (get_random): {}", ret_3); +} diff --git a/insert_interval.c b/insert_interval.c new file mode 100644 index 0000000..21025da --- /dev/null +++ b/insert_interval.c @@ -0,0 +1,52 @@ +// 57. Insert Interval +#include "leetcode.h" + +/* + * return array of arrays of size '*returnSize' + * the sizes of the arrays are returned as '*returnColumnSizes' array + * note both returned array and '*columnSizes' array must be malloced (assume + * caller free()'s memory) + */ + +int **insert(int **intervals, int intervalsSize, int *intervalsColSize, + int *newInterval, int newIntervalSize, int *returnSize, + int **returnColumnSizes) { + *returnSize = 0; + int left = newInterval[0], right = newInterval[1]; + bool placed = false; + int **ans = malloc(sizeof(int *) * (intervalsSize + 1)); + *returnColumnSizes = malloc(sizeof(int *) * (intervalsSize + 1)); + for (int i = 0; i < intervalsSize; i++) { + int *intval = intervals[i]; + if (intval[0] > right) { + if (!placed) { + int *tmp = malloc(sizeof(int) * 2); + tmp[0] = left; + tmp[1] = right; + (*returnColumnSizes)[*returnSize] = 2; + ans[(*returnSize)++] = tmp; + placed = true; + } + int *tmp = malloc(sizeof(int) * 2); + memcpy(tmp, intval, sizeof(int) * 2); + (*returnColumnSizes)[*returnSize] = 2; + ans[(*returnSize)++] = tmp; + } else if (intval[1] < left) { + int *tmp = malloc(sizeof(int) * 2); + memcpy(tmp, intval, sizeof(int) * 2); + (*returnColumnSizes)[*returnSize] = 2; + ans[(*returnSize)++] = tmp; + } else { + left = fmin(left, intval[0]); + right = fmax(right, intval[1]); + } + } + if (!placed) { + int *tmp = malloc(sizeof(int) * 2); + tmp[0] = left; + tmp[1] = right; + (*returnColumnSizes)[*returnSize] = 2; + ans[(*returnSize)++] = tmp; + } + return ans; +} diff --git a/insert_interval.cpp b/insert_interval.cpp new file mode 100644 index 0000000..09c6fe7 --- /dev/null +++ b/insert_interval.cpp @@ -0,0 +1,39 @@ +#include "leetcode.h" + +class Solution { +public: + vvd(int) insert(vvd(int) & intervals, vector<int> &newInterval) { + const int START = 0, END = 1; + int s = newInterval[START], e = newInterval[END]; + vvd(int) left, right; + for (auto &curr : intervals) { + if (curr[END] < s) + left.push_back(curr); + else if (curr[START] > e) + right.push_back(curr); + else { + s = min(s, curr[START]); + e = max(e, curr[END]); + } + } + vvd(int) ans; + ans.insert(ans.end(), left.begin(), left.end()); + ans.push_back({s, e}); + ans.insert(ans.end(), right.begin(), right.end()); + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) intervals1 = {{1, 3}, {6, 9}}, + intervals2 = {{1, 2}, {3, 5}, {6, 7}, {8, 10}, {12, 16}}; + vector<int> newInterval1 = {2, 5}, newInterval2 = {4, 8}; + for (auto i : obj.insert(intervals1, newInterval1)) + for (auto j : i) + cout << j << ' '; // expect: [[1,5],[6,9]] + cout << endl; + for (auto i : obj.insert(intervals2, newInterval2)) + for (auto j : i) + cout << j << ' '; // expect: [[1,2],[3,10],[12,16]] +} diff --git a/insert_interval.py b/insert_interval.py new file mode 100644 index 0000000..442b223 --- /dev/null +++ b/insert_interval.py @@ -0,0 +1,31 @@ +# 57. Insert Interval + + +class Solution(object): + def insert(self, intervals, newInterval): + """ + :type intervals: List[List[int]] + :type newInterval: List[int] + :rtype: List[List[int]] + """ + ans, i = [], -1 + for i, (x, y) in enumerate(intervals): + if y < newInterval[0]: + ans.append([x, y]) + elif newInterval[1] < x: + i -= 1 + break + else: + newInterval[0] = min(newInterval[0], x) + newInterval[1] = max(newInterval[1], y) + return ans + [newInterval] + intervals[i + 1 :] + + +if __name__ == "__main__": + obj = Solution() + print(obj.insert(intervals=[[1, 3], [6, 9]], newInterval=[2, 5])) + print( + obj.insert( + intervals=[[1, 2], [3, 5], [6, 7], [8, 10], [12, 16]], newInterval=[4, 8] + ) + ) diff --git a/int_roman.cpp b/int_roman.cpp new file mode 100644 index 0000000..e3a8a22 --- /dev/null +++ b/int_roman.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + string intToRoman(int num) { + string ans; + int val[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; + string sym[] = {"M", "CM", "D", "CD", "C", "XC", "L", + "XL", "X", "IX", "V", "IV", "I"}; + for (int i = 0; num != 0; i++) + while (num >= val[i]) { + ans += sym[i]; + num -= val[i]; + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.intToRoman(1994); +} diff --git a/int_roman.rs b/int_roman.rs new file mode 100644 index 0000000..9e8aa9e --- /dev/null +++ b/int_roman.rs @@ -0,0 +1,26 @@ +struct Solution; + +impl Solution { + pub fn int_to_roman(num: i32) -> String { + let (mut ans, mut curr) = ("".to_owned(), num); + let val_sym: Vec<(i32, &str)> = vec![ + (1000, "M"), (900, "CM"), (500, "D"), + (400, "CD"), (100, "C"), (90, "XC"), + (50, "L"), (40, "XL"), (10, "X"), + (9, "IX"), (5, "V"), (4, "IV"), (1, "I") + ]; + for &(v, s) in val_sym.iter() { + let count = curr / v; + if count > 0 { + let mult_str = s.repeat(count as usize); + ans.push_str(&mult_str); + curr %= v; + } + } + ans + } +} + +fn main() { + print!("{}", Solution::int_to_roman(1994)); +} diff --git a/integer_break.c b/integer_break.c new file mode 100644 index 0000000..27ad29e --- /dev/null +++ b/integer_break.c @@ -0,0 +1,37 @@ +// 343. Integer Break +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer 'n', break it into the sum of 'k' positive integers, where + * 'k >= 2' and maximise the product of those integers. return the maximum + * product you can get + */ + +int integerBreak(int n) { + int *dp = (int *)malloc((n + 1) * sizeof(int)); + dp[0] = 0; + dp[1] = 1; + dp[2] = 1; + int max = INT_MIN, half, val, a, b; + for (int i = 3; i <= n; i++) { + half = i / 2; + for (int j = 1; j <= half; j++) { + a = (dp[j] > j) ? dp[j] : j; + b = (dp[i - j] > (i - j)) ? dp[i - j] : (i - j); + val = a * b; + if (val > max) + max = val; + } + dp[i] = max; + } + int ans = dp[n]; + free(dp); + return ans; +} + +int main() { + printf("%d\n", integerBreak(2)); // expect: 1 (2 = 1 + 1, 1 * 1 = 1) + printf("%d\n", integerBreak(10)); // expect: 36 (10 = 3 + 3 + 4, 3 * 3 * 4) +} diff --git a/integer_break.cpp b/integer_break.cpp new file mode 100644 index 0000000..c015be2 --- /dev/null +++ b/integer_break.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + int integerBreak(int n) { + if (n <= 2) + return true; + vector<int> arrMax(n + 1, 0); + arrMax[1] = 0, arrMax[2] = 1; + for (int i = 3; i <= n; i++) + for (int j = 1; j < i; j++) + arrMax[i] = max(arrMax[i], max(j * (i - j), j * arrMax[i - j])); + return arrMax[n]; + } +}; + +int main() { + Solution obj; + cout << obj.integerBreak(2); +} diff --git a/integer_break.py b/integer_break.py new file mode 100644 index 0000000..b8d5a0f --- /dev/null +++ b/integer_break.py @@ -0,0 +1,24 @@ +# 343. Integer Break + +""" +given an integer 'n', break it into the sum of 'k' positive integers, where +'k >= 2' and maximise the product of those integers. return the maximum +product you can get +""" + + +class Solution(object): + def integerBreak(self, n): + case = [0, 0, 1, 2, 4, 6, 9] + if n < 7: + return case[n] + dp = case + [0] * (n - 6) + for i in range(7, n + 1): + dp[i] = 3 * dp[i - 3] + return dp[-1] + + +if __name__ == "__main__": + obj = Solution() + print(obj.integerBreak(2)) # expect: 1 + print(obj.integerBreak(10)) # expect: 36 diff --git a/interleaving_string.c b/interleaving_string.c new file mode 100644 index 0000000..2d93759 --- /dev/null +++ b/interleaving_string.c @@ -0,0 +1,63 @@ +// 97. Interleaving String +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given strings 's1', 's2', 's3', find whether 's3' is formed by an + interleaving of 's1' and 's2'. an interleaving of two strings 's' and 't' isa + configuration where 's' and 't' are divided into 'n' and 'm' substrings + respectively, such that + s = s1 + s2 + ... + sn + t = t1 + t2 + ... + tm + |n - m| <= 1 + The interleaving is s1 + t1 + s2 + t2 + s3 + t3 + ... or t1 + s1 + t2 + s2 + + t3 + s3 + ... +*/ + +bool isInterleave(char *s1, char *s2, char *s3) { + int n1 = strlen(s1), n2 = strlen(s2), n3 = strlen(s3); + if (n1 + n2 != n3) + return false; + if (!n1) { + if (!strcmp(s2, s3)) + return true; + else + return false; + } + if (!n2) { + if (!strcmp(s1, s3)) + return true; + else + return false; + } + if (s3[n3 - 1] != s1[n1 - 1] && s3[n3 - 1] != s2[n2 - 1]) + return false; + if (s3[0] != s1[0] && s3[0] != s2[0]) + return false; + bool **dp = malloc((n1 + 1) * sizeof(bool *)); + for (int i = 0; i <= n1; i++) + dp[i] = calloc(n2 + 1, sizeof(bool)); + dp[0][0] = true; + for (int i = 1; i <= n1; i++) + dp[i][0] = (dp[i - 1][0] == true && (s1[i - 1] == s3[i - 1])); + for (int i = 1; i <= n2; i++) + dp[0][i] = (dp[0][i - 1] == true && (s2[i - 1] == s3[i - 1])); + for (int i = 1; i <= n1; i++) { + for (int j = 1; j <= n2; j++) { + if ((s1[i - 1] == s3[i + j - 1]) && dp[i - 1][j] == true) + dp[i][j] = true; + else if ((s2[j - 1] == s3[i + j - 1]) && dp[i][j - 1] == true) + dp[i][j] = true; + } + } + return dp[n1][n2]; +} + +int main() { + char s11[] = {"aabcc"}, s21[] = {"dbbca"}, s31[] = {"aadbbcbcac"}; + char s12[] = {"aabcc"}, s22[] = {"dbbca"}, s32[] = {"aadbbbaccc"}; + printf("%d\n", isInterleave(s11, s21, s31)); // expect: 1 + printf("%d\n", isInterleave(s12, s22, s32)); // expect: 0 +} diff --git a/interleaving_string.cpp b/interleaving_string.cpp new file mode 100644 index 0000000..ed2a5b9 --- /dev/null +++ b/interleaving_string.cpp @@ -0,0 +1,39 @@ +#include "leetcode.h" + +class Solution { +public: + bool isInterleave(string s1, string s2, string s3) { + memset(t, -1, sizeof(t)); + m = s1.size(); + n = s2.size(); + N = s3.size(); + if (m + n != N) + return false; + return helper(s1, s2, s3, 0, 0); + } + +private: + int m, n, N; + int t[101][101]; + bool helper(string s1, string s2, string s3, int i, int j) { + if (i >= m && j >= n && i + j >= N) + return true; + if (i + j >= N) + return false; + if (t[i][j] != -1) + return t[i][j]; + return t[i][j] = ((s1[i] == s3[i + j] && helper(s1, s2, s3, i + 1, j)) || + (s2[j] == s3[i + j] && helper(s1, s2, s3, i, j + 1))); + } +}; + +int main() { + Solution obj; + string s1 = "aabcc"; + string s2 = "dbbca"; + string s3 = "aadbbcbcac"; + if (obj.isInterleave(s1, s2, s3)) + cout << "true"; + else + cout << "false"; +} diff --git a/intersection_2_array.c b/intersection_2_array.c new file mode 100644 index 0000000..d4074e1 --- /dev/null +++ b/intersection_2_array.c @@ -0,0 +1,53 @@ +// 349. Intersection of Two Arrays +#include "leetcode.h" + +/* + * given two integer arrays 'nums1' and 'nums2' return an array of their + * intersection. each element in the result must be unique and you may return + * the result in any order. + */ + +typedef struct { + int key; + bool intersect; + UT_hash_handle hh; +} map; + +int *intersection(int *nums1, int nums1Size, int *nums2, int nums2Size, + int *returnSize) { + map *m = NULL, *element, *tmp; + int *ans = malloc(*returnSize * sizeof(int)), len = 0; + *returnSize = nums1Size < nums2Size ? nums1Size : nums2Size; + for (int i = 0; i < nums1Size; i++) { + element = malloc(sizeof(map)); + element->key = nums1[i]; + element->intersect = 0; + HASH_ADD_INT(map, key, element); + } + for (int i = 0; i < nums2Size; i++) { + element = NULL; + HASH_FIND_INT(map, &nums2[i], element); + if (element) + element->intersect = 1; + } + HASH_ITER(hh, map, element, tmp) { + if (element->intersect) + ans[len++] = element->key; + } + *returnSize = len; + return realloc(ans, sizeof(int) * len); +} + +int main() { + int n11[] = {1, 2, 2, 1}, n21[] = {2, 2}, n12[] = {4, 9, 5}, + n22[] = {9, 4, 9, 8, 4}; + int rs1[] = {}, rs2[] = {}; + int *i1 = intersection(n11, ARRAY_SIZE(n11), n21, ARRAY_SIZE(n21), rs1); + int *i2 = intersection(n12, ARRAY_SIZE(n12), n22, ARRAY_SIZE(n22), rs2); + for (int i = 0; i < 1; i++) + printf("%d ", i1[i]); // expect: 2 + printf("\n"); + for (int i = 0; i < 2; i++) + printf("%d ", i2[i]); // expect: 9 4 + printf("\n"); +} diff --git a/intersection_2_array.py b/intersection_2_array.py new file mode 100644 index 0000000..9c884bd --- /dev/null +++ b/intersection_2_array.py @@ -0,0 +1,23 @@ +# 349. Intersection of Two Arrays + +""" +given two integer arrays 'nums1' and 'nums2' return an array of their +intersection. each element in the result must be unique and you may return +the result in any order. +""" + + +class Solution(object): + def intersection(self, nums1, nums2): + """ + :type nums1: List[int] + :type nums2: List[int] + :rtype: List[int] + """ + return list(set(nums1).intersection(set(nums2))) + + +if __name__ == "__main__": + obj = Solution() + print(obj.intersection(nums1=[1, 2, 2, 1], nums2=[2, 2])) + print(obj.intersection(nums1=[4, 9, 5], nums2=[9, 4, 9, 8, 4])) diff --git a/intersection_2_linked_list.cpp b/intersection_2_linked_list.cpp new file mode 100644 index 0000000..7477734 --- /dev/null +++ b/intersection_2_linked_list.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { + ListNode *p1 = headA; + ListNode *p2 = headB; + if (p1 == NULL || p2 == NULL) + return NULL; + while (p1 != NULL && p2 != NULL && p1 != p2) { + p1 = p1->next; + p2 = p2->next; + if (p1 == p2) + return p1; + if (p1 == NULL) + p1 = headB; + if (p2 == NULL) + p2 = headA; + } + return p1; + } +}; + +int main() {} diff --git a/intervals_between_identical_element.c b/intervals_between_identical_element.c new file mode 100644 index 0000000..3a3b4d6 --- /dev/null +++ b/intervals_between_identical_element.c @@ -0,0 +1,87 @@ +// 2121. Intervals Between Identical Elements +#include "leetcode.h" + +/* + * given a 0-indexed array of 'n' integers 'arr'. the interval between two + * elements in 'arr' is defined as the absolute difference between their + * indices. more formally, the interval between 'arr[i]' and 'arr[j]' is |i - + * j|. return an array intervals of length 'n' where 'intervals[i]' is the sum + * of the intervals between 'arr[i]' and each element in 'arr' with the same + * value as 'arr[i]'. + */ + +typedef struct { + int value; + uint64_t idx_sum; + int idx_max; + int idx_cnt; + int *idx; +} node; + +typedef struct { + int size; + node *n; +} hash; + +node *hash_find(hash *h, int v) { + int idx = v % h->size; + for (int i = 0; i < h->size; i++) { + int curr_idx = (idx + i) % h->size; + node *curr = &h->n[curr_idx]; + if (!curr->idx_cnt || curr->value == v) + return curr; + } + return NULL; +} + +long long *getDistances(int *arr, int arrSize, int *returnSize) { + long long *ans = calloc(arrSize, sizeof(long long)); + hash h = {0, NULL}; + h.size = arrSize * 2; + h.n = calloc(h.size, sizeof(node)); + for (int i = 0; i < arrSize; i++) { + node *curr = hash_find(&h, arr[i]); + if (!curr->idx_cnt) { + curr->value = arr[i]; + curr->idx_max = 10; + curr->idx = calloc(curr->idx_max, sizeof(int)); + } + if (curr->idx_cnt == curr->idx_max) { + curr->idx_max *= 2; + curr->idx = realloc(curr->idx, curr->idx_max * sizeof(int)); + } + curr->idx[curr->idx_cnt++] = i; + curr->idx_sum += i; + } + for (int i = 0; i < h.size; i++) { + node *curr = &h.n[i]; + if (curr->idx_cnt) { + uint64_t pre_sum = 0, post_sum = curr->idx_sum; + for (int j = 0; j < curr->idx_cnt; j++) { + uint64_t curr_idx = curr->idx[j]; + post_sum -= curr_idx; + ans[curr_idx] = (j * curr_idx - pre_sum) + + (post_sum - (curr->idx_cnt - j - 1) * curr_idx); + pre_sum += curr_idx; + } + free(curr->idx); + } + } + free(h.n); + *returnSize = arrSize; + return ans; +} + +int main() { + int a1[] = {2, 1, 3, 1, 2, 3, 3}, a2[] = {10, 5, 10, 10}; + int rs1 = 0, rs2 = 0; + long long *gd1 = getDistances(a1, ARRAY_SIZE(a1), &rs1); + long long *gd2 = getDistances(a2, ARRAY_SIZE(a2), &rs2); + for (int i = 0; i < ARRAY_SIZE(a1); i++) + printf("%lld ", gd1[i]); // expect: [4,2,7,2,4,4,5] + printf("\n"); + for (int i = 0; i < ARRAY_SIZE(a2); i++) + printf("%lld ", gd2[i]); // expect: [5,0,3,4] + printf("\n"); + free(gd1), free(gd2); +} diff --git a/intervals_between_identical_element.py b/intervals_between_identical_element.py new file mode 100644 index 0000000..4fe7175 --- /dev/null +++ b/intervals_between_identical_element.py @@ -0,0 +1,39 @@ +# 2121. Intervals Between Identical Elements + +""" +given a 0-indexed array of 'n' integers 'arr'. the interval between two +elements in 'arr' is defined as the absolute difference between their +indices. more formally, the interval between 'arr[i]' and 'arr[j]' is |i - +j|. return an array intervals of length 'n' where 'intervals[i]' is the sum +of the intervals between 'arr[i]' and each element in 'arr' with the same +value as 'arr[i]'. +""" + + +class Solution(object): + def getDistances(self, arr): + """ + :type arr: List[int] + :rtype: List[int] + """ + m, ans = {}, [0] * len(arr) + for i, v in enumerate(arr): + if v not in m: + m[v] = list() + m[v].append(i) + for i in m: + l = m[i] + pre = [0] * (len(l) + 1) + for j in range(len(l)): + pre[j + 1] = pre[j] + l[j] + for j, v in enumerate(l): + ans[v] = (v * (j + 1) - pre[j + 1]) + ( + (pre[len(l)] - pre[j]) - v * (len(l) - (i)) + ) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.getDistances(arr=[2, 1, 3, 1, 2, 3, 3])) + print(obj.getDistances(arr=[10, 5, 10, 10])) diff --git a/invert_binary_tree.c b/invert_binary_tree.c new file mode 100644 index 0000000..e40aaa7 --- /dev/null +++ b/invert_binary_tree.c @@ -0,0 +1,21 @@ +// 226. Invert Binary Tree +// given 'root' of binary tree, invert the tree and return its root +#include <stddef.h> + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +struct TreeNode *invertTree(struct TreeNode *root) { + struct TreeNode *tmp; + if (root == NULL) + return NULL; + tmp = root->left; + root->left = root->right; + root->right = tmp; + invertTree(root->left); + invertTree(root->right); + return root; +} diff --git a/invert_binary_tree.cpp b/invert_binary_tree.cpp new file mode 100644 index 0000000..e8f0585 --- /dev/null +++ b/invert_binary_tree.cpp @@ -0,0 +1,26 @@ +// 226. Invert Binary Tree +#include "leetcode.h" + +// given 'root' of binary tree, invert the tree and return its root + +class Solution { +public: + TreeNode *invertTree(TreeNode *root) { + if (root == nullptr) + return root; + queue<TreeNode *> q; + q.push(root); + while (!q.empty()) { + TreeNode *node = q.front(); + q.pop(); + if (node->left != nullptr) + q.push(node->left); + if (node->right != nullptr) + q.push(node->right); + TreeNode *tmp = node->left; + node->left = node->right; + node->right = tmp; + } + return root; + } +}; @@ -0,0 +1,109 @@ +// 502. IPO +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * suppose leetcode will start its ipo soon. in order to sell a good price of + * its shares to venture capital, leetcode woule like to work on some projects + * to increase its capital before the ipo. since it has limited resources, it + * can only finish at most k distinct projects before the ipo. maximise capital + * after finishing at most 'k' distinct projects. given 'n' projects where the + * i'th project has a pure profit 'profits[i]' and min capital of 'capital[i]' + * is needed to start it. + */ + +typedef struct heap_s { + int capacity; + int size; + int **arr; +} heap_t; + +heap_t *init(int); +void insert(heap_t *, int, int); +int *top(heap_t *); +void pop(heap_t *); +bool empty(heap_t *); + +int undo_cmp(void **a, void **b) { return (*(int **)a)[1] - (*(int **)b)[1]; } + +int findMaximizedCapital(int k, int w, int *profits, int profitsSize, + int *capital, int capitalSize) { + heap_t *doable = init(profitsSize); + int **undoable = NULL; + int i, undoableSize = 0; + for (int i = 0; i < profitsSize; i++) { + if (profits[i] <= 0) + continue; + if (capital[i] <= w) + insert(doable, profits[i], capital[i]); + else { + undoable = (int **)realloc(undoable, sizeof(int *) * (++undoableSize)); + int *item = (int *)malloc(sizeof(int) * 2); + item[0] = profits[i]; + item[1] = capital[i]; + undoable[undoableSize - 1] = item; + } + } + qsort(undoable, undoableSize, sizeof(int *), undo_cmp); + i = 0; + while (!empty(doable) && k--) { + w += top(doable)[0]; + pop(doable); + while (i < undoableSize) { + if (w >= undoable[i][1]) { + insert(doable, undoable[i][0], undoable[i][1]); + i++; + } else + break; + } + } + return w; +} + +heap_t *init(int max) { + heap_t *heap = (heap_t *)malloc(sizeof(heap_t)); + heap->capacity = max; + heap->size = 0; + heap->arr = (int **)malloc(sizeof(int *) * (max + 1)); + return heap; +} + +bool empty(heap_t *heap) { return heap->size == 0; } + +int *top(heap_t *heap) { return heap->arr[1]; } + +bool cmp(int *a, int *b) { return a[0] == b[0] ? a[1] < b[1] : a[0] > b[0]; } + +void swap(int **a, int i, int j) { + int *tmp = a[i]; + a[i] = a[j]; + a[j] = tmp; +} + +void insert(heap_t *heap, int val, int len) { + int *node = (int *)malloc(sizeof(int) * 2); + node[0] = val; + node[1] = len; + heap->arr[++heap->size] = node; + for (int i = heap->size; i > 1 && cmp(heap->arr[i], heap->arr[i / 2]); i /= 2) + swap(heap->arr, i, i / 2); +} + +void pop(heap_t *heap) { + heap->arr[1] = heap->arr[heap->size--]; + for (int i = 1; i * 2 <= heap->size;) { + int child = cmp(heap->arr[i * 2], heap->arr[i * 2 + 1]) ? i * 2 : i * 2 + 1; + if (cmp(heap->arr[child], heap->arr[i])) { + swap(heap->arr, child, i); + i = child; + } else + break; + } +} + +int main() { + int profits[] = {1, 2, 3}, c1[] = {0, 1, 1}, c2[] = {0, 1, 2}; + printf("%d\n", findMaximizedCapital(2, 0, profits, 3, c1, 3)); // expect: 4 + printf("%d\n", findMaximizedCapital(3, 0, profits, 3, c2, 3)); // expect: 6 +} @@ -0,0 +1,52 @@ +// 502. IPO +#include "leetcode.h" + +/* + * suppose leetcode will start its ipo soon. in order to sell a good price of + * its shares to venture capital, leetcode woule like to work on some projects + * to increase its capital before the ipo. since it has limited resources, it + * can only finish at most k distinct projects before the ipo. maximise capital + * after finishing at most 'k' distinct projects. given 'n' projects where the + * i'th project has a pure profit 'profits[i]' and min capital of 'capital[i]' + * is needed to start it. + */ + +class Solution { +public: + int findMaximizedCapital(int k, int w, vector<int> &profits, + vector<int> &capital) { + priority_queue<int> pq; + int x = 0; + vector<pair<int, int>> vp; + for (int i = 0; i < profits.size(); i++) + vp.push_back({capital[i], profits[i]}); + sort(vp.begin(), vp.end()); + while (x < vp.size() && k) { + if (w >= vp[x].first) { + pq.push(vp[x].second); + x++; + } else { + if (pq.empty()) + return w; + else { + w += pq.top(); + pq.pop(); + k--; + } + } + } + while (k-- && !pq.empty()) { + w += pq.top(); + pq.pop(); + } + return w; + } +}; + +int main() { + Solution obj; + vector<int> profits = {1, 2, 3}; + vector<int> c1 = {0, 1, 1}, c2 = {0, 1, 2}; + cout << obj.findMaximizedCapital(2, 0, profits, c1) << endl; // expect: 4 + cout << obj.findMaximizedCapital(3, 0, profits, c2) << endl; // expect: 6 +} diff --git a/is_graph_biparite.c b/is_graph_biparite.c new file mode 100644 index 0000000..139625e --- /dev/null +++ b/is_graph_biparite.c @@ -0,0 +1,79 @@ +// 785. Is Graph Bipartite? +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * there is an undirected graph with 'n' nodes, where each node is numbered + * between 0 and 'n - 1'. you are given a 2d array 'graph' where 'graph[u]' is + * an array of nodes that node 'u' is adjacent to. more formally, for each 'v' + * in 'graph[u]', there is an undirected edge between node 'u' and node 'v'. the + * graph has the following properties: + * - there are no self-edges ('graph[u]' does not contain 'u') + * - there are no parallel edges ('graph[u]' does not contain duplicate values) + * - if 'v' is in 'graph[u]', then 'u' is in 'graph[v]' (the graph is + * undirected) + * - the graph may not be connected, meaning there may be two nodes 'u' and 'v' + * such that there is no path between them a graph is bipartite if the nodes can + * be partitioned into two independent sets 'A' and 'B' such that every edge in + * the graph connects a node in set 'A' and a node in set 'B'. return true if + * and only if the graph is bipartite. + */ + +bool dfs(int **graph, int graph_size, int *graph_col_size, int *queue, + int begin, int end, int *node, bool *paint) { + int _end = end; + for (int i = begin; i < end; i++) { + int pos = queue[i]; + int colour = node[pos] ? 2 : 1; + for (int j = 0; j < graph_col_size[pos]; j++) { + int itr = graph[pos][j]; + if (node[itr] == node[pos]) + return false; + else if (!paint[itr]) { + node[itr] = colour; + paint[itr] = true; + queue[_end] = itr; + _end++; + } + } + if (!dfs(graph, graph_size, graph_col_size, queue, end, _end, node, paint)) + return false; + } + return true; +} + +bool isBipartite(int **graph, int graph_size, int *graph_col_size) { + int *node = calloc(graph_size, sizeof(int)); + bool *paint = calloc(graph_size, sizeof(int)); + int *queue = malloc(graph_size * sizeof(int)); + int idx = 0; + for (int i = 0; i < graph_size; i++) { + if (!paint[i]) { + node[i] = 1; + paint[i] = true; + for (int j = 0; j < graph_col_size[i]; j++) { + int itr = graph[i][j]; + if (node[itr] == node[i]) + return false; + else if (!paint[itr]) { + node[itr] = 2; + paint[itr] = true; + queue[idx] = itr; + idx++; + } + } + if (!dfs(graph, graph_size, graph_col_size, queue, 0, idx, node, paint)) + return false; + } + } + return true; +} + +int main() { + int g1[][4] = {{1, 2, 3}, {0, 2}, {0, 1, 3}, {0, 2}}; + int g2[][4] = {{1, 3}, {0, 2}, {1, 3}, {0, 2}}; + int gcs[] = {}; + printf("%d\n", isBipartite(g1, 5, gcs)); // expect: 0 + printf("%d\n", isBipartite(g2, 5, gcs)); // expect: 1 +} diff --git a/is_graph_biparite.cpp b/is_graph_biparite.cpp new file mode 100644 index 0000000..3f2f853 --- /dev/null +++ b/is_graph_biparite.cpp @@ -0,0 +1,52 @@ +// 785. Is Graph Bipartite? +#include "leetcode.h" + +/* + * there is an undirected graph with 'n' nodes, where each node is numbered + * between 0 and 'n - 1'. you are given a 2d array 'graph' where 'graph[u]' is + * an array of nodes that node 'u' is adjacent to. more formally, for each 'v' + * in 'graph[u]', there is an undirected edge between node 'u' and node 'v'. the + * graph has the following properties: + * - there are no self-edges ('graph[u]' does not contain 'u') + * - there are no parallel edges ('graph[u]' does not contain duplicate values) + * - if 'v' is in 'graph[u]', then 'u' is in 'graph[v]' (the graph is + * undirected) + * - the graph may not be connected, meaning there may be two nodes 'u' and 'v' + * such that there is no path between them a graph is bipartite if the nodes can + * be partitioned into two independent sets 'A' and 'B' such that every edge in + * the graph connects a node in set 'A' and a node in set 'B'. return true if + * and only if the graph is bipartite. + */ + +class Solution { +public: + bool isBipartite(vvd(int) & graph) { + int n = graph.size(); + vector<int> colour(n); + queue<int> q; + for (int i = 0; i < n; i++) { + if (colour[i]) + continue; + colour[i] = 1; + for (q.push(i); !q.empty(); q.pop()) { + int curr = q.front(); + for (int neighbour : graph[curr]) { + if (!colour[neighbour]) { + colour[neighbour] = -colour[curr]; + q.push(neighbour); + } else if (colour[neighbour] == colour[curr]) + return false; + } + } + } + return true; + } +}; + +int main() { + Solution obj; + vvd(int) g1 = {{1, 2, 3}, {0, 2}, {0, 1, 3}, {0, 2}}; + vvd(int) g2 = {{1, 3}, {0, 2}, {1, 3}, {0, 2}}; + printf("%d\n", obj.isBipartite(g1)); // expect: 0 + printf("%d\n", obj.isBipartite(g2)); // expect: 1 +} diff --git a/is_subseq.c b/is_subseq.c new file mode 100644 index 0000000..35ddd09 --- /dev/null +++ b/is_subseq.c @@ -0,0 +1,31 @@ +// 392. Is Subsequence +#include <stdbool.h> +#include <stdio.h> + +/* + * given two strings 's' and 't', return 'true' if 's' is a subsequnce of 't' or + * 'false' otherwise. a subsequnce of a string is a new string that is formed + * from the original string by deleting some (can be none) of the characters + * without disturbing the relative positions of the remaining characters (ie. + * "ace" is a subsequnce of "abcde", while "aec" is not). + */ + +bool isSubsequence(char *s, char *t) { + int s_idx = 0, t_idx = 0; + while (s[s_idx] != '\0') { + while ((t[t_idx] != '\0') & (t[t_idx] != s[s_idx])) + t_idx++; + if (t[t_idx] == '\0') + return false; + t_idx++; + s_idx++; + } + return true; +} + +int main() { + char s1[] = {"abc"}, s2[] = {"axc"}; + char t1[] = {"ahbgdc"}, t2[] = {"ahbgdc"}; + printf("%d\n", isSubsequence(s1, t1)); // expect: 1 + printf("%d\n", isSubsequence(s2, t2)); // expect: 0 +} diff --git a/is_subseq.py b/is_subseq.py new file mode 100644 index 0000000..cb9fbde --- /dev/null +++ b/is_subseq.py @@ -0,0 +1,30 @@ +# 392. Is Subsequence + +""" +given two strings 's' and 't', return 'true' if 's' is a subsequnce of 't' or +'false' otherwise. a subsequnce of a string is a new string that is formed +from the original string by deleting some (can be none) of the characters +without disturbing the relative positions of the remaining characters (ie. +"ace" is a subsequnce of "abcde", while "aec" is not). +""" + + +class Solution(object): + def isSubsequence(self, s, t): + if len(s) > len(t): + return False + if len(s) == 0: + return True + subsequnce = 0 + for i in range(0, len(t)): + if subsequnce <= len(s) - 1: + # print(s[subsequnce]) + if s[subsequnce] == t[i]: + subsequnce += 1 + return subsequnce == len(s) + + +if __name__ == "__main__": + obj = Solution() + print(obj.isSubsequence("abc", "ahbgdc")) # expect: True + print(obj.isSubsequence("axc", "ahbgdc")) # expect: False diff --git a/island_perimeter.c b/island_perimeter.c new file mode 100644 index 0000000..8e898ca --- /dev/null +++ b/island_perimeter.c @@ -0,0 +1,35 @@ +//463. Island Perimeter +#include "leetcode.h" + +/* + * given a 'row * col' grid representing a map where 'grid[i][j] = 1' + * represents land and 'grid[i][j] = 0' represents water. grid cells are + * connected horizontally/vertically (not diagonally). the 'gird' is completely + * surrounded by water, and there is exactly one island. the island does not + * have lakes meaning the water inside is not connected to the water around the + * island. one cell is a square with side length 1. the grid is rectangular + * width and height don't exceed 100. determine the perimeter of the island. + */ + +int edge_sum(int **grid, int row, int col, int grid_row_size, + int grid_col_size) { + int total = 0; + if (row - 1 < 0 || !grid[row - 1][col]) + total++; + if (row + 1 == grid_row_size || !grid[row + 1][col]) + total++; + if (col - 1 < 0 || !grid[row][col - 1]) + total++; + if (col + 1 == grid_col_size || !grid[row][col + 1]) + total++; + return total; +} + +int islandPerimeter(int **grid, int gridSize, int *gridColSize) { + int ans = 0; + for (int i = 0; i < gridSize; ++i) + for (int j = 0; j < *gridColSize; ++j) + if (grid[i][j]) + ans += edge_sum(grid, i, j, gridSize, *gridColSize); + return ans; +} diff --git a/island_perimeter.py b/island_perimeter.py new file mode 100644 index 0000000..e7c80e1 --- /dev/null +++ b/island_perimeter.py @@ -0,0 +1,43 @@ +# 463. Island Perimeter + +""" +given a 'row col' grid representing a map where 'grid[i][j] = 1' +represents land and 'grid[i][j] = 0' represents water. grid cells are +connected horizontally/vertically (not diagonally). the 'gird' is completely +surrounded by water, and there is exactly one island. the island does not +have lakes meaning the water inside is not connected to the water around the +island. one cell is a square with side length 1. the grid is rectangular +width and height don't exceed 100. determine the perimeter of the island. +""" + + +class Solution(object): + def islandPerimeter(self, grid): + """ + :type grid: List[List[int]] + :rtype: int + """ + m, n, ans = len(grid), len(grid[0]), 0 + for i in range(m): + for j in range(n): + ans += 4 * grid[i][j] + if i > 0: + ans -= grid[i][j] * grid[i - 1][j] + if i < m - 1: + ans -= grid[i][j] * grid[i + 1][j] + if j > 0: + ans -= grid[i][j] * grid[i][j - 1] + if j < n - 1: + ans -= grid[i][j] * grid[i][j + 1] + return ans + + +if __name__ == "__main__": + obj = Solution() + print( + obj.islandPerimeter( + grid=[[0, 1, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0], [1, 1, 0, 0]] + ) + ) + print(obj.islandPerimeter(grid=[[1]])) + print(obj.islandPerimeter(grid=[[1, 0]])) diff --git a/isomorphic_strings.c b/isomorphic_strings.c new file mode 100644 index 0000000..e869681 --- /dev/null +++ b/isomorphic_strings.c @@ -0,0 +1,29 @@ +// 205. Isomorphic Strings +#include "leetcode.h" + +/* + * given two strings 's' and 't', determine if they are isomorphic. two strings + * 's' and 't' are isomorphic if the characters in 's' can be replaced to get + * 't'. all occurences of a character must be replaced with another character + * while presevering the order of characters. no two characters may map to the + * same character, but a character may map to itself. + */ + +bool isIsomorphic(char *s, char *t) { + int s1[256] = {0}, t1[256] = {0}, n = strlen(s); + for (int i = 0; i < n; i++) { + if (s1[(int)s[i]] != t1[(int)t[i]]) + return 0; + s1[(int)s[i]] = i + 1; + t1[(int)t[i]] = i + 1; + } + return 1; +} + +int main() { + char *s1 = "egg", *t1 = "add", *s2 = "foo", *t2 = "bar", *s3 = "paper", + *t3 = "title"; + printf("%d\n", isIsomorphic(s1, t1)); // expect: 1 + printf("%d\n", isIsomorphic(s2, t2)); // expect: 0 + printf("%d\n", isIsomorphic(s3, t3)); // expect: 1 +} diff --git a/isomorphic_strings.py b/isomorphic_strings.py new file mode 100644 index 0000000..68178a1 --- /dev/null +++ b/isomorphic_strings.py @@ -0,0 +1,32 @@ +# 205. Isomorphic Strings + +""" +given two strings 's' and 't', determine if they are isomorphic. two strings +'s' and 't' are isomorphic if the characters in 's' can be replaced to get +'t'. all occurences of a character must be replaced with another character +while presevering the order of characters. no two characters may map to the +same character, but a character may map to itself. +""" + + +class Solution(object): + def isIsomorphic(self, s, t): + """ + :type s: str + :type t: str + :rtype: bool + """ + s1, t1 = [0 for _ in range(256)], [0 for _ in range(256)] + for i in range(len(s)): + if s1[ord(s[i])] != t1[ord(t[i])]: + return False + s1[ord(s[i])] = i + 1 + t1[ord(t[i])] = i + 1 + return True + + +if __name__ == "__main__": + obj = Solution() + print(obj.isIsomorphic("egg", "add")) + print(obj.isIsomorphic("foo", "bar")) + print(obj.isIsomorphic("paper", "title")) diff --git a/jump_game.cpp b/jump_game.cpp new file mode 100644 index 0000000..153d9aa --- /dev/null +++ b/jump_game.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + bool canJump(vector<int> &nums) { + int minJump = 0; + for (int i = nums.size() - 2; i >= 0; i--) { + minJump++; + if (nums[i] >= minJump) + minJump = 0; + } + if (minJump == 0) + return true; + else + return false; + } +}; + +int main() { + Solution obj; + vector<int> nums1 = {2, 3, 1, 1, 4}, nums2 = {3, 2, 1, 0, 4}; + testBool(obj.canJump(nums1)); // true + testBool(obj.canJump(nums2)); // false +} diff --git a/jump_game.rs b/jump_game.rs new file mode 100644 index 0000000..e7f36b0 --- /dev/null +++ b/jump_game.rs @@ -0,0 +1,18 @@ +struct Solution; + +impl Solution { + pub fn can_jump(nums: Vec<i32>) -> bool { + let mut n = 1; + for i in (0..nums.len() - 1).rev() { + n = if nums[i] < n { n + 1 } else { 1 }; + } + n == 1 + } +} + +fn main() { + let nums1 = vec![2,3,1,1,4]; + let nums2 = vec![3,2,1,0,4]; + println!("{}", Solution::can_jump(nums1)); + println!("{}", Solution::can_jump(nums2)); +} diff --git a/jump_game2.c b/jump_game2.c new file mode 100644 index 0000000..0582bc2 --- /dev/null +++ b/jump_game2.c @@ -0,0 +1,34 @@ +// 45. Jump Game II +#include <stdio.h> + +/* + * you are given 0-indexed array of integers 'nums' of length + * 'n'. you are initially positioned at 'nums[0]' each element + * 'nums[i]' represents the maximum length of forward jump from + * from index 'i'. in other words, you can jump to any + * 'nums[i + j]' where 0 <= j <= nums[i] and i + j < n + * return the minimum number of jumps to reach 'nums[n - 1]'. + */ + +int jump(int *nums, int numsSize) { + if (numsSize < 2) + return 0; + if (nums[0] >= numsSize - 1) + return 1; + int cnt = 0, max = 0, min = 0; + for (int i = 0; i < numsSize - 1; i++) { + max = nums[i] + i > max ? nums[i] + i : max; + if (i == min) { + min = max; + cnt++; + } + } + return cnt; +} + +int main() { + int nums1[] = {2, 3, 1, 1, 14}, ns1 = 5; + int nums2[] = {2, 3, 0, 1, 4}, ns2 = 5; + printf("%d\n", jump(nums1, ns1)); // expect: 2 + printf("%d\n", jump(nums2, ns2)); // expect: 2 +} diff --git a/jump_game2.cpp b/jump_game2.cpp new file mode 100644 index 0000000..23d2b35 --- /dev/null +++ b/jump_game2.cpp @@ -0,0 +1,16 @@ +#include "leetcode.h" + +class Solution { +public: + int jump(vector<int> &nums) { + int n = nums.size(); + vector<int> dp(n, 10001); + dp[n - 1] = 0; + for (int i = n - 2; i >= 0; i--) + for (int jumpLen = 1; jumpLen <= nums[i]; jumpLen++) + dp[i] = min(dp[i], 1 + dp[min(n - 1, i + jumpLen)]); + return dp[0]; + } +}; + +int main() {} diff --git a/jump_game3.cpp b/jump_game3.cpp new file mode 100644 index 0000000..03f7d37 --- /dev/null +++ b/jump_game3.cpp @@ -0,0 +1,27 @@ +#include "leetcode.h" + +class Solution { +public: + bool canReach(vector<int> &arr, int start) { + vector<bool> visited(arr.size(), false); + return dfs(arr, start, visited); + } + +private: + bool dfs(vector<int> &arr, int curr, vector<bool> &k) { + if ((curr < 0) || (curr >= arr.size()) || k[curr]) + return false; + if (arr[curr] == 0) + return true; + k[curr] = true; + return dfs(arr, curr + arr[curr], k) || dfs(arr, curr - arr[curr], k); + } +}; + +int main() { + Solution obj; + vector<int> arr1 = {4, 2, 3, 0, 3, 1, 2}, arr2 = {3, 0, 2, 1, 2}; + testBool(obj.canReach(arr1, 5)); // true + testBool(obj.canReach(arr1, 0)); // true + testBool(obj.canReach(arr2, 2)); // false +} diff --git a/jump_game3.rs b/jump_game3.rs new file mode 100644 index 0000000..a973fad --- /dev/null +++ b/jump_game3.rs @@ -0,0 +1,35 @@ +use std::collections::VecDeque; +struct Solution; + +impl Solution { + pub fn can_reach(arr: Vec<i32>, start: i32) -> bool { + let mut arr = arr; + let mut vd: VecDeque<i32> = VecDeque::with_capacity(arr.len()); + vd.push_back(start); + while let Some(front) = vd.pop_front() { + match arr[front as usize].cmp(&0) { + std::cmp::Ordering::Less => continue, + std::cmp::Ordering::Equal => return true, + std::cmp::Ordering::Greater => { + if front - arr[front as usize] >= 0 { + vd.push_back(front - arr[front as usize]); + } + if front + arr[front as usize] < arr.len() as i32 { + vd.push_back(front + arr[front as usize]); + } + arr[front as usize] = -1; + } + } + } + false + } +} + +fn main() { + let arr1 = vec![4,2,3,0,3,1,2]; + let arr2 = vec![4,2,3,0,3,1,2]; + let arr3 = vec![3,0,2,1,2]; + println!("{}", Solution::can_reach(arr1, 5)); //true + println!("{}", Solution::can_reach(arr2, 0)); //true + println!("{}", Solution::can_reach(arr3, 2)); //false +} diff --git a/jump_game4.c b/jump_game4.c new file mode 100644 index 0000000..27380b8 --- /dev/null +++ b/jump_game4.c @@ -0,0 +1,97 @@ +// 1345. Jump Game IV +#include "lib/uthash/src/uthash.h" +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given array of integers 'arr', you are initially positioned at first index of + * array. in one step, you can jump from index 'i' to index 'j'. return minimum + * number of steps to reach lat index of array. notice, you cannot jump outside + * of array at any time. + */ + +typedef struct { + int key; + struct list_node *ptr; + UT_hash_handle hh; +} node; + +typedef struct { + int val; + int *next; +} list_node; + +typedef struct { + int pos; + int step; +} status; + +int minJumps(int *arr, int arr_size) { + if (arr_size <= 1) + return 1; + status obj[arr_size]; + int visited[arr_size]; + memset(visited, 0, arr_size * sizeof(int)); + node *hash = NULL, *s; + struct list_node *tp; + for (int i = 0; i < arr_size; i++) { + HASH_FIND_INT(hash, &arr[i], s); + if (!s) { + s = (node *)calloc(1, sizeof(node)); + s->key = arr[i]; + HASH_ADD_INT(hash, key, s); + } + tp = (struct list_node *)calloc(1, sizeof(struct list_node)); + tp->val = i; + tp->next = s->ptr; + s->ptr = tp; + } + int top = 1, left = 0, pos, val; + obj[0].step = obj[0].pos = 0; + visited[0] = 1; + while (left < top) { + if (obj[left].pos == arr_size - 1) + break; + val = arr[obj[left].pos]; + HASH_FIND_INT(hash, &val, s); + if (s) { + tp = s->ptr; + while (tp) { + pos = tp->val; + if (!visited[pos]) { + visited[pos] = 1; + obj[top].step = obj[left].step + 1; + obj[top].pos = pos; + top++; + } + tp = tp->next; + } + HASH_DEL(hash, s); + } + for (int i = 0; i < 2; i++) { + pos = obj[left].pos + (i ? 1 : -1); + if (pos < 0 || pos >= arr_size) + continue; + if (visited[pos]) + continue; + obj[top].step = obj[left].step + 1; + obj[top].pos = pos; + visited[pos] = 1; + top++; + } + left++; + } + free(tp); + return obj[left].step; +} + +int main() { + int a1[] = {100, -23, -23, 404, 100, 23, 23, 23, 3, 404}; + int a2[] = {7}; + int a3[] = {7, 6, 9, 6, 9, 6, 9, 7}; + printf("%d\n", minJumps(a1, sizeof(a1) / sizeof(a1[0]))); // expect: 3 + printf("%d\n", minJumps(a2, sizeof(a2) / sizeof(a2[0]))); // expect: 0 + printf("%d\n", minJumps(a3, sizeof(a3) / sizeof(a3[0]))); // expect: 1 +} diff --git a/jump_game4.cpp b/jump_game4.cpp new file mode 100644 index 0000000..8496d94 --- /dev/null +++ b/jump_game4.cpp @@ -0,0 +1,52 @@ +// 1345. Jump Game IV +#include "leetcode.h" + +/* + * given array of integers 'arr', you are initially positioned at first index of + * array. in one step, you can jump from index 'i' to index 'j'. return minimum + * number of steps to reach lat index of array. notice, you cannot jump outside + * of array at any time. + */ + +class Solution { +public: + int minJumps(vector<int> &arr) { + int n = arr.size(), step = 0; + unordered_map<int, vector<int>> idx_val; + for (int i = 0; i < n; i++) + idx_val[arr[i]].push_back(i); + vector<bool> visited(n); + visited[0] = true; + queue<int> q; + q.push(0); + while (!q.empty()) { + for (int size = q.size(); size > 0; --size) { + int i = q.front(); + q.pop(); + if (i == n - 1) + return step; // end of arr + vector<int> next = idx_val[arr[i]]; + next.push_back(i - 1); + next.push_back(i + 1); + for (int j : next) { + if (j >= 0 && j < n && !visited[j]) { + visited[j] = true; + q.push(j); + } + } + next.clear(); + } + step++; + } + return 0; + } +}; + +int main() { + Solution obj; + vector<int> a1 = {100, -23, -23, 404, 100, 23, 23, 23, 3, 404}; + vector<int> a2 = {7}, a3 = {7, 6, 9, 6, 9, 6, 9, 7}; + cout << obj.minJumps(a1) << endl; // expect: 3 + cout << obj.minJumps(a2) << endl; // expect: 0 + cout << obj.minJumps(a3) << endl; // expect: 1 +} diff --git a/jump_game6.cpp b/jump_game6.cpp new file mode 100644 index 0000000..81bbf05 --- /dev/null +++ b/jump_game6.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + int maxResult(vector<int> &nums, int k) { + int ans = 0; + deque<int> dq; + for (int i = nums.size() - 1; i >= 0; i--) { + ans = nums[i] + (dq.empty() ? 0 : nums[dq.front()]); + while (!dq.empty() && ans > nums[dq.back()]) + dq.pop_back(); + dq.push_back(i); + if (dq.front() >= i + k) + dq.pop_front(); + nums[i] = ans; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums = {1, -1, -2, 4, -7, 3}; + int k = 2; + cout << obj.maxResult(nums, k); +} diff --git a/k_diff_pair_array.c b/k_diff_pair_array.c new file mode 100644 index 0000000..f7a85a6 --- /dev/null +++ b/k_diff_pair_array.c @@ -0,0 +1,43 @@ +// 532. K-diff Pairs in an Array +#include "leetcode.h" + +/* + * given an array of integers 'nums' and an integer 'k', return the number of + * unique pair '(nums[i], nums[j])' where the following are true: '0 <= i, j < + * nums.len', 'i != j', and '| nums[i] - nums[j] == k'. + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +bool check(int *nums, int numsSize, int val) { + int left = 0, right = numsSize - 1, mid; + while (left <= right) { + mid = (left + right) / 2; + if (nums[mid] == val) + return 1; + if (val > nums[mid]) + left = mid + 1; + else + right = mid - 1; + } + return 0; +} + +int findPairs(int *nums, int numsSize, int k) { + qsort(nums, numsSize, sizeof(int), cmp); + int ans = 0; + for (int i = 0; i < numsSize - 1; i++) { + if (i && nums[i] == nums[i - 1]) + continue; + if (check(&nums[i + 1], numsSize - i - 1, k + nums[i])) + ans++; + } + return ans; +} + +int main() { + int n1[] = {3, 1, 4, 1, 5}, n2[] = {1, 2, 3, 4, 5}, n3[] = {1, 3, 1, 5, 4}; + printf("%d\n", findPairs(n1, ARRAY_SIZE(n1), 2)); // expect: 2 + printf("%d\n", findPairs(n2, ARRAY_SIZE(n2), 4)); // expect: 4 + printf("%d\n", findPairs(n3, ARRAY_SIZE(n3), 1)); // expect: 1 +} diff --git a/k_diff_pair_array.py b/k_diff_pair_array.py new file mode 100644 index 0000000..fb44c0f --- /dev/null +++ b/k_diff_pair_array.py @@ -0,0 +1,30 @@ +# 532. K-diff Pairs in an Array +from collections import Counter + +""" +given an array of integers 'nums' and an integer 'k', return the number of +unique pair '(nums[i], nums[j])' where the following are true: '0 <= i, j < +nums.len', 'i != j', and '| nums[i] - nums[j] == k'. +""" + + +class Solution(object): + def findPairs(self, nums, k): + """ + :type nums: List[int] + :type k: int + :rtype: int + """ + ans = 0 + c = Counter(nums) + for i in c: + if k > 0 and i + k in c or k == 0 and c[i] > 1: + ans += 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.findPairs(nums=[3, 1, 4, 1, 5], k=2)) + print(obj.findPairs(nums=[1, 2, 3, 4, 5], k=1)) + print(obj.findPairs(nums=[1, 3, 1, 5, 4], k=0)) diff --git a/k_inverse_pairs.cpp b/k_inverse_pairs.cpp new file mode 100644 index 0000000..5601d19 --- /dev/null +++ b/k_inverse_pairs.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + int kInversePairs(int n, int k) { + vector<int> dp(k + 1, 0); + int mod = 1e9 + 7; + for (int i = 1; i <= n; i++) { + vector<int> tmp(k + 1, 0); + tmp[0] = 1; + for (int j = 1; j <= k; j++) { + long long val = (dp[j] + mod - ((j - i) >= 0 ? dp[j - i] : 0)) % mod; + tmp[j] = (tmp[j - 1] + val) % mod; + } + dp = tmp; + } + return (dp[k] + mod - (k > 0 ? dp[k - 1] : 0)) % mod; + } +}; + +int main() { + Solution obj; + cout << obj.kInversePairs(3, 0); +} diff --git a/k_radius_subarr.c b/k_radius_subarr.c new file mode 100644 index 0000000..c4bce78 --- /dev/null +++ b/k_radius_subarr.c @@ -0,0 +1,65 @@ +// 2090. K Radius Subarray Averages +#include <stdio.h> +#include <stdlib.h> + +/* + * given a 0-indexed array 'nums' of 'n' integers, and an integer 'k'. the + * k-radius average for a subarray of 'nums' centered at some index 'i' with the + * radius 'k' is the average of all elements in 'nums' between the indices 'i - + * k' and 'i + k' (inclusive). if there are less than 'k' elements before or + * after the index 'i', then the k-radius average is -1. build and return 'avgs' + * of length 'n' where 'avgs[i]' is the k-radius average for the subarray + * centered at index 'i'. the average of 'x' elements is the sum of the 'x' + * elements divided by 'x', using integer division. the integer division + * truncates toward zero, which means losing its fractional part. + */ + +int *getAverages(int *nums, int nums_size, int k, int *return_size) { + int n = nums_size, d = 2 * k + 1; + int *ans = malloc(n * sizeof(int)); + *return_size = n; + long long sum = 0; + if (n < d) { + for (int i = 0; i < n; i++) + ans[i] = -1; + return ans; + } + for (int i = 0; i < k; i++) { + ans[i] = -1; + sum += nums[i]; + } + sum += nums[k]; + for (int i = k + 1; i < 2 * k + 1; i++) + sum += nums[i]; + ans[k] = sum / d; + for (int i = k + 1; i < n - k; i++) { + int d = nums[i + k] - nums[i - k - 1]; + if (!d) + ans[i] = ans[i - 1]; + else { + sum += d; + ans[i] = sum / d; + } + } + for (int i = 0; i < k; i++) + ans[n - 1 - i] = -1; + return ans; +} + +int main() { + int n1[] = {7, 4, 3, 9, 1, 8, 5, 2, 6}, ns1 = 9, k1 = 3, rs1[] = {}; + int n2[] = {100000}, ns2 = 1, k2 = 0, rs2[] = {}; + int n3[] = {8}, ns3 = 1, k3 = 100000, rs3[] = {}; + int *ga1 = getAverages(n1, ns1, k1, rs1); + int *ga2 = getAverages(n2, ns2, k2, rs2); + int *ga3 = getAverages(n3, ns3, k3, rs3); + for (int i = 0; i < ns1; i++) + printf("%d ", ga1[i]); // expect: -1,-1,-1,5,4,4,-1,-1,-1 + printf("\n"); + for (int i = 0; i < ns2; i++) + printf("%d ", ga2[i]); // expect: 100000 + printf("\n"); + for (int i = 0; i < ns3; i++) + printf("%d ", ga3[i]); // expect: -1 + printf("\n"); +} diff --git a/k_radius_subarr.cpp b/k_radius_subarr.cpp new file mode 100644 index 0000000..91184bb --- /dev/null +++ b/k_radius_subarr.cpp @@ -0,0 +1,45 @@ +// 2090. K Radius Subarray Averages +#include "leetcode.h" + +/* + * given a 0-indexed array 'nums' of 'n' integers, and an integer 'k'. the + * k-radius average for a subarray of 'nums' centered at some index 'i' with the + * radius 'k' is the average of all elements in 'nums' between the indices 'i - + * k' and 'i + k' (inclusive). if there are less than 'k' elements before or + * after the index 'i', then the k-radius average is -1. build and return 'avgs' + * of length 'n' where 'avgs[i]' is the k-radius average for the subarray + * centered at index 'i'. the average of 'x' elements is the sum of the 'x' + * elements divided by 'x', using integer division. the integer division + * truncates toward zero, which means losing its fractional part. + */ + +class Solution { +public: + vector<int> getAverages(vector<int> &nums, int k) { + vector<int> ans(nums.size(), -1); + long long sum = 0, d = k * 2 + 1; + for (int i = 0; i < nums.size(); ++i) { + sum += nums[i]; + if (i + 1 >= d) { + if (i >= d) + sum -= nums[i - d]; + ans[i - d / 2] = sum / d; + } + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {7, 4, 3, 9, 1, 8, 5, 2, 6}, n2 = {100000}, n3 = {8}; + for (auto i : obj.getAverages(n1, 3)) + printf("%d ", i); // expect: -1,-1,-1,5,4,4,-1,-1,-1 + printf("\n"); + for (auto i : obj.getAverages(n2, 0)) + printf("%d ", i); // expect: 100000 + printf("\n"); + for (auto i : obj.getAverages(n3, 100000)) + printf("%d ", i); // expect: -1 + printf("\n"); +} diff --git a/keys_and_rooms.cpp b/keys_and_rooms.cpp new file mode 100644 index 0000000..d807c7c --- /dev/null +++ b/keys_and_rooms.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class Solution { +public: + bool canVisitAllRooms(vvd(int) & rooms) { + stack<int> dfs; + dfs.push(0); + unordered_set<int> seen = {0}; + while (!dfs.empty()) { + int i = dfs.top(); + dfs.pop(); + for (int j : rooms[i]) { + if (seen.count(j) == 0) { + dfs.push(j); + seen.insert(j); + if (rooms.size() == seen.size()) + return true; + } + } + } + return rooms.size() == seen.size(); + } +}; + +int main() { + Solution obj; + vvd(int) rooms = {{1}, {2}, {3}, {}}; + if (obj.canVisitAllRooms(rooms)) + cout << "true"; + else + cout << "false"; +} diff --git a/keys_and_rooms.rs b/keys_and_rooms.rs new file mode 100644 index 0000000..678c732 --- /dev/null +++ b/keys_and_rooms.rs @@ -0,0 +1,23 @@ +struct Solution; + +impl Solution { + pub fn can_visit_all_rooms(rooms: Vec<Vec<i32>>) -> bool { + let mut unlocked = vec![false; rooms.len()]; + unlocked[0] = true; + let mut stack = vec![0]; + while let Some(next) = stack.pop() { + for &i in &rooms[next as usize] { + if !unlocked[i as usize] { + unlocked[i as usize] = true; + stack.push(i); + } + } + } + unlocked.iter().all(|&b| b) + } +} + +fn main() { + let rooms = vec![vec![1], vec![2], vec![3], vec![]]; + print!("{}", Solution::can_visit_all_rooms(rooms)); +} diff --git a/kids_max_num_candy.c b/kids_max_num_candy.c new file mode 100644 index 0000000..ea7b70d --- /dev/null +++ b/kids_max_num_candy.c @@ -0,0 +1,43 @@ +// 1431. Kids With the Greatest Number of Candies +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * there are 'n' kids with candies. you are given an integer array 'candies', + * where each 'candies[i]' represents the number of candies the i'th kid has, + * and an integer 'extra' denoting the number of extra candies that you have. + * return a boolean array 'result' of length 'n' where 'result[i]' is 1 if, + * after giving the i'th kid all the 'extra', they will have the greatest number + * of candies among all the kids, or 0 otherwise. + */ + +bool *kidsWithCandies(int *candies, int candies_size, int extra, + int *return_size) { + *return_size = candies_size; + bool *ans = (bool *)malloc(candies_size * sizeof(bool)); + int max = candies[0]; + for (int i = 1; i < candies_size; i++) + max = candies[i] > max ? candies[i] : max; + for (int i = 0; i < candies_size; i++) + ans[i] = (candies[i] + extra >= max) ? 1 : 0; + return ans; +} + +int main() { + int c1[] = {2, 3, 5, 1, 3}, cs1 = 5, e1 = 3, rs1[] = {5}; + int c2[] = {4, 2, 1, 1, 2}, cs2 = 5, e2 = 1, rs2[] = {5}; + int c3[] = {12, 1, 12}, cs3 = 3, e3 = 10, rs3[] = {3}; + bool *kwc1 = kidsWithCandies(c1, cs1, e1, rs1); + bool *kwc2 = kidsWithCandies(c2, cs2, e2, rs2); + bool *kwc3 = kidsWithCandies(c3, cs3, e3, rs3); + for (int i = 0; i < cs1; i++) + printf("%d ", kwc1[i]); // expect: 1 1 1 0 1 + printf("\n"); + for (int i = 0; i < cs2; i++) + printf("%d ", kwc2[i]); // expect: 1 0 0 0 0 + printf("\n"); + for (int i = 0; i < cs3; i++) + printf("%d ", kwc3[i]); // expect: 1 0 1 + printf("\n"); +} diff --git a/kids_max_num_candy.cpp b/kids_max_num_candy.cpp new file mode 100644 index 0000000..8be7b4c --- /dev/null +++ b/kids_max_num_candy.cpp @@ -0,0 +1,42 @@ +// 1431. Kids With the Greatest Number of Candies +#include "leetcode.h" + +/* + * there are 'n' kids with candies. you are given an integer array 'candies', + * where each 'candies[i]' represents the number of candies the i'th kid has, + * and an integer 'extra' denoting the number of extra candies that you have. + * return a boolean array 'result' of length 'n' where 'result[i]' is 1 if, + * after giving the i'th kid all the 'extra', they will have the greatest number + * of candies among all the kids, or 0 otherwise. + */ + +class Solution { +public: + vector<bool> kidsWithCandies(vector<int> &candies, int extra) { + int m = 0; + vector<bool> ans; + for (int c : candies) + m = max(m, c); + for (int c : candies) { + if (c + extra >= m) + ans.push_back(1); + else + ans.push_back(0); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> c1 = {2, 3, 5, 1, 3}, c2 = {4, 2, 1, 1, 2}, c3 = {12, 1, 12}; + for (auto i : obj.kidsWithCandies(c1, 3)) + cout << i << ' '; // expect: 1 1 1 0 1 + cout << endl; + for (auto i : obj.kidsWithCandies(c2, 1)) + cout << i << ' '; // expect: 1 0 0 0 0 + cout << endl; + for (auto i : obj.kidsWithCandies(c3, 10)) + cout << i << ' '; // expect: 1 0 1 + cout << endl; +} diff --git a/knight_dialer.c b/knight_dialer.c new file mode 100644 index 0000000..be72a6e --- /dev/null +++ b/knight_dialer.c @@ -0,0 +1,65 @@ +// 935. Knight Dialer +#include "leetcode.h" + +/* + * the chess knight has a unique movement, it may move two squares vertically + * and one square horizontally, or two squares horizontally andone square + * vertically with both forming the shape of an L. the possible movements of + * chess knights ares shown in below diagram. given an integer 'n', return how + * many distinct phone number of length 'n' we can dial. you are allowed to + * place the knight on any numeric cell initially and then you should perform 'n + * - 1' jumps to dial a number of length 'n'. all jumps should be valid jumps. + * as the answer may be very large, return answer modulo 10^9 + 7 + */ + +int knightDialer(int n) { + long int new_jump[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + long int old_jump[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + long long int numbers = 0; + int row0[] = {2, 4, 6}; + int row1[] = {2, 6, 8}; + int row2[] = {2, 7, 9}; + int row3[] = {2, 8, 4}; + int row4[] = {3, 3, 9, 0}; + int row5[] = {0}; + int row6[] = {3, 7, 0, 1}; + int row7[] = {2, 2, 6}; + int row8[] = {2, 1, 3}; + int row9[] = {2, 4, 2}; + int **dial = malloc(10 * sizeof(int *)); + dial[0] = row0; + dial[1] = row1; + dial[2] = row2; + dial[3] = row3; + dial[4] = row4; + dial[5] = row5; + dial[6] = row6; + dial[7] = row7; + dial[8] = row8; + dial[9] = row9; + if (n == 1) + return 10; + for (int i = 1; i < n; i++) { + numbers = 0; + for (int j = 0; j < 10; j++) + for (int k = 1; k < dial[j][0] + 1; k++) { + if (j == 5) + continue; + new_jump[dial[j][k]] += old_jump[j]; + new_jump[dial[j][k]] %= 1000000007LL; + } + memcpy(old_jump, new_jump, sizeof(long) * 10); + for (int j = 0; j < 10; j++) { + numbers += new_jump[j]; + new_jump[j] = 0; + } + } + free(dial); + return numbers % 1000000007LL; +} + +int main() { + printf("%d\n", knightDialer(1)); // expect: 10 + printf("%d\n", knightDialer(2)); // expect: 20 + printf("%d\n", knightDialer(3131)); // expect: 136006598 +} diff --git a/knight_dialer.py b/knight_dialer.py new file mode 100644 index 0000000..a3a2d96 --- /dev/null +++ b/knight_dialer.py @@ -0,0 +1,42 @@ +# 935. Knight Dialer + +""" +the chess knight has a unique movement, it may move two squares vertically +and one square horizontally, or two squares horizontally andone square +vertically with both forming the shape of an L. the possible movements of +chess knights ares shown in below diagram. given an integer 'n', return how +many distinct phone number of length 'n' we can dial. you are allowed to +place the knight on any numeric cell initially and then you should perform 'n +- 1' jumps to dial a number of length 'n'. all jumps should be valid jumps. +as the answer may be very large, return answer modulo 10^9 + 7 +""" + + +class Solution(object): + def knightDialer(self, n): + """ + :type n: int + :rtype: int + """ + x1 = x2 = x3 = x4 = x5 = x6 = x7 = x8 = x9 = x0 = 1 + for i in range(n - 1): + x1, x2, x3, x4, x5, x6, x7, x8, x9, x0 = ( + x6 + x8, + x7 + x9, + x4 + x8, + x3 + x9 + x0, + 0, + x1 + x7 + x0, + x2 + x6, + x1 + x3, + x2 + x4, + x4 + x6, + ) + return (x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x0) % (10**9 + 7) + + +if __name__ == "__main__": + obj = Solution() + print(obj.knightDialer(1)) # expect: 10 + print(obj.knightDialer(2)) # expect: 20 + print(obj.knightDialer(3131)) # expect: 136006598 diff --git a/knight_probability_chessboard.c b/knight_probability_chessboard.c new file mode 100644 index 0000000..63a678d --- /dev/null +++ b/knight_probability_chessboard.c @@ -0,0 +1,62 @@ +// 688. Knight Probability in Chessboard +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * on an 'n x n' chessboard, a knight starts at the cell '(row, column)' and + * attempts to make exactly 'k' moves. the rows and columns are 0-indexed, so + * the top-left cell is '(0, 0)', and the bottom-right cell is '(n - 1, n - 1)'. + * a chess knight has eight possible moves it can make, as illustrated below + * [see image]. each move is two cells in a cardinal direction, then one cell in + * an orthogonal direction. + */ + +bool in_bound(int row, int col, int n) { + return 0 <= row && row < n && col >= 0 && col < n; +} + +double knightProbability(int n, int k, int row, int col) { + double **a = (double **)malloc(sizeof(double *) * n); + double **b = (double **)malloc(sizeof(double *) * n); + for (int i = 0; i < n; i++) { + a[i] = (double *)malloc(sizeof(double) * n); + b[i] = (double *)malloc(sizeof(double) * n); + for (int j = 0; j < n; j++) { + a[i][j] = 0; + b[i][j] = 0; + } + } + static int dr[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; + static int dc[8] = {-2, -1, 1, 2, -2, -1, 1, 2}; + a[row][col] = 1; + double **to = a; + double **from = NULL; + for (int step = 1; step <= k; step++) { + to = ((step % 2) != 0 ? b : a); + from = ((step % 2) != 0 ? a : b); + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + to[i][j] = 0; + for (int l = 0; l < 8; l++) { + to[i][j] += in_bound(i + dr[l], j + dc[l], n) + ? from[i + dr[l]][j + dc[l]] / 8 + : 0; + } + } + } + } + double ans = 0; + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + ans += to[i][j]; + for (int i = 0; i < n; i++) + free(a[i]), free(b[i]); + free(a), free(b); + return ans; +} + +int main() { + printf("%f\n", knightProbability(3, 2, 0, 0)); // expect: 0.06250 + printf("%f\n", knightProbability(1, 0, 0, 0)); // expect: 1.00000 +} diff --git a/knight_probability_chessboard.cpp b/knight_probability_chessboard.cpp new file mode 100644 index 0000000..0c5094d --- /dev/null +++ b/knight_probability_chessboard.cpp @@ -0,0 +1,41 @@ +// 688. Knight Probability in Chessboard +#include "leetcode.h" + +/* + * on an 'n x n' chessboard, a knight starts at the cell '(row, column)' and + * attempts to make exactly 'k' moves. the rows and columns are 0-indexed, so + * the top-left cell is '(0, 0)', and the bottom-right cell is '(n - 1, n - 1)'. + * a chess knight has eight possible moves it can make, as illustrated below + * [see image]. each move is two cells in a cardinal direction, then one cell in + * an orthogonal direction. + */ + +class Solution { +public: + double knightProbability(int n, int k, int row, int col) { + unordered_map<int, unordered_map<int, unordered_map<int, double>>> dp; + if (dp.count(row) && dp[row].count(col) && dp[row][row].count(k)) + return dp[row][col][k]; + if (row < 0 || row >= n || col < 0 || col >= n) + return 0; + if (!k) + return 1; + double total = knightProbability(n, k - 1, row - 1, col - 2) + + knightProbability(n, k - 1, row - 2, col - 1) + + knightProbability(n, k - 1, row - 1, col + 2) + + knightProbability(n, k - 1, row - 2, col + 1) + + knightProbability(n, k - 1, row + 1, col + 2) + + knightProbability(n, k - 1, row + 2, col + 1) + + knightProbability(n, k - 1, row + 1, col - 2) + + knightProbability(n, k - 1, row + 2, col - 1); + double ans = total / 8; + dp[row][col][k] = ans; + return ans; + } +}; + +int main() { + Solution obj; + printf("%f\n", obj.knightProbability(3, 2, 0, 0)); // expect: 0.06250 + printf("%f\n", obj.knightProbability(1, 0, 0, 0)); // expect: 1.00000 +} diff --git a/koko_eating_bananas.c b/koko_eating_bananas.c new file mode 100644 index 0000000..4d0d0cd --- /dev/null +++ b/koko_eating_bananas.c @@ -0,0 +1,29 @@ +// 875. Koko Eating Bananas +#include <stdio.h> + +// return minimum integer 'k' such that koko can eat all bananas within 'h' +// hours + +int minEatingSpeed(int *piles, int piles_size, int h) { + int l = 1, r = 1000000000; + while (l < r) { + int m = (l + r) / 2, total = 0; + for (int i = 0; i < piles_size; i++) + total += (piles[i] + m - 1) / m; + if (total > h) + l = m + 1; + else + r = m; + } + return l; +} + +int main() { + int p1[] = {3, 6, 7, 11}, p2_3[] = {30, 11, 23, 4, 20}; + printf("%d\n", minEatingSpeed(p1, sizeof(p1) / sizeof(p1[0]), 8)); // expect: + // 4 + printf("%d\n", + minEatingSpeed(p2_3, sizeof(p2_3) / sizeof(p2_3[0]), 5)); // expect: 30 + printf("%d\n", + minEatingSpeed(p2_3, sizeof(p2_3) / sizeof(p2_3[0]), 6)); // expect: 23 +} diff --git a/koko_eating_bananas.cpp b/koko_eating_bananas.cpp new file mode 100644 index 0000000..3076169 --- /dev/null +++ b/koko_eating_bananas.cpp @@ -0,0 +1,30 @@ +// 875. Koko Eating Bananas +#include "leetcode.h" + +// return minimum integer 'k' such that koko can eat all bananas within 'h' +// hours + +class Solution { +public: + int minEatingSpeed(vector<int> &piles, int h) { + int l = 1, r = 1000000000; + while (l < r) { + int m = (l + r) / 2, total = 0; + for (int p : piles) + total += (p + m - 1) / m; + if (total > h) + l = m + 1; + else + r = m; + } + return l; + } +}; + +int main() { + Solution obj; + vector<int> p1 = {3, 6, 7, 11}, p2_3 = {30, 11, 23, 4, 20}; + printf("%d\n", obj.minEatingSpeed(p1, 8)); // expect: 4 + printf("%d\n", obj.minEatingSpeed(p2_3, 5)); // expect: 30 + printf("%d\n", obj.minEatingSpeed(p2_3, 6)); // expect: 23 +} diff --git a/kth_element_in_stream.cpp b/kth_element_in_stream.cpp new file mode 100644 index 0000000..8d79bac --- /dev/null +++ b/kth_element_in_stream.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class KthLargest { +private: + int k; + priority_queue<int, vector<int>, greater<int>> pq; + +public: + KthLargest(int k, vector<int> &nums) { + this->k = k; + auto endPointer = nums.begin() + min(k, (int)nums.size()); + pq = priority_queue<int, vector<int>, greater<int>>(nums.begin(), + endPointer); + for (int i = k; i < nums.size(); ++i) { + pq.push(nums[i]); + pq.pop(); + } + } + int add(int val) { + pq.push(val); + if (pq.size() > k) + pq.pop(); + return pq.top(); + } +}; + +int main() { + vector<int> nums({4, 5, 8, 2}), stream({3, 5, 10, 9, 4}); + KthLargest *obj = new KthLargest(3, nums); + for (auto num : stream) + cout << obj->add(num) << ' '; +} diff --git a/kth_largest_element.c b/kth_largest_element.c new file mode 100644 index 0000000..5abeec8 --- /dev/null +++ b/kth_largest_element.c @@ -0,0 +1,54 @@ +// 215. Kth Largest Element in an Array +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array 'nums' and an integer 'k', return the k'th largest + * element in the array. note that it is the k'th largest elemented in sorted + * order, not the k'th distinct element. can you solve without sorting? + */ + +int max(int *a, int n, int i, int j, int k) { + int m = i; + if (j < n && a[j] > a[m]) + m = j; + if (k < n && a[k] > a[m]) + m = k; + return m; +} + +void down_heap(int *a, int n, int i) { + while (1) { + int j = max(a, n, i, 2 * i + 1, 2 * i + 2); + if (j == i) + break; + int t = a[i]; + a[i] = a[j]; + a[j] = t; + i = j; + } +} + +void heapsort(int *a, int n) { + for (int i = (n - 2) / 2; i >= 0; i--) + down_heap(a, n, i); + for (int i = 0; i < n; i++) { + int t = a[n - i - 1]; + a[n - i - 1] = a[0]; + a[0] = t; + down_heap(a, n - i - 1, 0); + } +} + +int findKthLargest(int *nums, int nums_size, int k) { + if (!nums_size || k > nums_size) + return 0; + heapsort(nums, nums_size); + return nums[nums_size - k]; +} + +int main() { + int n1[] = {3, 2, 1, 5, 6, 4}, n2[] = {3, 2, 3, 1, 2, 4, 5, 5, 6}; + printf("%d\n", findKthLargest(n1, 6, 2)); // expect: 5 + printf("%d\n", findKthLargest(n2, 9, 4)); // expect: 4 +} diff --git a/kth_largest_element.cpp b/kth_largest_element.cpp new file mode 100644 index 0000000..c9a60c2 --- /dev/null +++ b/kth_largest_element.cpp @@ -0,0 +1,25 @@ +// 215. Kth Largest Element in an Array +#include "leetcode.h" + +/* + * given an integer array 'nums' and an integer 'k', return the k'th largest + * element in the array. note that it is the k'th largest elemented in sorted + * order, not the k'th distinct element. can you solve without sorting? + */ + +class Solution { +public: + int findKthLargest(vector<int> &nums, int k) { + priority_queue<int> pq(nums.begin(), nums.end()); + for (int i = 1; i < k; i++) + pq.pop(); + return pq.top(); + } +}; + +int main() { + Solution obj; + vector<int> nums = {3, 2, 1, 5, 6, 4}; + int k = 2; + cout << obj.findKthLargest(nums, k); +} diff --git a/kth_largest_element_stream.c b/kth_largest_element_stream.c new file mode 100644 index 0000000..f7ec953 --- /dev/null +++ b/kth_largest_element_stream.c @@ -0,0 +1,105 @@ +// 703. Kth Largest Element in a Stream +#include <limits.h> +#include <stdlib.h> +#include <string.h> + +/* + * design a class to find the k'th largest element in a stream. note that it is + * the k'th largest element in the sorted order, not the k'th distinct element. + * implement 'KthLargest' class: + * - KthLargest(int k, int[] nums) initialises the objct with the integer 'k' + * and the stream of integers 'nums' int add(int val) appends the integer 'val' + * to the stream and returns the element representing the k'th largest stream + * element + */ + +typedef struct { + int *min_heap; + int size; + int curr; +} KthLargest; + +int cmp_func(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +KthLargest *kthLargestCreate(int k, int *nums, int nums_size) { + if (nums_size) + qsort(nums, nums_size, sizeof(int), cmp_func); + KthLargest *res = malloc(sizeof(KthLargest)); + res->size = k; + res->min_heap = malloc(k * sizeof(int)); + if (k <= nums_size) { + memcpy(res->min_heap, &nums[nums_size - k], k * sizeof(int)); + res->curr = k; + } else { + for (int i = 0; i < k; i++) { + if (i < nums_size) + res->min_heap[i] = nums[i]; + else + res->min_heap[i] = INT_MAX; + res->curr = nums_size; + } + } + return res; +} + +void swap(int *a, int *b) { + int tmp = *a; + *a = *b; + *b = tmp; +} + +int kthLargestAdd(KthLargest *obj, int val) { + if (obj->curr < obj->size) { + obj->min_heap[obj->curr] = val; + int pos = obj->curr; + obj->curr++; + while (pos) { + if (obj->min_heap[pos] < obj->min_heap[(pos - 1) / 2]) { + swap(&obj->min_heap[pos], &obj->min_heap[(pos - 1) / 2]); + pos = (pos - 1) / 2; + } else + break; + } + if (obj->curr == obj->size) + return obj->min_heap[0]; + else + return -1; + } else if (obj->curr == obj->size && val > obj->min_heap[0]) { + obj->min_heap[0] = val; + int idx = 0; + while (2 * idx + 1 < obj->size && 2 * idx + 2 < obj->size) { + if (obj->min_heap[2 * idx + 1] <= obj->min_heap[2 * idx + 1]) { + if (obj->min_heap[idx] > obj->min_heap[2 * idx + 1]) { + swap(&obj->min_heap[idx], &obj->min_heap[2 * idx + 1]); + idx = 2 * idx + 1; + } else + break; + } else { + if (obj->min_heap[idx] > obj->min_heap[2 * idx + 2]) { + swap(&obj->min_heap[idx], &obj->min_heap[2 * idx + 2]); + idx = 2 * idx + 2; + } else + break; + } + } + if (2 * idx + 1 < obj->size) { + if (obj->min_heap[idx] > obj->min_heap[2 * idx + 1]) { + swap(&obj->min_heap[idx], &obj->min_heap[2 * idx + 1]); + idx = 2 * idx + 1; + } + } + } + return obj->min_heap[0]; +} + +void kthLargestFree(KthLargest *obj) { + free(obj->min_heap); + free(obj); +} + +int main() { + int k, nums[] = {}, nums_size, val; + KthLargest *obj = kthLargestCreate(k, nums, nums_size); + int param_1 = kthLargestAdd(obj, val); + kthLargestFree(obj); +} diff --git a/kth_largest_element_stream.cpp b/kth_largest_element_stream.cpp new file mode 100644 index 0000000..805d144 --- /dev/null +++ b/kth_largest_element_stream.cpp @@ -0,0 +1,40 @@ +// 703. Kth Largest Element in a Stream +#include "leetcode.h" + +/* + * design a class to find the k'th largest element in a stream. note that it is + * the k'th largest element in the sorted order, not the k'th distinct element. + * implement 'KthLargest' class: + * - KthLargest(int k, int[] nums) initialises the objct with the integer 'k' + * and the stream of integers 'nums' int add(int val) appends the integer 'val' + * to the stream and returns the element representing the k'th largest stream + * element + */ + +class KthLargest { + priority_queue<int, vector<int>, greater<int>> pq; + int size; + +public: + KthLargest(int k, vector<int> &nums) { + size = k; + for (int i = 0; i < nums.size(); i++) { + pq.push(nums[i]); + if (pq.size() > k) + pq.pop(); + } + } + int add(int val) { + pq.push(val); + if (pq.size() > size) + pq.pop(); + return pq.top(); + } +}; + +int main() { + int k, val; + vector<int> nums; + KthLargest *obj = new KthLargest(k, nums); + int param_1 = obj->add(val); +} diff --git a/kth_missing_pos_num.c b/kth_missing_pos_num.c new file mode 100644 index 0000000..db84e14 --- /dev/null +++ b/kth_missing_pos_num.c @@ -0,0 +1,26 @@ +// 1539. Kth Missing Positive Number +#include <stdio.h> + +/* + * given array 'arr' of positive integers sorted in a strictly increasing order, + * and an integer 'k', return 'kth' positive integer missing from array -- o(log + * n) + */ + +int findKthPositive(int *arr, int arr_size, int k) { + int l = 0, r = arr_size, m; + while (l < r) { + m = (l + r) / 2; + if (arr[m] - 1 - m < k) + l = m + 1; + else + r = m; + } + return l + k; +} + +int main() { + int a1[] = {2, 3, 4, 7, 11}, a2[] = {1, 2, 3, 4}; + printf("%d\n", findKthPositive(a1, 5, 5)); // expect: 9 + printf("%d\n", findKthPositive(a2, 2, 4)); // expect: 6 +} diff --git a/kth_missing_pos_num.cpp b/kth_missing_pos_num.cpp new file mode 100644 index 0000000..a7f81f7 --- /dev/null +++ b/kth_missing_pos_num.cpp @@ -0,0 +1,30 @@ +// 1539. Kth Missing Positive Number +#include "leetcode.h" + +/* + * given array 'arr' of positive integers sorted in a strictly increasing order, + * and an integer 'k', return 'kth' positive integer missing from array -- o(log + * n) + */ + +class Solution { +public: + int findKthPositive(vector<int> &arr, int k) { + int l = 0, r = arr.size(), m; + while (l < r) { + m = (l + r) / 2; + if (arr[m] - 1 - m < k) + l = m + 1; + else + r = m; + } + return l + k; + } +}; + +int main() { + Solution obj; + vector<int> a1 = {2, 3, 4, 7, 11}, a2 = {1, 2, 3, 4}; + cout << obj.findKthPositive(a1, 5) << endl; // expect: 9 + cout << obj.findKthPositive(a2, 2) << endl; // expect: 6 +} diff --git a/kth_smallest_BST.cpp b/kth_smallest_BST.cpp new file mode 100644 index 0000000..73243d4 --- /dev/null +++ b/kth_smallest_BST.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + set<int> s; + int kthSmallest(TreeNode *root, int k) { + traverse(root); + for (auto ans : s) { + k--; + if (!k) + return ans; + } + return 0; + } + +private: + void traverse(TreeNode *root) { + if (!root) + return; + s.insert(root->val); + traverse(root->left); + traverse(root->right); + } +}; + +int main() {} diff --git a/kth_smallest_lexicographical.c b/kth_smallest_lexicographical.c new file mode 100644 index 0000000..85551db --- /dev/null +++ b/kth_smallest_lexicographical.c @@ -0,0 +1,37 @@ +// 440. K-th Smallest in Lexicographical Order +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +// given two integers 'n' and 'k', return the k'th lexicographically smallest +// integer + +int count_prefix(int n, long long prefix) { + long long offset = 10, target = n; + int total = 0; + for (int i = 1; i <= 9; i++) { + long long min = prefix * offset; + long long max = min + offset - 1; + if (target < min) + break; + total += fmin(target, max) - min + 1; + } + return total + 1; +} + +int findKthNumber(int n, int k) { + int prefix = 0; + if (k) + for (int i = !prefix ? 1 : 0; i <= 9; i++) { + int prefix_cnt = count_prefix(n, 10 * prefix + i); + if (k <= prefix_cnt) + return findKthNumber(n, k - 1); + k -= prefix_cnt; + } + return prefix; +} + +int main() { + printf("%d\n", findKthNumber(13, 2)); // expect: 10 + printf("%d\n", findKthNumber(1, 1)); // expect: 1 +} diff --git a/kth_smallest_lexicographical.cpp b/kth_smallest_lexicographical.cpp new file mode 100644 index 0000000..1e292ec --- /dev/null +++ b/kth_smallest_lexicographical.cpp @@ -0,0 +1,43 @@ +#include "leetcode.h" + +class Soltuion { +public: + int findKthNumber(int n, int k) { + int ans = 0, rankNum = 0, next = 0, rankNext = 0; + while (rankNum != k) { + int lower = ans ? 0 : 1, upper = 9; + while (lower < upper) { + auto mid = (lower + upper + 1) / 2; + next = ans * 10 + mid; + rankNext = rank(next, n); + } + ans *= 10, ans += lower; + rankNum = (ans == next ? rankNext : rank(ans, n)); + } + return ans; + } + +private: + static int rank(int prefix, int maxVal) { + int ret = 1, num = 0; + for (int i = prefix; i; i /= 10, ++num) + for (int j = 1; j <= i % 10; ++j) + ret += numPrefixes(i - j, maxVal); + ret += num - 1; + return ret; + } + static int numPrefixes(int prefix, int maxVal) { + if (prefix == 0) + return 0; + int ret = 0; + unsigned long long ull = 1; + for (unsigned long long val = prefix; val <= maxVal; ull *= 10, val *= 10) + ret += min(ull, maxVal - val + 1); + return ret; + } +}; + +int main() { + Soltuion obj; + cout << obj.findKthNumber(13, 2); +} diff --git a/kth_smallest_prime_fraction.c b/kth_smallest_prime_fraction.c new file mode 100644 index 0000000..c3a8126 --- /dev/null +++ b/kth_smallest_prime_fraction.c @@ -0,0 +1,76 @@ +// 786. K-th Smallest Prime Fraction +#include "leetcode.h" + +/* + * given a sorted integer array 'arr' containing '1' and prime numbers where + * all the integers of 'arr' are unique. you are also given an integer 'k'. for + * every 'i' and 'j' where '0 <= i < j < arr.len', we consider the fraction + * 'arr[i] / arr[j]'. return the k'th smallest fraction considered. return your + * answer as an array of integers of size '2'. + */ + +int less_equal_position(int *nums, int n, int i, double val) { + int left = i + 1, right = n - 1, mid; + if (val < (double)nums[i] / nums[n - 1]) + return n; + while (left < right) { + mid = left + (right - left) / 2; + double tmp = (double)nums[i] / nums[mid]; + if (tmp == val) + return mid; + if (tmp < val) + right = mid; + else + left = mid + 1; + } + return left; +} + +int *kthSmallestPrimeFraction(int *arr, int arrSize, int k, int *returnSize) { + double left = 0, right = 1, mid; + while (left < right) { + mid = (left + right) / 2; + int cnt = 0; + for (int i = 0; i < arrSize - 1; i++) { + int pos = less_equal_position(arr, arrSize, i, mid); + cnt += (arrSize - pos); + } + if (cnt == k) + break; + if (cnt > k) + right = mid; + else + left = mid; + } + double val = 0; + int x = 0, y = 0; + for (int i = 0; i < arrSize; i++) + for (int j = i + 1; j < arrSize; j++) { + double tmp = (double)arr[i] / arr[j]; + if (tmp <= mid) { + if (val < tmp) { + val = tmp; + x = arr[i]; + y = arr[j]; + } + break; + } + } + int *ans = (int *)malloc(2 * sizeof(int)); + ans[0] = x; + ans[1] = y; + *returnSize = 2; + return ans; +} + +int main() { + int a1[] = {1, 2, 3, 5}, a2[] = {1, 7}, rs1, rs2; + int *ksmpf1 = kthSmallestPrimeFraction(a1, ARRAY_SIZE(a1), 3, &rs1); + int *ksmpf2 = kthSmallestPrimeFraction(a2, ARRAY_SIZE(a2), 1, &rs2); + for (int i = 0; i < rs1; i++) + printf("%d ", ksmpf1[i]); // expect: 2 5 + printf("\n"); + for (int i = 0; i < rs2; i++) + printf("%d ", ksmpf2[i]); // expect: 1 7 + printf("\n"); +} diff --git a/kth_smallest_prime_fraction.py b/kth_smallest_prime_fraction.py new file mode 100644 index 0000000..a64d1d1 --- /dev/null +++ b/kth_smallest_prime_fraction.py @@ -0,0 +1,39 @@ +# 786. K-th Smallest Prime Fraction +from bisect import bisect + +""" +given a sorted integer array 'arr' containing '1' and prime numbers where +all the integers of 'arr' are unique. you are also given an integer 'k'. for +every 'i' and 'j' where '0 <= i < j < arr.len', we consider the fraction +'arr[i] / arr[j]'. return the k'th smallest fraction considered. return your +answer as an array of integers of size '2'. +""" + + +class Solution(object): + def kthSmallestPrimeFraction(self, arr, k): + """ + :type arr: List[int] + :type k: int + :rtype: List[int] + """ + left, right, n = 0, 1, len(arr) + while True: + mid = (left + right) / 2 + border = [bisect(arr, arr[i] / mid) for i in range(n)] + curr = sum(n - i for i in border) + if curr > k: + right = mid + elif curr < k: + left = mid + else: + return max( + [(arr[i], arr[j]) for i, j in enumerate(border) if j < n], + key=lambda x: x[0] / x[1], + ) + + +if __name__ == "__main__": + obj = Solution() + print(obj.kthSmallestPrimeFraction(arr=[1, 2, 3, 5], k=3)) + print(obj.kthSmallestPrimeFraction(arr=[1, 7], k=1)) diff --git a/kth_smallest_sorted_matrix.cpp b/kth_smallest_sorted_matrix.cpp new file mode 100644 index 0000000..aad9458 --- /dev/null +++ b/kth_smallest_sorted_matrix.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + int kthSmallest(vector<vector<int>> &matrix, int k) { + int n = matrix.size(), left = matrix[0][0], right = matrix[n - 1][n - 1], + mid = 0; + while (left < right) { + mid = left + (right - left) / 2; + int num = 0; + for (int i = 0; i < n; i++) { + int pos = upper_bound(matrix[i].begin(), matrix[i].end(), mid) - + matrix[i].begin(); + num += pos; + } + if (num < k) + left = mid + 1; + else + right = mid; + } + return left; + } +}; + +int main() { + Solution obj; + vector<vector<int>> matrix; + int k; + obj.kthSmallest(matrix, k); +} diff --git a/kth_symbol_grammar.c b/kth_symbol_grammar.c new file mode 100644 index 0000000..59e79ce --- /dev/null +++ b/kth_symbol_grammar.c @@ -0,0 +1,27 @@ +// 779. K-th Symbol in Grammar +#include <stdio.h> +#include <stdlib.h> + +/* + * we build a table of 'n' rows (1-indexed) we start by writing 0 in the first + * row. now in every subsequent row, we look at the previous row and replace + * each occurence of zero with '01', and each occurence of 1 with '10'. for + * example for 'n = 3', the first row is the 0, the second row is the 01, and + * the third row is 0110. given two integer 'n' and 'k', return the k'th + * (1-indexed) symbol in the n'th row of a table of 'n' rows. + */ + +int kthGrammar(int n, int k) { + if (n == 1) + return 0; + if (k % 2 == 1) + return kthGrammar(n - 1, (k + 1) / 2); + else + return (kthGrammar(n - 1, k / 2) == 0) ? 1 : 0; +} + +int main() { + printf("%d\n", kthGrammar(1, 1)); // expect: 0 + printf("%d\n", kthGrammar(2, 1)); // expect: 0 + printf("%d\n", kthGrammar(2, 2)); // expect: 1 +} diff --git a/kth_symbol_grammar.py b/kth_symbol_grammar.py new file mode 100644 index 0000000..5089c46 --- /dev/null +++ b/kth_symbol_grammar.py @@ -0,0 +1,22 @@ +# 779. K-th Symbol in Grammar + +""" +we build a table of 'n' rows (1-indexed) we start by writing 0 in the first +row. now in every subsequent row, we look at the previous row and replace +each occurence of zero with '01', and each occurence of 1 with '10'. for +example for 'n = 3', the first row is the 0, the second row is the 01, and +the third row is 0110. given two integer 'n' and 'k', return the k'th +(1-indexed) symbol in the n'th row of a table of 'n' rows. +""" + + +class Solution(object): + def kthGrammar(self, n, k): + return bin(k - 1).count("1") & 1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.kthGrammar(1, 1)) # expect: 0 + print(obj.kthGrammar(2, 1)) # expect: 0 + print(obj.kthGrammar(2, 2)) # expect: 1 diff --git a/largest_3_digit_string.c b/largest_3_digit_string.c new file mode 100644 index 0000000..9c9ed41 --- /dev/null +++ b/largest_3_digit_string.c @@ -0,0 +1,44 @@ +// 2264. Largest 3-Same-Digit Number in String +#include "leetcode.h" + +/* + * given a string 'num' representing a large integer, an integer is good if it + * meets the following conditions: if it is a substring of 'num' with length + * '3', it consists of only one unique digit. return the maximum good integer as + * a string or an empty string "" if no such integer. + */ + +char *largestGoodInterger(char *num) { + int n = strlen(num), chr = 'a', cnt = 1; + for (int i = 1; i < n; i++) { + if (num[i] == num[i - 1]) { + cnt++; + if (i < n - 1) + continue; + } + if (cnt >= 3) { + if (chr == 'a') + chr = num[i - 1]; + else + chr = fmax(chr, num[i - 1]); + } + cnt = 1; + } + if (chr == 'a') + return ""; + else { + char *ans = malloc(4); + ans[3] = '\0'; + ans[0] = chr; + ans[1] = chr; + ans[2] = chr; + return ans; + } +} + +int main() { + char *n1 = "6777133339", *n2 = "2300019", *n3 = "42352338"; + printf("%s\n", largestGoodInterger(n1)); // expect: 777 + printf("%s\n", largestGoodInterger(n2)); // expect: 000 + printf("%s\n", largestGoodInterger(n3)); // expect: NULL +} diff --git a/largest_3_digit_string.py b/largest_3_digit_string.py new file mode 100644 index 0000000..f8789a4 --- /dev/null +++ b/largest_3_digit_string.py @@ -0,0 +1,36 @@ +# 2264. Largest 3-Same-Digit Number in String + +""" +given a string 'num' representing a large integer, an integer is good if it +meets the following conditions: if it is a substring of 'num' with length +'3', it consists of only one unique digit. return the maximum good integer as +a string or an empty string "" if no such integer. +""" + + +class Solution(object): + def largestGoodInteger(self, num): + """ + :type num: str + :rtype: str + """ + ans = "" + empty = "" + tmp = 0 + check = True + for i in range(len(num) - 2): + if i + 2 < len(num) and num[i] == num[i + 1] == num[i + 2]: + tmp = max(tmp, int(num[i])) + check = False + if not check: + ans += str(tmp) * 3 + else: + return empty + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.largestGoodInteger("6777133339")) # expect: 777 + print(obj.largestGoodInteger("2300019")) # expect: 000 + print(obj.largestGoodInteger("42352338")) # expect: NULL diff --git a/largest_colour_value_graph.cpp b/largest_colour_value_graph.cpp new file mode 100644 index 0000000..984f472 --- /dev/null +++ b/largest_colour_value_graph.cpp @@ -0,0 +1,87 @@ +// 1857. Largest Color Value in a Directed Graph +#include "leetcode.h" + +/* + * there is a directed graph of n coloured nodes and m edges. the nodes are + * numbered from 0 to n - 1. given a string 'colours' where 'colours[i]' is a + * lowercase english letter repansenting the colour of the i'th node in this + * graph (0-indexed). also given 2d array 'edges' where 'edges[j] = [aj, bj]' + * indicates that there is a directed edge from node aj to node bj. a valid path + * in the graph is a sequence of nodes 'x1 -> x2 -> ... -> xk' such that there + * is a directed edge from xi to xi + 1 for every 1 <= i < k. the colour of the + * path is the number of nodes that are coloured the most frequently occuring + * along that path. return largest colour value of any valid path in the given + * graph or -1. + */ + +class Solution { + bool dfs(vvd(int) & al, vector<int> &gb, int i) { + if (!gb[i]) { + gb[i] = 1; + for (auto j : al[i]) + if (!dfs(al, gb, j)) + return false; + gb[i] = 2; + } + return gb[i] == 2; + } + +public: + int largestPathValue(string colours, vvd(int) & edges) { + int cnt[128] = {}, colours_size = colours_size; + for (auto c : colours) + ++cnt[c]; + char s[26] = {}; + iota(begin(s), end(s), 'a'); + sort(begin(s), end(s), [&](char a, char b) { return cnt[a] > cnt[b]; }); + vvd(int) al(colours_size); + vector<bool> target(colours_size); + for (auto &e : edges) { + al[e[0]].push_back(e[1]); + target[e[1]] = true; + } + vector<pair<int, int>> vp; + for (int i = 0; i < colours_size; ++i) + if (!target[i]) + vp.push_back({i, -1}); + int ans = 0; + vector<int> gb(colours_size); + for (auto [i, tmp] : vp) + if (!dfs(al, gb, i)) + return -1; + if (count(begin(gb), end(gb), 2) != colours_size) + return -1; + for (char c : s) { + if (ans >= cnt[c]) + continue; + vector<int> cnt(colours_size, -1); + auto q = vp; + while (!q.empty()) { + vector<pair<int, int>> vp1; + for (auto [i, from] : vp) { + int count = (from == -1 ? 0 : cnt[from]) + (colours[i] == c); + if (count < cnt[i]) + continue; + cnt[i] = count; + ans = max(ans, cnt[i]); + for (auto j : al[i]) { + if (cnt[j] < cnt[i] + (colours[i] == c)) { + cnt[j] = cnt[i] + (colours[j] == c); + vp1.push_back({j, i}); + } + } + } + swap(vp, vp1); + } + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) e1 = {{0, 1}, {0, 2}, {2, 3}, {3, 4}}; + vvd(int) e2 = {{0, 0}}; + printf("%d\n", obj.largestPathValue("abaca", e1)); // expect: 3 + printf("%d\n", obj.largestPathValue("a", e2)); // expect: -1 +} diff --git a/largest_divisible_subset.c b/largest_divisible_subset.c new file mode 100644 index 0000000..f540528 --- /dev/null +++ b/largest_divisible_subset.c @@ -0,0 +1,58 @@ +// 368. Largest Divisible Subset +#include "leetcode.h" + +/* + * given a set of distinct positive integers 'nums', return the largest subset + * 'answer' such that every pair '(ans[i], ans[j])' of elements in this subset + * satifies 'ans[i] % ans[j] == 0' or 'ans[j] % ans[i] == 0'. if there are + * multiple solutions, return any of them. + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int *largestDivisibleSubset(int *nums, int nums_size, int *return_size) { + qsort(nums, nums_size, sizeof(int), cmp); + int *idx = malloc(nums_size * sizeof(int)); + int *cnt = malloc(nums_size * sizeof(int)); + int max = 1, max_idx = 0, tmp; + idx[0] = -1; + cnt[0] = 1; + for (int i = 1; i < nums_size; i++) { + idx[i] = -1; + cnt[i] = 1; + for (int j = i - 1; j >= 0; j--) + if (!(nums[i] % nums[j])) { + tmp = cnt[j] + 1; + if (tmp > cnt[i]) { + cnt[i] = tmp; + idx[i] = j; + } + } + if (cnt[i] > max) { + max = cnt[i]; + max_idx = i; + } + } + *return_size = max; + int *ans = malloc(max * sizeof(int)); + for (int i = max - 1; i >= 0; i--) { + ans[i] = nums[max_idx]; + max_idx = idx[max_idx]; + } + free(idx), free(cnt); + return ans; +} + +int main() { + int n1[] = {1, 2, 3}, n2[] = {1, 2, 4, 8}; + int rs1[] = {}, rs2[] = {}; + int *lds1 = largestDivisibleSubset(n1, ARRAY_SIZE(n1), rs1); + int *lds2 = largestDivisibleSubset(n2, ARRAY_SIZE(n2), rs2); + for (int i = 0; i < 2; i++) + printf("%d ", lds1[i]); // expect: 1 2 + printf("\n"); + for (int i = 0; i < 4; i++) + printf("%d ", lds2[i]); // expect: 1 2 4 8 + printf("\n"); + free(lds1), free(lds2); +} diff --git a/largest_divisible_subset.py b/largest_divisible_subset.py new file mode 100644 index 0000000..842b78a --- /dev/null +++ b/largest_divisible_subset.py @@ -0,0 +1,31 @@ +# 368. Largest Divisible Subset + +""" +given a set of distinct positive integers 'nums', return the largest subset +'answer' such that every pair '(ans[i], ans[j])' of elements in this subset +satifies 'ans[i] % ans[j] == 0' or 'ans[j] % ans[i] == 0'. if there are +multiple solutions, return any of them. +""" + + +class Solution(object): + def largestDivisibleSubset(self, nums): + """ + :type nums: List[int] + :rtype: List[int] + """ + if len(nums) == 0: + return [] + nums.sort() + ans = [[i] for i in nums] + for i in range(len(nums)): + for j in range(i): + if nums[i] % nums[j] == 0 and len(ans[i]) < len(ans[j]) + 1: + ans[i] = ans[j] + [nums[i]] + return max(ans, key=len) + + +if __name__ == "__main__": + obj = Solution() + print(obj.largestDivisibleSubset([1, 2, 3])) + print(obj.largestDivisibleSubset([1, 2, 4, 8])) diff --git a/largest_int_add_target.cpp b/largest_int_add_target.cpp new file mode 100644 index 0000000..91015d0 --- /dev/null +++ b/largest_int_add_target.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +class Solution { +public: + string largestNumber(vector<int> &cost, int target) { + vector<int> dp(target + 1, -10000); + dp[0] = 0; + for (int i = 1; i <= target; ++i) + for (int j = 0; j < 9; ++j) + dp[i] = max(dp[i], i >= cost[j] ? 1 + dp[i - cost[j]] : -10000); + if (dp[target] < 0) + return "0"; + string ans = ""; + for (int i = 8; i >= 0; --i) { + while (target >= cost[i] && dp[target] == dp[target - cost[i]] + 1) { + ans.push_back('1' + i); + target -= cost[i]; + } + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> cost = {4, 3, 2, 5, 6, 7, 2, 5, 5}; + int target = 9; + cout << obj.largestNumber(cost, target); +} diff --git a/largest_local_val_matrix.c b/largest_local_val_matrix.c new file mode 100644 index 0000000..c587217 --- /dev/null +++ b/largest_local_val_matrix.c @@ -0,0 +1,55 @@ +// 2373. Largest Local Values in a Matrix +#include "leetcode.h" + +/* + * given an 'n * n' integer matrix grid. generate an integer matrix 'max_local' + * of size '(n - 2) * (n - 2)' such that 'max_local[i][j]' is equal to the + * largest value of the 3 * 3 matrix in 'grid' centred around row 'i + 1' and + * column 'j + 1'. in other words, we want to find the largest value in every + * contiguous 3 * 3 matrix in 'grid'. return the generated matrix. + */ + +int **largestLocal(int **grid, int gridSize, int *gridColSize, int *returnSize, + int **returnColumnSizes) { + *returnSize = gridSize - 2; + *returnColumnSizes = (int *)malloc((gridSize - 2) * sizeof(int)); + for (int i = 0; i < gridSize - 2; ++i) + (*returnColumnSizes)[i] = gridSize - 2; + int **ans = (int **)malloc((gridSize - 2) * sizeof(int *)); + for (int i = 0; i < gridSize - 2; ++i) + ans[i] = (int *)malloc((gridSize - 2) * sizeof(int)); + for (int i = 0; i < gridSize - 2; ++i) + for (int j = 0; j < gridSize - 2; ++j) { + for (int row = 0; row <= 2; ++row) { + int max = 0; + for (int col = 0; col <= 2; ++col) + if (grid[i + row][j + col] > max) + max = grid[i + row][j + col]; + ans[i][j] = max; + max = 0; + } + } + return ans; +} + +int main() { + int g1[4][4], g2[5][5], gcs1[] = {4, 4, 4, 4}, gcs2[] = {5, 5, 5, 5, 5}, rs1, + rs2, *rcs1, *rcs2; + g1[0][0] = 9, g1[0][1] = 9, g1[0][2] = 8, g1[0][3] = 1; + g1[1][0] = 5, g1[1][1] = 6, g1[1][2] = 2, g1[1][3] = 6; + g1[2][0] = 8, g1[2][1] = 2, g1[2][2] = 6, g1[2][3] = 4; + g1[3][0] = 6, g1[3][1] = 2, g1[3][2] = 2, g1[3][3] = 2; + for (int i = 0; i < 5; i++) + for (int j = 0; j < 5; j++) + g2[i][j] = 1; + int **ll1 = largestLocal((int **)g1, 4, gcs1, &rs1, &rcs1); + int **ll2 = largestLocal((int **)g2, 5, gcs2, &rs2, &rcs2); + for (int i = 0; i < rs1; i++) + for (int j = 0; j < rs1; j++) + printf("%d ", ll1[i][j]); + printf("\n"); + for (int i = 0; i < rs2; i++) + for (int j = 0; j < rs2; j++) + printf("%d ", ll2[i][j]); + printf("\n"); +} diff --git a/largest_local_val_matrix.py b/largest_local_val_matrix.py new file mode 100644 index 0000000..47575d0 --- /dev/null +++ b/largest_local_val_matrix.py @@ -0,0 +1,43 @@ +# 2373. Largest Local Values in a Matrix + +""" +given an 'n n' integer matrix grid. generate an integer matrix 'max_local' +of size '(n - 2) (n - 2)' such that 'max_local[i][j]' is equal to the +largest value of the 3 3 matrix in 'grid' centred around row 'i + 1' and +column 'j + 1'. in other words, we want to find the largest value in every +contiguous 3 3 matrix in 'grid'. return the generated matrix. +""" + + +class Solution(object): + def largestLocal(self, grid): + """ + :type grid: List[List[int]] + :rtype: List[List[int]] + """ + n = len(grid) + ans = [[0] * (n - 2) for _ in range(n - 2)] + for i in range(n - 2): + for j in range(n - 2): + ans[i][j] = max( + grid[ii][jj] for ii in range(i, i + 3) for jj in range(j, j + 3) + ) + return ans + + +if __name__ == "__main__": + obj = Solution() + print( + obj.largestLocal(grid=[[9, 9, 8, 1], [5, 6, 2, 6], [8, 2, 6, 4], [6, 2, 2, 2]]) + ) + print( + obj.largestLocal( + grid=[ + [1, 1, 1, 1, 1], + [1, 1, 1, 1, 1], + [1, 1, 2, 1, 1], + [1, 1, 1, 1, 1], + [1, 1, 1, 1, 1], + ] + ) + ) diff --git a/largest_multiple_three.cpp b/largest_multiple_three.cpp new file mode 100644 index 0000000..1c9e3e1 --- /dev/null +++ b/largest_multiple_three.cpp @@ -0,0 +1,37 @@ +#include "leetcode.h" + +class Solution { +public: + string largestMultipleOfThree(vector<int> &digits) { + int n = digits.size(), d[10] = {}, sum = 0; + int r1[] = {1, 4, 7, 2, 5, 8}, r2[] = {2, 5, 8, 1, 4, 7}; + string ans = ""; + for (int i = 0; i < n; i++) { + ++d[digits[i]]; + sum += digits[i]; + } + while (sum % 3 != 0) { + for (int i = 0; i < 6; i++) { + if (sum % 3 == 1 && d[r1[i]]) { + sum -= r1[i]; + d[r1[i]]--; + break; + } else if (sum % 3 == 2 && d[r2[i]]) { + sum -= r2[i]; + d[r2[i]]--; + break; + } + } + } + for (int i = 9; i >= 0; i--) + for (int j = 1; j <= d[i]; j++) + ans += to_string(i); + return ans[0] == '0' ? "0" : ans; + } +}; + +int main() { + Solution obj; + vector<int> digits = {8, 1, 9}; + cout << obj.largestMultipleOfThree(digits); +} diff --git a/largest_number.c b/largest_number.c new file mode 100644 index 0000000..2d797f8 --- /dev/null +++ b/largest_number.c @@ -0,0 +1,82 @@ +// 179. Largest Number +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a list of non-negative integers 'nums', arrange them such that they + * form the larget number and return it. since the result may be very large, so + * you need to return a string instead of an integer. + */ + +int check_digit(int val) { + int digit = 0; + while (val) { + digit++; + val /= 10; + } + return digit; +} + +char *int_to_str(int val) { + if (!val) + return "0"; + int digit = check_digit(val); + char *res = malloc(digit + 1); + res[digit] = '\0'; + int idx = digit - 1; + while (val) { + res[idx] = val % 10 + '0'; + val /= 10; + idx--; + } + return res; +} + +int cmp(const void *a, const void *b) { + char *aa = *(char **)a; + char *bb = *(char **)b; + int n = strlen(aa) + strlen(bb); + char *ab = malloc(n + 1), *ba = malloc(n + 1); + ab[n] = '\0'; + ba[n] = '\0'; + strcpy(ab, aa); + strcpy(&ab[strlen(aa)], bb); + strcpy(ba, bb); + strcpy(&ba[strlen(bb)], aa); + for (int i = 0; i < n; i++) { + if (ab[i] == ba[i]) + continue; + return ba[i] - ab[i]; + } + return 0; +} + +char *largestNumber(int *nums, int nums_size) { + int n = nums_size, len = 0; + char **data = malloc(n * sizeof(char *)); + bool zero = true; + for (int i = 0; i < n; i++) { + data[i] = int_to_str(nums[i]); + len += strlen(data[i]); + if (nums[i]) + zero = false; + } + if (zero) + return "0"; + qsort(data, n, sizeof(char *), cmp); + char *ans = malloc(len + 1); + int p = 0; + for (int i = 0; i < n; i++) { + strcpy(&ans[p], data[i]); + p += strlen(data[i]); + } + return ans; +} + +int main() { + int n1[] = {10, 2}, n2[] = {3, 30, 34, 5, 9}; + printf("%s\n", largestNumber(n1, 2)); // expect: 210 + printf("%s\n", largestNumber(n2, 5)); // expect: 9534330 +} diff --git a/largest_number.py b/largest_number.py new file mode 100644 index 0000000..8efe135 --- /dev/null +++ b/largest_number.py @@ -0,0 +1,36 @@ +# 179. Largest Number + +""" +given a list of non-negative integers 'nums', arrange them such that they +form the larget number and return it. since the result may be very large, so +you need to return a string instead of an integer. +""" + + +class Solution(object): + def largestNumber(self, nums): + self.quickSort(nums, 0, len(nums) - 1) + return str(int("".join(map(str, nums)))) + + def quickSort(self, nums, l, r): + if l >= r: + return + pos = self.partition(nums, l, r) + self.quickSort(nums, l, pos - 1) + self.quickSort(nums, pos + 1, r) + + def partition(self, nums, l, r): + low = l + while l < r: + if self.compare(nums[l], nums[r]): + nums[l], nums[low] = nums[low], nums[l] + low += 1 + l += 1 + nums[low], nums[r] = nums[r], nums[low] + return low + + +if __name__ == "__main__": + obj = Solution() + print(obj.largestNumber([10, 2])) # expect: 210 + print(obj.largestNumber([3, 30, 34, 5, 9])) # expect: 9534330 diff --git a/largest_odd_num_string.c b/largest_odd_num_string.c new file mode 100644 index 0000000..246fbdc --- /dev/null +++ b/largest_odd_num_string.c @@ -0,0 +1,26 @@ +// 1903. Largest Odd Number in String +#include "leetcode.h" + +/* + * given a string 'num' representing a large integer. return the largest-valued + * odd integer as a string is a non-empty substring of 'num', or an empty string + * "" if no odd integer exists. a substring is a contiguous sequence of + * characters within a string + */ + +char *largestOddNumber(char *num) { + int n = strlen(num); + for (int i = n - 1; i >= 0; i--) + if ((num[i] - '0') % 2 == 1) { + num[i + 1] = '\0'; + return num; + } + return ""; +} + +int main() { + char *n1 = "52", *n2 = "4206", *n3 = "35427"; + printf("%s\n", largestOddNumber(n1)); // expect: 5 + printf("%s\n", largestOddNumber(n2)); // expect: NULL + printf("%s\n", largestOddNumber(n3)); // expect: 35427 +} diff --git a/largest_odd_num_string.cpp b/largest_odd_num_string.cpp new file mode 100644 index 0000000..019d609 --- /dev/null +++ b/largest_odd_num_string.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" + +class Solution { +public: + string largestOddNumber(string num) { + if (num.back() == '0') + num.pop_back(); + int back = stoi(num) % 10; + if (back % 2 == 0) { + for (int i = 0; i < num.size(); i++) + if (num[i] % 2 == 0) + num.erase(i, 1), i--; + if (num.size() < 2) + return num; + else + for (int i = 0; i < num.size(); i++) + if (num[i] < num[i + 1]) + return num.substr(i + 2, 1); + } else + return num; + return string(); + } +}; + +int main() { + Solution obj; + cout << endl << obj.largestOddNumber("10133890"); +} diff --git a/largest_odd_num_string.py b/largest_odd_num_string.py new file mode 100644 index 0000000..8ea2183 --- /dev/null +++ b/largest_odd_num_string.py @@ -0,0 +1,27 @@ +# 1903. Largest Odd Number in String + +""" +given a string 'num' representing a large integer. return the largest-valued +odd integer as a string is a non-empty substring of 'num', or an empty string +"" if no odd integer exists. a substring is a contiguous sequence of +characters within a string +""" + + +class Solution(object): + def largestOddNumber(self, num): + """ + :type num: str + :rtype: str + """ + for i in range(len(num) - 1, -1, -1): + if num[i] in {"1", "3", "5", "7", "9"}: + return num[: i + 1] + return "" + + +if __name__ == "__main__": + obj = Solution() + print(obj.largestOddNumber("52")) # expect: 5 + print(obj.largestOddNumber("4206")) # expect: "" + print(obj.largestOddNumber("35427")) # expect: 35427 diff --git a/largest_perimeter_triangle.cpp b/largest_perimeter_triangle.cpp new file mode 100644 index 0000000..64b3682 --- /dev/null +++ b/largest_perimeter_triangle.cpp @@ -0,0 +1,18 @@ +#include "leetcode.h" + +class Solution { +public: + int largestPerimeter(vector<int> &nums) { + sort(nums.begin(), nums.end()); + for (int i = nums.size() - 1; i > 1; --i) + if (nums[i] < nums[i - 1] + nums[i - 2]) + return nums[i] + nums[i - 1] + nums[i - 2]; + return 0; + } +}; + +int main() { + Solution obj; + vector<int> nums = {2, 1, 2}; + cout << obj.largestPerimeter(nums); +} diff --git a/largest_pos_int_neg.c b/largest_pos_int_neg.c new file mode 100644 index 0000000..4d3ba32 --- /dev/null +++ b/largest_pos_int_neg.c @@ -0,0 +1,36 @@ +// 2441. Largest Positive Integer That Exists With Its Negative +#include "leetcode.h" + +/* + * given an integer array 'nums'that does not contain any zeros, find the + * largest positive integer 'k' such that '-k' also exists in the array. return + * the positive integer 'k'. if there is no such integer, return -1; + */ + +int findMaxK(int *nums, int numsSize) { + for (int i = 0; i < numsSize - 1; i++) + for (int j = i + 1; j < numsSize; j++) + if (nums[i] > nums[j]) { + int tmp = nums[i]; + nums[i] = nums[j]; + nums[j] = tmp; + } + int j = numsSize - 1, i = 0; + while (i < j) { + if (!(nums[i] + nums[j])) + return nums[j]; + else if (nums[i] + nums[j] < 0) + i++; + else + j--; + } + return -1; +} + +int main() { + int n1[] = {-1, 2 - 3, 3}, n2[] = {-1, 10, 6, 7, -7, 1}, + n3[] = {-10, 8, 6, 7, -2, -3}; + printf("%d\n", findMaxK(n1, ARRAY_SIZE(n1))); // expect: 3 + printf("%d\n", findMaxK(n2, ARRAY_SIZE(n2))); // expect: 7 + printf("%d\n", findMaxK(n3, ARRAY_SIZE(n3))); // expect: -1 +} diff --git a/largest_pos_int_neg.py b/largest_pos_int_neg.py new file mode 100644 index 0000000..f0d3fe4 --- /dev/null +++ b/largest_pos_int_neg.py @@ -0,0 +1,35 @@ +# 2441. Largest Positive Integer That Exists With Its Negative + +""" +given an integer array 'nums'that does not contain any zeros, find the +largest positive integer 'k' such that '-k' also exists in the array. return +the positive integer 'k'. if there is no such integer, return -1; +""" + + +class Solution(object): + def findMaxK(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + nums.sort() + left, right = 0, len(nums) - 1 + max_k = float("-inf") + while left < right: + if nums[left] + nums[right] == 0: + max_k = max(max_k, nums[right]) + left += 1 + right -= 1 + elif nums[left] + nums[right] < 0: + left += 1 + else: + right -= 1 + return max_k if max_k != float("-inf") else -1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.findMaxK([-1, 2, -3, 3])) + print(obj.findMaxK([-1, 10, 6, 7, -7, 1])) + print(obj.findMaxK([-10, 8, 6, 7, -2, -3])) diff --git a/largest_submatrix.c b/largest_submatrix.c new file mode 100644 index 0000000..4caa160 --- /dev/null +++ b/largest_submatrix.c @@ -0,0 +1,35 @@ +// 1727. Largest Submatrix With Rearrangements +#include "leetcode.h" + +/* + * you are given a binary matrix of size 'm * n' and you are allowed to + * rearrange the columns of the 'matrix' in any order. return the area of the + * largest submatrix within 'matrix' where every element of the submatrix is 1 + * after reordering columns optimally + */ + +int cmp(const void *a, const void *b) { return (*(int *)a - *(int *)b); } + +int largestSubmatrix(int **matrix, int matrix_size, int *matrix_col_size) { + int **heights = (int **)malloc(matrix_size * sizeof(int *)), max_area = 0; + for (int i = 0; i < matrix_size; i++) { + heights[i] = (int *)malloc(*matrix_col_size * sizeof(int)); + for (int j = 0; j < *matrix_col_size; j++) { + if (!i) + heights[i][j] = matrix[i][j]; + else + heights[i][j] = (matrix[i][j] == 1) ? heights[i - 1][j] + 1 : 0; + } + } + for (int i = 0; i < matrix_size; i++) { + qsort(heights[i], *matrix_col_size, sizeof(int), cmp); + for (int j = 0; j < *matrix_col_size; j++) { + int width = *matrix_col_size - j, height = heights[i][j]; + max_area = fmax(max_area, width * height); + } + } + for (int i = 0; i < matrix_size; i++) + free(heights[i]); + free(heights); + return max_area; +} diff --git a/largest_substr_eq_char.c b/largest_substr_eq_char.c new file mode 100644 index 0000000..b13f459 --- /dev/null +++ b/largest_substr_eq_char.c @@ -0,0 +1,32 @@ +// 1624. Largest Substring Between Two Equal Characters +#include "leetcode.h" + +/* + * given a string 's', return the length of the longest substring between two + * equal characters excluding the two characters if there is no such substring + * return -1. a substring is a contiguous sequence of characters within a + * string. + */ + +int maxLengthBetweenEqualCharacters(char *s) { + int n = strlen(s), max = -1; + int *pre_alpha = calloc(26, sizeof(int)); + int *suff_alpha = calloc(26, sizeof(int)); + for (int i = 0; i < n; i++) + if (!pre_alpha[s[i] - 'a']) + pre_alpha[s[i] - 'a'] = i + 1; + for (int i = n - 1; i >= 0; i--) + if (!suff_alpha[s[i] - 'a']) + suff_alpha[s[i] - 'a'] = i + 1; + for (int i = 0; i < 26; i++) + max = fmax(max, suff_alpha[i] - pre_alpha[i] - 1); + free(pre_alpha), free(suff_alpha); + return max; +} + +int main() { + char *s1 = "aa", *s2 = "abca", *s3 = "cbzxy"; + printf("%d\n", maxLengthBetweenEqualCharacters(s1)); // expect: 0 + printf("%d\n", maxLengthBetweenEqualCharacters(s2)); // expect: 2 + printf("%d\n", maxLengthBetweenEqualCharacters(s3)); // expect: -1 +} diff --git a/largest_substr_eq_char.py b/largest_substr_eq_char.py new file mode 100644 index 0000000..cb84a07 --- /dev/null +++ b/largest_substr_eq_char.py @@ -0,0 +1,29 @@ +# 1624. Largest Substring Between Two Equal Characters + +""" +given a string 's', return the length of the longest substring between two +equal characters excluding the two characters if there is no such substring +return -1. a substring is a contiguous sequence of characters within a +string. +""" + + +class Solution(object): + def maxLengthBetweenEqualCharacters(self, s): + """ + :type s: str + :rtype: int + """ + ans = -1 + for left in range(len(s)): + for right in range(left + 1, len(s)): + if s[left] == s[right]: + ans = max(ans, right - left - 1) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxLengthBetweenEqualCharacters("aa")) # expect: 0 + print(obj.maxLengthBetweenEqualCharacters("abca")) # expect: 2 + print(obj.maxLengthBetweenEqualCharacters("cbzxy")) # expect: -1 diff --git a/last_day_cross.cpp b/last_day_cross.cpp new file mode 100644 index 0000000..761e05b --- /dev/null +++ b/last_day_cross.cpp @@ -0,0 +1,62 @@ +// 1970. Last Day Where You Can Still Cross +#include "leetcode.h" + +/* + * there is a 1-based binary matrix where 0 represents land and 1 represents + * water. you are given integers 'row' and 'col' representing the number of rows + * and columns in the matrix, respectively. initially on day 0, the entire + * matrix is land. however each day a new cell becomes flooded with water. you + * are given a 1-based 2d array 'cells', where 'cells[i] = [ri, ci]' represnts + * that on the i'th day, the cell on the r[i'th] row and c[i'th] column (1-based + * coordinates) will be covered with water (ie. changed to 1). you want to find + * the last day that it is possible to walk from the top to the bottom by only + * walking on land cells. you can start from any cell in the top row and end in + * any cell in the bottom row. you can only travel in the four cardinal + * directions (left, right, up, down) return the last day where it is possible + * to walk from the top to the bottom by only walking on land cells + */ + +class Solution { +public: + int latestDayToCross(int row, int col, vvd(int) & cells) { + vvd(int) grid(row, vector<int>(col, 1)); + p = vector<int>(row * col + 3, -1); + int start_g = row * col + 1, end_g = row * col + 2; + for (int i = 0; i < col; i++) { + uni(i, start_g); + uni((row - 1) * col + i, end_g); + } + for (int i = row * col - 1; i >= 0; i--) { + int r = cells[i][0] - 1, c = cells[i][1] - 1; + grid[r][c] = 0; + int key = r * col + c; + for (int k = 0; k < 4; ++k) { + int n_r = r + dir[k][0], n_c = c + dir[k][1]; + if (n_r >= 0 && n_r < row && n_c >= 0 && n_c < col && !grid[n_r][n_c]) { + int n_key = n_r * col + n_c; + uni(key, n_key); + } + } + } + return row * col - 1; + } + +private: + vector<int> p; + const int dir[4][2] = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}}; + int find(int x) { return p[x] < 0 ? x : p[x] = find(p[x]); } + void uni(int x, int y) { + x = find(x), y = find(y); + if (x == y) + return; + p[y] = x; + } +}; + +int main() { + Solution obj; + vvd(int) c1 = {{1, 1}, {2, 1}, {1, 2}, {2, 2}}, + c2 = {{1, 1}, {1, 2}, {2, 1}, {2, 2}}; + printf("%d\n", obj.latestDayToCross(2, 2, c1)); // expect: 2 + printf("%d\n", obj.latestDayToCross(2, 2, c2)); // expect: 1 +} diff --git a/last_stone_weight.c b/last_stone_weight.c new file mode 100644 index 0000000..f1c0978 --- /dev/null +++ b/last_stone_weight.c @@ -0,0 +1,47 @@ +// 1046. Last Stone Weight +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * you are given an array of integers 'stones' where 'stones[i]' is the weight + * of the i'th stone. on each turn, we choose the heaviest two stones and smash + * them together suppose the heaviest two stones have weights x and y with x <= + * y. the result of the smash is if x == y, both stones are destroyed. and if x + * != y, the stone of weight x is destroyed, and the stone of weight y has new + * weight y - x. at the end of the game there is at most one stone left. return + * the weight of the remaining stone or zero. + */ + +int lastStoneWeight(int *stones, int stones_size) { + int h[1001] = {}, mx = INT_MIN; + for (int i = 0; i < stones_size; ++i) { + h[stones[i]]++; + mx = fmax(mx, stones[i]); + } + int w = mx; + h[w]--; + while (w) { + if (h[w]) { + if (mx) { + int d = mx - w; + h[d]++; + h[w]--; + w = fmax(w, d); + mx = 0; + } else { + h[w]--; + mx = w; + } + } else + --w; + } + return mx; +} + +int main() { + int s1[] = {2, 7, 4, 1, 8, 1}, s2[] = {1}; + printf("%d\n", lastStoneWeight(s1, 6)); // expect: 1 + printf("%d\n", lastStoneWeight(s2, 1)); // expect: 1 +} diff --git a/last_stone_weight.cpp b/last_stone_weight.cpp new file mode 100644 index 0000000..c7422db --- /dev/null +++ b/last_stone_weight.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + int lastStoneWeight(vector<int> &stones) { + make_heap(stones.begin(), stones.end()); + while (stones.size() > 1) { + int x = stones.front(); + pop_heap(stones.begin(), stones.end()); + stones.pop_back(); + int y = stones.front(); + pop_heap(stones.begin(), stones.end()); + stones.pop_back(); + if (x == y) + continue; + stones.push_back(x - y); + push_heap(stones.begin(), stones.end()); + } + return stones.size() ? stones.front() : 0; + } +}; + +int main() {} diff --git a/latest_time_catch_bus.c b/latest_time_catch_bus.c new file mode 100644 index 0000000..0f280d6 --- /dev/null +++ b/latest_time_catch_bus.c @@ -0,0 +1,48 @@ +// 2332. The Latest Time to Catch a Bus +#include "leetcode.h" + +/* + * given a 0-indexed array 'buses' of length 'n' where 'buses[i]' represents the + * departure time of the i'th bus. you are also given a 0-indexed array + * 'passengers' of length 'm' where 'passengers[j]' represents the arrival time + * of the j'th passenger. all bus departure times are unique. all passenger + * arrival times are unique. return the latest time you may arrive at the bus + * station to catch a bus. you cannot arrive at the same time as another + * passenger. + */ + +int cmp(const void *a, const void *b) { + if (*(int *)a == *(int *)b) + return 0; + return *(int *)a < *(int *)b ? -1 : 1; +} + +int latestTimeCatchTheBus(int *buses, int busesSize, int *passengers, + int passengersSize, int capacity) { + qsort(buses, busesSize, sizeof(int), cmp); + qsort(passengers, passengersSize, sizeof(int), cmp); + int p = 0, last_board = -1, last_bus = busesSize - 1, j; + for (int i = 0; i < busesSize; i++) + for (j = 0; j < capacity && p < passengersSize && passengers[p] <= buses[i]; + j++) { + last_board = i; + p++; + } + if (last_board != last_bus) + return buses[last_bus]; + p--; + if (j < capacity && passengers[p] + 1 <= buses[last_board]) + return buses[last_board]; + while (p && passengers[p] - 1 == passengers[p - 1]) + p--; + return passengers[p] - 1; +} + +int main() { + int b1[] = {10, 20}, p1[] = {2, 17, 18, 19}, b2[] = {20, 30, 10}, + p2[] = {19, 13, 26, 4, 25, 11, 21}; + printf("%d\n", latestTimeCatchTheBus(b1, ARRAY_SIZE(b1), p1, ARRAY_SIZE(p1), + 2)); // expect: 16 + printf("%d\n", latestTimeCatchTheBus(b2, ARRAY_SIZE(b2), p2, ARRAY_SIZE(p2), + 2)); // expect: 20 +} diff --git a/latest_time_catch_bus.py b/latest_time_catch_bus.py new file mode 100644 index 0000000..3e1b1a8 --- /dev/null +++ b/latest_time_catch_bus.py @@ -0,0 +1,62 @@ +# 2332. The Latest Time to Catch a Bus + +""" +given a 0-indexed array 'buses' of length 'n' where 'buses[i]' represents the +departure time of the i'th bus. you are also given a 0-indexed array +'passengers' of length 'm' where 'passengers[j]' represents the arrival time +of the j'th passenger. all bus departure times are unique. all passenger +arrival times are unique. return the latest time you may arrive at the bus +station to catch a bus. you cannot arrive at the same time as another +passenger. +""" + + +class Solution(object): + def latestTimeCatchTheBus(self, buses, passengers, capacity): + """ + :type buses: List[int] + :type passengers: List[int] + :type capacity: int + :rtype: int + """ + buses.sort() + passengers.sort() + i, j = 0, 0 + n, m = len(buses), len(passengers) + curr_cap = 0 + while i < n: + curr_cap = 0 + while j < m and curr_cap < capacity and passengers[j] <= buses[i]: + j += 1 + curr_cap += 1 + if i == n - 1: + j -= 1 + if curr_cap < capacity: + time = buses[i] + while j >= 0 and time == passengers[j]: + time -= 1 + j -= 1 + return time + else: + time = passengers[j] - 1 + j -= 1 + while j <= 0 and time == passengers[j]: + time -= 1 + j -= 1 + return time + i += 1 + return buses[-1] + + +if __name__ == "__main__": + obj = Solution() + print( + obj.latestTimeCatchTheBus( + buses=[10, 20], passengers=[2, 17, 18, 19], capacity=2 + ) + ) + print( + obj.latestTimeCatchTheBus( + buses=[20, 30, 10], passengers=[19, 13, 26, 4, 25, 11, 21], capacity=2 + ) + ) diff --git a/leaf_similar_trees.c b/leaf_similar_trees.c new file mode 100644 index 0000000..f902b2c --- /dev/null +++ b/leaf_similar_trees.c @@ -0,0 +1,39 @@ +// 872. Leaf-Similar Trees +#include "leetcode.h" + +/* + * consider all levels of a binary tree, from left to right order, the value of + * those leaves form a leaf value sequence. two binary trees are considered leaf + * similar if their leafe value sequence is the same. return 1 if and only if + * the two given trees with head nodes 'root1' and 'root2' are leaf-similar. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +void get_leaf_values(struct TreeNode *root, int *arr, int *length) { + if (!root) + return; + if (!root->left && !root->right) + arr[(*length)++] = root->val; + return; + get_leaf_values(root->left, arr, length); + get_leaf_values(root->right, arr, length); +} + +bool leafSimilar(struct TreeNode *root1, struct TreeNode *root2) { + int a[100] = {0}, b[100] = {0}, len_a = 0, len_b = 0; + + get_leaf_values(root1, a, &len_a); + get_leaf_values(root2, b, &len_b); + if (len_a != len_b) + return 0; + + for (int i = 0; i < len_a; i++) + if (a[i] != b[i]) + return 0; + return 1; +} diff --git a/leaf_similar_trees.cpp b/leaf_similar_trees.cpp new file mode 100644 index 0000000..319fbbf --- /dev/null +++ b/leaf_similar_trees.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" + +class Solution { +public: + bool leafSimilar(TreeNode *root1, TreeNode *root2) { + stack<TreeNode *> s1, s2; + s1.push(root1); + s2.push(root2); + while (!s1.empty() && !s2.empty()) + if (dfs(s1) != dfs(s2)) + return false; + return s1.empty() && s2.empty(); + } + +private: + int dfs(stack<TreeNode *> &s) { + while (true) { + TreeNode *node = s.top(); + s.pop(); + if (node->right) + s.push(node->right); + if (node->left) + s.push(node->left); + if (!node->left && !node->right) + return node->val; + } + } +}; diff --git a/leaf_similar_trees.py b/leaf_similar_trees.py new file mode 100644 index 0000000..c6e529b --- /dev/null +++ b/leaf_similar_trees.py @@ -0,0 +1,44 @@ +# 872. Leaf-Similar Trees + +""" +consider all levels of a binary tree, from left to right order, the value of +those leaves form a leaf value sequence. two binary trees are considered leaf +similar if their leafe value sequence is the same. return 1 if and only if +the two given trees with head nodes 'root1' and 'root2' are leaf-similar. +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def leafSimilar(self, root1, root2): + """ + :type root1: TreeNode + :type root2: TreeNode + :rtype: bool + """ + + def dfs(root): + if root is None: + return [] + leaves = dfs(root.left) + dfs(root.right) + return leaves or [root.val] + + return dfs(root1) == dfs(root2) + + +if __name__ == "__main__": + obj = Solution() + print( + obj.leafSimilar( + root1=[3, 5, 1, 6, 2, 9, 8, null, null, 7, 4], + root2=[3, 5, 1, 6, 7, 4, 2, null, null, null, null, null, null, 9, 8], + ) + ) # expect: True + print(obj.leafSimilar(root1=[1, 2, 3], root2=[1, 3, 2])) # expect: False diff --git a/leaf_similar_trees.rs b/leaf_similar_trees.rs new file mode 100644 index 0000000..6dcaae1 --- /dev/null +++ b/leaf_similar_trees.rs @@ -0,0 +1,44 @@ +#[derive(Debug, PartialEq, Eq)] +pub struct TreeNode { + pub val: i32, + pub left: Option<Rc<RefCell<TreeNode>>>, + pub right: Option<Rc<RefCell<TreeNode>>> +} + +impl TreeNode { + #[inline] + pub fn new(val: i32) -> Self { + TreeNode { + val, + left: None, + right: None + } + } +} + +use std::rc::Rc; +use std::cell::RefCell; +impl Solution { + pub fn leaf_similar(root1: Option<Rc<RefCell<TreeNode>>>, root2: Option<Rc<RefCell<TreeNode>>>) -> bool { + let mut leaves1 = Vec::<i32>::new(); + Solution::get_leaves(root1, &mut leaves1); + let mut leaves2 = Vec::<i32>::new(); + Solution::get_leaves(root2, &mut leaves2); + leaves1 == leaves2 + } + fn get_leaves(node: Option<Rc<RefCell<TreeNode>>>, leaves: &mut Vec<i32>) { + if let Some(node) = node { + let node = node.borrow(); + if node.left == None && node.right == None { + leaves.push(node.val); + } else { + if let Some(ref left_node) = node.left { + Solution::get_leaves(Some(Rc::clone(left_node)), leaves); + } + if let Some(ref right_node) = node.right { + Solution::get_leaves(Some(Rc::clone(right_node)), leaves); + } + } + } + } +} diff --git a/least_num_unique_int.c b/least_num_unique_int.c new file mode 100644 index 0000000..4e4b4f6 --- /dev/null +++ b/least_num_unique_int.c @@ -0,0 +1,41 @@ +// 1481. Least Number of Unique Integers after K Removals +#include "leetcode.h" + +/* + * given an array of integers 'arr' and an integer 'k', find the least number of + * unique integers after removing exactly 'k' elements. + */ + +int cmp(const void *a, const void *b) { + return *(const int *)a > *(const int *)b; +} + +int findLeastNumOfUniqueInts(int *arr, int arr_size, int k) { + qsort(arr, arr_size, sizeof(int), cmp); + int idx = 0, cnt = 0, ans = 0; + int *tmp = (int *)malloc(arr_size * sizeof(int)); + for (int i = 0; i < arr_size; i++) { + int j = i; + while (j < arr_size && arr[j] == arr[i]) + cnt++, j++; + tmp[idx++] = cnt; + i = j - 1; + cnt = 0; + } + qsort(tmp, idx, sizeof(int), cmp); + for (int i = 0; i < idx; i++) { + ans += tmp[i]; + if (ans >= k) { + ans = (ans == k) ? idx - i - 1 : idx - i; + break; + } + } + free(tmp); + return ans; +} + +int main() { + int a1[] = {5, 5, 4}, a2[] = {4, 3, 1, 1, 3, 3, 2}; + printf("%d\n", findLeastNumOfUniqueInts(a1, ARRAY_SIZE(a1), 1)); // expect: 1 + printf("%d\n", findLeastNumOfUniqueInts(a2, ARRAY_SIZE(a2), 3)); // expect: 2 +} diff --git a/least_num_unique_int.py b/least_num_unique_int.py new file mode 100644 index 0000000..0ccacb7 --- /dev/null +++ b/least_num_unique_int.py @@ -0,0 +1,36 @@ +# 1481. Least Number of Unique Integers after K Removals +from collections import Counter + +""" +given an array of integers 'arr' and an integer 'k', find the least number of +unique integers after removing exactly 'k' elements. +""" + + +class Solution(object): + def findLeastNumOfUniqueInts(self, arr, k): + """ + :type arr: List[int] + :type k: int + :rtype: int + """ + mp = collections.Counter(arr) + v = list(mp.values()) + cnt = 0 + v.sort() + for i in range(len(v)): + if k > v[i]: + k -= v[i] + v[i] = 0 + else: + v[i] -= k + k = 0 + if v[i] != 0: + cnt += 1 + return cnt + + +if __name__ == "__main__": + obj = Solution() + print(obj.findLeastNumOfUniqueInts(arr=[5, 5, 4], k=1)) + print(obj.findLeastNumOfUniqueInts(arr=[4, 3, 1, 1, 3, 3, 2], k=3)) diff --git a/leetcode.h b/leetcode.h new file mode 100644 index 0000000..7a4095b --- /dev/null +++ b/leetcode.h @@ -0,0 +1,54 @@ +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdbool.h> +#include <limits.h> +#include <ctype.h> +#include <stdint.h> +#include "lib/uthash/src/uthash.h" + +#ifdef __cplusplus +#include <bits/stdc++.h> +using namespace std; + +#define vvd(data) vector<vector<data>> + +struct ListNode { + int val; + ListNode *next; + ListNode() : val(0), next(nullptr) {} + ListNode(int x) : val(x), next(nullptr) {} + ListNode(int x, ListNode *next) : val(x), next(next) {} +}; + +struct TreeNode { + int val; + TreeNode *left; + TreeNode *right; + TreeNode() : val(0), left(nullptr), right(nullptr) {} + TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} + TreeNode(int x, TreeNode *left, TreeNode *right) + : val(x), left(left), right(right) {} +}; + +class Node { +public: + int val; + vector<Node *> children; + Node() {} + Node(int _val) { val = _val; } + Node(int _val, vector<Node *> _children) { + val = _val; + children = _children; + } +}; +#endif //__cplusplus + +#define IS_ARRAY(value) \ + (!__builtin_types_compatible_p(typeof((value)), typeof(&(value)[0]))) + +#define ARRAY_SIZE(array) \ + (__builtin_choose_expr(IS_ARRAY((array)), \ + sizeof((array)) / sizeof((array)[0]), (void)0)) + diff --git a/lemonade_change.c b/lemonade_change.c new file mode 100644 index 0000000..25c9eaf --- /dev/null +++ b/lemonade_change.c @@ -0,0 +1,40 @@ +// 860. Lemonade Change +#include <stdbool.h> +#include <stdio.h> + +/* + * at a lemonade stand, each lemonade costs $5. customers are standing in a + * queue to buy from you and order one at a time. each customer will only buy + * one lemonade and pay with either $5, $10, or $20 bill. you must provide the + * correct change to each customer so that the net transaction is that the + * customer pays $5. note that you do not have any change in hand at first. + * given an integer array 'bills' where 'bills[i]' is the bill the i'th customer + * pays, return true if you can provide every customer with the correct change, + * or false otherwise + */ + +bool lemonadeChange(int *bills, int bills_size) { + int five = 0, ten = 0; + while (bills_size--) { + switch (*bills++) { + case 5: + ++five; + break; + case 10: + ++ten; + break; + case 20: + !ten ? five -= 3 : --ten, --five; + break; + } + if (five < 0) + return false; + } + return true; +} + +int main() { + int b1[] = {5, 5, 5, 10, 20}, b2[] = {5, 5, 10, 10, 20}; + printf("%d\n", lemonadeChange(b1, 5)); // expect: 1 + printf("%d\n", lemonadeChange(b2, 5)); // expect: 0 +} diff --git a/lemonade_change.py b/lemonade_change.py new file mode 100644 index 0000000..22e3362 --- /dev/null +++ b/lemonade_change.py @@ -0,0 +1,41 @@ +# 860. Lemonade Change + +""" +at a lemonade stand, each lemonade costs $5. customers are standing in a +queue to buy from you and order one at a time. each customer will only buy +one lemonade and pay with either $5, $10, or $20 bill. you must provide the +correct change to each customer so that the net transaction is that the +customer pays $5. note that you do not have any change in hand at first. +given an integer array 'bills' where 'bills[i]' is the bill the i'th customer +pays, return true if you can provide every customer with the correct change, +or false otherwise +""" + + +class Solution(object): + def lemonadeChange(self, bills): + fives, tens = 0, 0 + for b in bills: + if b == 5: + fives += 1 + elif b == 10: + if fives == 0: + return False + else: + fives -= 1 + tens += 1 + else: + if tens > 0 and fives > 0: + tens -= 1 + fives -= 1 + elif fives >= 3: + fives -= 3 + else: + return False + return True + + +if __name__ == "__main__": + obj = Solution() + print(obj.lemonadeChange([5, 5, 5, 10, 20])) # expect: True + print(obj.lemonadeChange([5, 5, 10, 10, 20])) # expect: False diff --git a/len_longest_subarr_k.c b/len_longest_subarr_k.c new file mode 100644 index 0000000..706483c --- /dev/null +++ b/len_longest_subarr_k.c @@ -0,0 +1,50 @@ +// 2958. Length of Longest Subarray With at Most K Frequency +#include "leetcode.h" + +/* + * given an integer array 'nums' and an integer 'k'. the frequency of an element + * x is the number of times it occurs in an array. an array is called good if + * the frequency of each element in this array is less than or equal to 'k'. + * return the length of the longest good subarray of 'nums' a subarray is a + * contiguous non empty sequence of elements within an array + */ + +typedef struct { + UT_hash_handle hh; + int num; + int cnt; +} h_elem; + +int maxSubarrayLength(int *nums, int numsSize, int k) { + h_elem *freq = NULL, *t, *s; + int left = 0, more = 0; + for (int right = 0; right < numsSize; right++) { + HASH_FIND_INT(freq, &nums[right], t); + if (t) { + t->cnt++; + } else { + t = calloc(sizeof(h_elem), 1); + t->num = nums[right]; + t->cnt = 1; + HASH_ADD_INT(freq, num, t); + } + if (t->cnt == k + 1) + more++; + if (more) { + HASH_FIND_INT(freq, &nums[left], s); + s->cnt--; + if (s->cnt == k) + more--; + left++; + } + } + return numsSize - left; +} + +int main() { + int n1[] = {1, 2, 3, 1, 2, 3, 1, 2}, n2[] = {1, 2, 1, 2, 1, 2, 1, 2}, + n3[] = {5, 5, 5, 5, 5, 5, 5}; + printf("%d\n", maxSubarrayLength(n1, ARRAY_SIZE(n1), 2)); // expect: 6 + printf("%d\n", maxSubarrayLength(n2, ARRAY_SIZE(n2), 1)); // expect: 2 + printf("%d\n", maxSubarrayLength(n3, ARRAY_SIZE(n3), 4)); // expect: 4 +} diff --git a/len_longest_subarr_k.py b/len_longest_subarr_k.py new file mode 100644 index 0000000..b97a849 --- /dev/null +++ b/len_longest_subarr_k.py @@ -0,0 +1,35 @@ +# 2958. Length of Longest Subarray With at Most K Frequency +from collections import Counter + +""" +given an integer array 'nums' and an integer 'k'. the frequency of an element +x is the number of times it occurs in an array. an array is called good if +the frequency of each element in this array is less than or equal to 'k'. +return the length of the longest good subarray of 'nums' a subarray is a +contiguous non empty sequence of elements within an array +""" + + +class Solution(object): + def maxSubarrayLength(self, nums, k): + """ + :type nums: List[int] + :type k: int + :rtype: int + """ + cnt = Counter() + ans, i = 0, 0 + for j in range(len(nums)): + cnt[nums[j]] += 1 + while cnt[nums[j]] > k: + cnt[nums[i]] -= 1 + i += 1 + ans = max(ans, j - i + 1) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxSubarrayLength(nums=[1, 2, 3, 1, 2, 3, 1, 2], k=2)) + print(obj.maxSubarrayLength(nums=[1, 2, 1, 2, 1, 2, 1, 2], k=1)) + print(obj.maxSubarrayLength(nums=[5, 5, 5, 5, 5, 5, 5], k=4)) diff --git a/length_last_word.c b/length_last_word.c new file mode 100644 index 0000000..2316885 --- /dev/null +++ b/length_last_word.c @@ -0,0 +1,31 @@ +// 58. Length of Last Word +#include "leetcode.h" + +/* + * given a string 's' consisting of words and spaces, return the length of the + * last word in the string. a word is a maximal substring consisting of non + * space characters only. + */ + +int lengthOfLastWord(char *s) { + int ans = 0, i = strlen(s) - 1; + if (s[i] == ' ') + while (i >= 0 && s[i] == ' ') + i--; + while (i >= 0) { + if (s[i] == ' ') + break; + if ((s[i] >= 97 && s[i] <= 122) || (s[i] >= 65 && s[i] <= 90)) + ans++; + i--; + } + return ans; +} + +int main() { + char *s1 = "Hello World", *s2 = " fly me to the moon ", + *s3 = "luffy is still joyboy"; + printf("%d\n", lengthOfLastWord(s1)); // expect: 5 + printf("%d\n", lengthOfLastWord(s2)); // expect: 4 + printf("%d\n", lengthOfLastWord(s3)); // expect: 6 +} diff --git a/length_last_word.py b/length_last_word.py new file mode 100644 index 0000000..c467206 --- /dev/null +++ b/length_last_word.py @@ -0,0 +1,29 @@ +# 58. Length of Last Word + +""" +given a string 's' consisting of words and spaces, return the length of the +last word in the string. a word is a maximal substring consisting of non +space characters only. +""" + + +class Solution(object): + def lengthOfLastWord(self, s): + """ + :type s: str + :rtype: int + """ + end = len(s) - 1 + while end > 0 and s[end] == " ": + end -= 1 + begin = end + while begin >= 0 and s[begin] != " ": + begin -= 1 + return end - begin + + +if __name__ == "__main__": + obj = Solution() + print(obj.lengthOfLastWord("Hello World")) + print(obj.lengthOfLastWord(" fly me to the moon ")) + print(obj.lengthOfLastWord("luffy is still joyboy")) diff --git a/letter_combo_number.c b/letter_combo_number.c new file mode 100644 index 0000000..ae2c247 --- /dev/null +++ b/letter_combo_number.c @@ -0,0 +1,69 @@ +// 17. Letter Combinations of a Phone Number +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a string containing digits 2 - 9 inclusive, return all possible letter + * combinations that the number could represent. return the answer in any order. + * a mapping of digits to letters (just like on the telephone buttons) is given + * below [see image]. note that 1 does not map to any letters. + */ + +char **letterCombinations(char *digits, int *return_size) { + int len = strlen(digits); + if (!len) { + *return_size = 0; + return NULL; + } + char pattern[10][5] = {"", "", "abc", "def", "ghi", + "jkl", "mno", "pqrs", "tuv", "wxyz"}; + int *order = malloc(len * sizeof(int)); + int *curr = calloc(len, sizeof(int)); + curr[0] = -1; + int l, size = 1, i, j; + for (i = 0; i < len; i++) { + l = strlen(pattern[digits[i] - '0']); + size *= l; + order[i] = l; + } + char **ans = (char **)malloc(size * sizeof(char *)); + for (i = 0; i < size; i++) { + ans[i] = malloc((len + 1) * sizeof(char)); + curr[0]++; + int id = 0; + while (1) { + if (curr[id] < order[id]) + break; + else { + curr[id + 1]++; + curr[id] = curr[id] % order[id]; + id++; + } + } + for (j = 0; j < len; j++) + ans[i][j] = pattern[digits[j] - '0'][curr[j]]; + ans[i][len] = '\0'; + } + *return_size = size; + free(order), free(curr); + return ans; +} + +int main() { + char d1[] = {"23"}, d2[] = {""}, d3[] = {"2"}; + int rs1[] = {}, rs2[] = {}, rs3[] = {}; + char **lc1 = letterCombinations(d1, rs1); + char **lc2 = letterCombinations(d2, rs2); + char **lc3 = letterCombinations(d3, rs3); + for (int i = 0; i < 9; i++) + printf("%s ", + lc1[i]); // expect: "ad","ae","af","bd","be","bf","cd","ce","cf" + printf("\n"); + for (int i = 0; i < 1; i++) + printf("%s ", lc2[i]); // expect: NULL + printf("\n"); + for (int i = 0; i < 3; i++) + printf("%s ", lc3[i]); // expect: "a","b","c" + printf("\n"); +} diff --git a/letter_combo_number.cpp b/letter_combo_number.cpp new file mode 100644 index 0000000..c15a628 --- /dev/null +++ b/letter_combo_number.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class Solution { +public: + vector<string> letterCombinations(string digits) { + if (digits.empty()) + return {}; + vector<string> ans; + ans.push_back(""); + for (auto digit : digits) { + vector<string> tmp; + for (auto candidate : nums[digit - '0']) + for (auto s : ans) + tmp.push_back(s + candidate); + ans.swap(tmp); + } + for (int i = 0; i < digits.size(); i++) + cout << ans[i]; + return ans; + } + +private: + const vector<string> nums = {"", "", "abc", "def", "ghi", + "jkl", "mno", "pqrs", "tuv", "wxyz"}; +}; + +int main() { + string digits = "23"; + cout << digits << endl; + Solution obj; + obj.letterCombinations(digits); +} diff --git a/letter_tile_possibilities.c b/letter_tile_possibilities.c new file mode 100644 index 0000000..3b9268c --- /dev/null +++ b/letter_tile_possibilities.c @@ -0,0 +1,35 @@ +// 1079. Letter Tile Possibilities +#include "leetcode.h" + +/* + * given 'n' tiles where each tile has one letter ('tiles[i]') printed on it. + * return the number of possible non-empty letters printed on those tiles. + */ + +void dfs(int *alpha, int *sum) { + for (int i = 0; i < 26; i++) { + if (!alpha[i]) + continue; + (*sum)++; + alpha[i]--; + dfs(alpha, sum); + alpha[i]++; + } +} + +int numTilePossibilities(char *tiles) { + int *alpha = calloc(26, sizeof(int)); + for (int i = 0; i < strlen(tiles); i++) + alpha[tiles[i] - 'A']++; + int ans = 0; + dfs(alpha, &ans); + free(alpha); + return ans; +} + +int main() { + char *t1 = "AAB", *t2 = "AAABBC", *t3 = "V"; + printf("%d\n", numTilePossibilities(t1)); // expect: 8 + printf("%d\n", numTilePossibilities(t2)); // expect: 188 + printf("%d\n", numTilePossibilities(t3)); // expect: 1 +} diff --git a/letter_tile_possibilities.py b/letter_tile_possibilities.py new file mode 100644 index 0000000..3d5e883 --- /dev/null +++ b/letter_tile_possibilities.py @@ -0,0 +1,31 @@ +# 1079. Letter Tile Possibilities + +""" +given 'n' tiles where each tile has one letter ('tiles[i]') printed on it. +return the number of possible non-empty letters printed on those tiles. +""" + + +class Solution(object): + def numTilePossibilities(self, tiles): + """ + :type tiles: str + :rtype: int + """ + ans = set() + + def dfs(path, tiles): + if path: + ans.add(path) + for i in range(len(tiles)): + dfs(path + tiles[i], tiles[:i] + tiles[i + 1 :]) + + dfs("", tiles) + return len(ans) + + +if __name__ == "__main__": + obj = Solution() + print(obj.numTilePossibilities("AAB")) + print(obj.numTilePossibilities("AAABBC")) + print(obj.numTilePossibilities("V")) diff --git a/lexicographical_numbers.cpp b/lexicographical_numbers.cpp new file mode 100644 index 0000000..55e9fe3 --- /dev/null +++ b/lexicographical_numbers.cpp @@ -0,0 +1,26 @@ +// dnw +#include "leetcode.h" + +class Solution { +public: + vector<int> ans; + vector<int> lexicalOrder(int n) { + ans.resize(n); + int pos = 0; + for (int i = 1; i <= 9 && i <= n; i++) + helper(i, n, pos); + return ans; + } + +private: + void helper(int i, int n, int pos) { + ans[pos++] = i; + int tmp; + for (int j = 0; j <= 9; j++) { + tmp = i * 10 + j; + if (tmp > n) + break; + helper(tmp, n, pos); + } + } +}; diff --git a/lexicographically_small_string.c b/lexicographically_small_string.c new file mode 100644 index 0000000..e635184 --- /dev/null +++ b/lexicographically_small_string.c @@ -0,0 +1,44 @@ +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int unionFind(int *u, int val) { + if (u[val] == val) + return val; + return unionFind(u, u[val]); +} + +bool unionSet(int *u, int a, int b) { + int findA = unionFind(u, a), findB = unionFind(u, b); + if (findA == findB) + return false; + if (findA < findB) + u[findB] = u[findA]; + else + u[findA] = u[findB]; + return true; +} + +char *smallestEquivalentString(char *s1, char *s2, char *baseStr) { + int *table = malloc(26 * sizeof(int)); + for (int i = 0; i < 26; i++) + table[i] = i; + for (int i = 0; i < strlen(s1); i++) + unionSet(table, s1[i] - 'a', s2[i] - 'a'); + int ansLen = strlen(baseStr); + char *ans = malloc((ansLen + 1) * sizeof(int)); + ans[ansLen] = '\0'; + for (int i = 0; i < ansLen; i++) + ans[i] = unionFind(table, baseStr[i] - 'a') + 'a'; + return ans; +} + +int main() { + printf("%s\n", smallestEquivalentString("parker", "morris", + "parser")); // expect: makkek + printf("%s\n", + smallestEquivalentString("hello", "world", "hold")); // expect: hdld + printf("%s\n", smallestEquivalentString("leetcode", "programs", + "sourcecode")); // expect: aauaaaaada +} diff --git a/lexicographically_small_string.cpp b/lexicographically_small_string.cpp new file mode 100644 index 0000000..3a58189 --- /dev/null +++ b/lexicographically_small_string.cpp @@ -0,0 +1,42 @@ +#include "leetcode.h" + +/* + * given: 2 strings of same length ('s1', 's2'), & a string 'baseStr' + * s1[i] and s2[i] are equivalent characters + * eg. s1 = "abc", s2 = "cde", 'a' == 'c', 'b' == 'd', etc. + * return lexicographically smallest equivalent string of 'baseStr' by using + * equivalency information from 's1' & 's2' + */ + +class Solution { +public: + // union find + string smallestEquivalentString(string s1, string s2, string baseStr) { + vector<int> ds(26, -1); + for (auto i = 0; i < s1.size(); ++i) + dsMerge(ds, s1[i] - 'a', s2[i] - 'a'); + for (auto i = 0; i < baseStr.size(); ++i) + baseStr[i] = dsFind(ds, baseStr[i] - 'a') + 'a'; + return baseStr; + } + +private: + int dsFind(vector<int> &ds, int p) { + return ds[p] == -1 ? p : ds[p] = dsFind(ds, ds[p]); + } + void dsMerge(vector<int> &ds, int p1, int p2) { + p1 = dsFind(ds, p1), p2 = dsFind(ds, p2); + if (p1 != p2) + ds[max(p1, p2)] = min(p1, p2); + } +}; + +int main() { + Solution obj; + cout << obj.smallestEquivalentString("parker", "morris", + "parser"); // expect: makkek + cout << obj.smallestEquivalentString("hello", "world", "hold"); // expect: + // hdld + cout << obj.smallestEquivalentString("leetcode", "programs", + "sourcecode"); // expect: aauaaaaada +} diff --git a/lfu_cache.c b/lfu_cache.c new file mode 100644 index 0000000..f004d74 --- /dev/null +++ b/lfu_cache.c @@ -0,0 +1,123 @@ +// 460. LFU Cache +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#define MAX_CACHE_ITEM 3192 +#define MAX_FREQ 128 + +// https://en.wikipedia.org/wiki/Least_frequently_used +// http://dhruvbird.com/lfu.pdf + +typedef struct LFUCache LFUCache; +typedef struct LFUCache { + int freq; + int val; + bool valid; + LFUCache *prev; + LFUCache *next; +} LFUCache; + +struct Freq { + LFUCache *head; + LFUCache *tail; +}; + +struct CacheData { + int capacity; + int size; + int freqIdx; + LFUCache *cache; + struct Freq *fm; +}; + +inline void *cacheAlloc(int capacity); +inline void cacheDealloc(void *cache); +inline void refreshCache(LFUCache *item, struct CacheData *cdata, + bool newEntry); + +LFUCache *lFUCacheCreate(int capacity) { return cacheAlloc(capacity); } + +int lFUCacheGet(LFUCache *obj, int key) { + struct CacheData *cdata = (void *)obj; + LFUCache *item = &cdata->cache[key]; + if (cdata->capacity <= 0 || !item->valid) + return -1; + refreshCache(item, cdata, false); + return item->val; +} + +void lFUCachePut(LFUCache *obj, int key, int value) { + struct CacheData *cdata = (void *)obj; + LFUCache *item = &cdata->cache[key]; + if (cdata->capacity <= 0 || key >= MAX_CACHE_ITEM) + return; + refreshCache(item, cdata, !item->valid); + item->val = value; +} + +void lFUCacheFree(LFUCache *obj) { cacheDealloc(obj); } + +inline void *cacheAlloc(int capacity) { + if (capacity > MAX_CACHE_ITEM) + return NULL; + struct CacheData *cdata = calloc(1, sizeof(*cdata)); + cdata->capacity = capacity; + cdata->cache = calloc(1, sizeof(LFUCache[MAX_CACHE_ITEM])); + cdata->fm = calloc(1, sizeof(struct Freq[MAX_FREQ])); + return cdata; +} + +inline void cacheDealloc(void *cache) { + struct CacheData *cdata = cache; + free(cdata->cache); + free(cdata->fm); + free(cdata); +} + +inline void fixNode(LFUCache *item) { + LFUCache **prev = &item->prev, **next = &item->next; + *prev ? (*prev)->next = *next : 0; + *next ? (*next)->prev = *prev : 0; +} + +inline void fixHeadTailFreq(LFUCache *item, struct CacheData *cdata) { + struct Freq *fm = &cdata->fm[item->freq]; + LFUCache **head = &fm->head, **tail = &fm->tail; + item == *head ? *head = item->next : 0; + item == *tail ? *tail = item->prev : 0; + item->freq == cdata->freqIdx && !fm->head ? cdata->freqIdx++ : 0; +} + +inline void fixHeadTail(LFUCache *item, struct CacheData *cdata) { + struct Freq *fm = &cdata->fm[++item->freq]; + item->prev = NULL; + item->next = fm->head; + fm->head = fm->head ? fm->head->prev = item : (fm->tail = item); +} + +inline void evictFreqNode(struct CacheData *cdata) { + struct Freq *fm = &cdata->fm[cdata->freqIdx]; + LFUCache *lu = fm->tail; + lu->prev ? lu->prev->next = NULL : 0; + lu->freq = 0; + lu->valid = false; + !(fm->tail = lu->prev) ? fm->head = NULL : 0; + lu->prev = lu->next = NULL; +} + +inline void refreshCache(LFUCache *item, struct CacheData *cdata, + bool newEntry) { + if (newEntry) + if (cdata->size == cdata->capacity) + evictFreqNode(cdata); + else + cdata->size++; + else { + fixNode(item); + fixHeadTailFreq(item, cdata); + } + fixHeadTail(item, cdata); + if (!cdata->freqIdx || cdata->freqIdx > item->freq) + cdata->freqIdx = item->freq; + item->valid = true; +} diff --git a/lfu_cache.cpp b/lfu_cache.cpp new file mode 100644 index 0000000..c0c857a --- /dev/null +++ b/lfu_cache.cpp @@ -0,0 +1,69 @@ +// 460. LFU Cache +#include <bits/stdc++.h> +#include <unordered_map> +using namespace std; + +// https://en.wikipedia.org/wiki/Least_frequently_used +// http://dhruvbird.com/lfu.pdf + +struct Node { + int value; + list<int>::iterator itr; +}; + +class LFUCache { +private: + unordered_map<int, Node> umVal; + unordered_map<int, int> umCount; + unordered_map<int, list<int>> umlCountKey; + int lowFreq, maxCap; + +public: + LFUCache(int capacity) { + maxCap = capacity; + lowFreq = 0; + } + int get(int key) { + if (umVal.find(key) == umVal.end() || maxCap <= 0) + return -1; + put(key, umVal[key].value); + return umVal[key].value; + } + void put(int key, int value) { + if (maxCap <= 0) + return; + if (umVal.find(key) == umVal.end()) { + if (umVal.size() == maxCap) { + int del = umlCountKey[lowFreq].back(); + umlCountKey[lowFreq].pop_back(); + if (umlCountKey[lowFreq].empty()) + umlCountKey.erase(lowFreq); + umVal.erase(del); + umCount.erase(del); + } + umVal[key].value = value; + umCount[key] = 0; + lowFreq = 0; + umlCountKey[umCount[key]].push_front(key); + umVal[key].itr = umlCountKey[0].begin(); + } else { + umlCountKey[umCount[key]].erase(umVal[key].itr); + if (umlCountKey[umCount[key]].empty()) { + if (lowFreq == umCount[key]) + lowFreq++; + umlCountKey.erase(umCount[key]); + } + umVal[key].value = value; + umCount[key]++; + umlCountKey[umCount[key]].push_front(key); + umVal[key].itr = umlCountKey[umCount[key]].begin(); + } + } +}; + +int main() { + int capacity, key, value; + LFUCache *obj = new LFUCache(capacity); + int param_1 = obj->get(key); + obj->put(key, value); +} diff --git a/lib/uthash/src/utarray.h b/lib/uthash/src/utarray.h new file mode 100644 index 0000000..1fe8bc1 --- /dev/null +++ b/lib/uthash/src/utarray.h @@ -0,0 +1,252 @@ +/* +Copyright (c) 2008-2022, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* a dynamic array implementation using macros + */ +#ifndef UTARRAY_H +#define UTARRAY_H + +#define UTARRAY_VERSION 2.3.0 + +#include <stddef.h> /* size_t */ +#include <string.h> /* memset, etc */ +#include <stdlib.h> /* exit */ + +#ifdef __GNUC__ +#define UTARRAY_UNUSED __attribute__((__unused__)) +#else +#define UTARRAY_UNUSED +#endif + +#ifndef utarray_oom +#define utarray_oom() exit(-1) +#endif + +typedef void (ctor_f)(void *dst, const void *src); +typedef void (dtor_f)(void *elt); +typedef void (init_f)(void *elt); +typedef struct { + size_t sz; + init_f *init; + ctor_f *copy; + dtor_f *dtor; +} UT_icd; + +typedef struct { + unsigned i,n;/* i: index of next available slot, n: num slots */ + UT_icd icd; /* initializer, copy and destructor functions */ + char *d; /* n slots of size icd->sz*/ +} UT_array; + +#define utarray_init(a,_icd) do { \ + memset(a,0,sizeof(UT_array)); \ + (a)->icd = *(_icd); \ +} while(0) + +#define utarray_done(a) do { \ + if ((a)->n) { \ + if ((a)->icd.dtor) { \ + unsigned _ut_i; \ + for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ + (a)->icd.dtor(utarray_eltptr(a,_ut_i)); \ + } \ + } \ + free((a)->d); \ + } \ + (a)->n=0; \ +} while(0) + +#define utarray_new(a,_icd) do { \ + (a) = (UT_array*)malloc(sizeof(UT_array)); \ + if ((a) == NULL) { \ + utarray_oom(); \ + } \ + utarray_init(a,_icd); \ +} while(0) + +#define utarray_free(a) do { \ + utarray_done(a); \ + free(a); \ +} while(0) + +#define utarray_reserve(a,by) do { \ + if (((a)->i+(by)) > (a)->n) { \ + char *utarray_tmp; \ + while (((a)->i+(by)) > (a)->n) { (a)->n = ((a)->n ? (2*(a)->n) : 8); } \ + utarray_tmp=(char*)realloc((a)->d, (a)->n*(a)->icd.sz); \ + if (utarray_tmp == NULL) { \ + utarray_oom(); \ + } \ + (a)->d=utarray_tmp; \ + } \ +} while(0) + +#define utarray_push_back(a,p) do { \ + utarray_reserve(a,1); \ + if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,(a)->i++), p); } \ + else { memcpy(_utarray_eltptr(a,(a)->i++), p, (a)->icd.sz); }; \ +} while(0) + +#define utarray_pop_back(a) do { \ + if ((a)->icd.dtor) { (a)->icd.dtor( _utarray_eltptr(a,--((a)->i))); } \ + else { (a)->i--; } \ +} while(0) + +#define utarray_extend_back(a) do { \ + utarray_reserve(a,1); \ + if ((a)->icd.init) { (a)->icd.init(_utarray_eltptr(a,(a)->i)); } \ + else { memset(_utarray_eltptr(a,(a)->i),0,(a)->icd.sz); } \ + (a)->i++; \ +} while(0) + +#define utarray_len(a) ((a)->i) + +#define utarray_eltptr(a,j) (((j) < (a)->i) ? _utarray_eltptr(a,j) : NULL) +#define _utarray_eltptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j)))) + +#define utarray_insert(a,p,j) do { \ + if ((j) > (a)->i) utarray_resize(a,j); \ + utarray_reserve(a,1); \ + if ((j) < (a)->i) { \ + memmove( _utarray_eltptr(a,(j)+1), _utarray_eltptr(a,j), \ + ((a)->i - (j))*((a)->icd.sz)); \ + } \ + if ((a)->icd.copy) { (a)->icd.copy( _utarray_eltptr(a,j), p); } \ + else { memcpy(_utarray_eltptr(a,j), p, (a)->icd.sz); }; \ + (a)->i++; \ +} while(0) + +#define utarray_inserta(a,w,j) do { \ + if (utarray_len(w) == 0) break; \ + if ((j) > (a)->i) utarray_resize(a,j); \ + utarray_reserve(a,utarray_len(w)); \ + if ((j) < (a)->i) { \ + memmove(_utarray_eltptr(a,(j)+utarray_len(w)), \ + _utarray_eltptr(a,j), \ + ((a)->i - (j))*((a)->icd.sz)); \ + } \ + if ((a)->icd.copy) { \ + unsigned _ut_i; \ + for(_ut_i=0;_ut_i<(w)->i;_ut_i++) { \ + (a)->icd.copy(_utarray_eltptr(a, (j) + _ut_i), _utarray_eltptr(w, _ut_i)); \ + } \ + } else { \ + memcpy(_utarray_eltptr(a,j), _utarray_eltptr(w,0), \ + utarray_len(w)*((a)->icd.sz)); \ + } \ + (a)->i += utarray_len(w); \ +} while(0) + +#define utarray_resize(dst,num) do { \ + unsigned _ut_i; \ + if ((dst)->i > (unsigned)(num)) { \ + if ((dst)->icd.dtor) { \ + for (_ut_i = (num); _ut_i < (dst)->i; ++_ut_i) { \ + (dst)->icd.dtor(_utarray_eltptr(dst, _ut_i)); \ + } \ + } \ + } else if ((dst)->i < (unsigned)(num)) { \ + utarray_reserve(dst, (num) - (dst)->i); \ + if ((dst)->icd.init) { \ + for (_ut_i = (dst)->i; _ut_i < (unsigned)(num); ++_ut_i) { \ + (dst)->icd.init(_utarray_eltptr(dst, _ut_i)); \ + } \ + } else { \ + memset(_utarray_eltptr(dst, (dst)->i), 0, (dst)->icd.sz*((num) - (dst)->i)); \ + } \ + } \ + (dst)->i = (num); \ +} while(0) + +#define utarray_concat(dst,src) do { \ + utarray_inserta(dst, src, utarray_len(dst)); \ +} while(0) + +#define utarray_erase(a,pos,len) do { \ + if ((a)->icd.dtor) { \ + unsigned _ut_i; \ + for (_ut_i = 0; _ut_i < (len); _ut_i++) { \ + (a)->icd.dtor(utarray_eltptr(a, (pos) + _ut_i)); \ + } \ + } \ + if ((a)->i > ((pos) + (len))) { \ + memmove(_utarray_eltptr(a, pos), _utarray_eltptr(a, (pos) + (len)), \ + ((a)->i - ((pos) + (len))) * (a)->icd.sz); \ + } \ + (a)->i -= (len); \ +} while(0) + +#define utarray_renew(a,u) do { \ + if (a) utarray_clear(a); \ + else utarray_new(a, u); \ +} while(0) + +#define utarray_clear(a) do { \ + if ((a)->i > 0) { \ + if ((a)->icd.dtor) { \ + unsigned _ut_i; \ + for(_ut_i=0; _ut_i < (a)->i; _ut_i++) { \ + (a)->icd.dtor(_utarray_eltptr(a, _ut_i)); \ + } \ + } \ + (a)->i = 0; \ + } \ +} while(0) + +#define utarray_sort(a,cmp) do { \ + qsort((a)->d, (a)->i, (a)->icd.sz, cmp); \ +} while(0) + +#define utarray_find(a,v,cmp) bsearch((v),(a)->d,(a)->i,(a)->icd.sz,cmp) + +#define utarray_front(a) (((a)->i) ? (_utarray_eltptr(a,0)) : NULL) +#define utarray_next(a,e) (((e)==NULL) ? utarray_front(a) : (((a)->i != utarray_eltidx(a,e)+1) ? _utarray_eltptr(a,utarray_eltidx(a,e)+1) : NULL)) +#define utarray_prev(a,e) (((e)==NULL) ? utarray_back(a) : ((utarray_eltidx(a,e) != 0) ? _utarray_eltptr(a,utarray_eltidx(a,e)-1) : NULL)) +#define utarray_back(a) (((a)->i) ? (_utarray_eltptr(a,(a)->i-1)) : NULL) +#define utarray_eltidx(a,e) (((char*)(e) - (a)->d) / (a)->icd.sz) + +/* last we pre-define a few icd for common utarrays of ints and strings */ +static void utarray_str_cpy(void *dst, const void *src) { + char *const *srcc = (char *const *)src; + char **dstc = (char**)dst; + if (*srcc == NULL) { + *dstc = NULL; + } else { + *dstc = (char*)malloc(strlen(*srcc) + 1); + if (*dstc == NULL) { + utarray_oom(); + } else { + strcpy(*dstc, *srcc); + } + } +} +static void utarray_str_dtor(void *elt) { + char **eltc = (char**)elt; + if (*eltc != NULL) free(*eltc); +} +static const UT_icd ut_str_icd UTARRAY_UNUSED = {sizeof(char*),NULL,utarray_str_cpy,utarray_str_dtor}; +static const UT_icd ut_int_icd UTARRAY_UNUSED = {sizeof(int),NULL,NULL,NULL}; +static const UT_icd ut_ptr_icd UTARRAY_UNUSED = {sizeof(void*),NULL,NULL,NULL}; + + +#endif /* UTARRAY_H */ diff --git a/lib/uthash/src/uthash.h b/lib/uthash/src/uthash.h new file mode 100644 index 0000000..68693bf --- /dev/null +++ b/lib/uthash/src/uthash.h @@ -0,0 +1,1140 @@ +/* +Copyright (c) 2003-2022, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTHASH_H +#define UTHASH_H + +#define UTHASH_VERSION 2.3.0 + +#include <string.h> /* memcmp, memset, strlen */ +#include <stddef.h> /* ptrdiff_t */ +#include <stdlib.h> /* exit */ + +#if defined(HASH_DEFINE_OWN_STDINT) && HASH_DEFINE_OWN_STDINT +/* This codepath is provided for backward compatibility, but I plan to remove it. */ +#warning "HASH_DEFINE_OWN_STDINT is deprecated; please use HASH_NO_STDINT instead" +typedef unsigned int uint32_t; +typedef unsigned char uint8_t; +#elif defined(HASH_NO_STDINT) && HASH_NO_STDINT +#else +#include <stdint.h> /* uint8_t, uint32_t */ +#endif + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#if !defined(DECLTYPE) && !defined(NO_DECLTYPE) +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define DECLTYPE(x) (decltype(x)) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#endif +#elif defined(__MCST__) /* Elbrus C Compiler */ +#define DECLTYPE(x) (__typeof(x)) +#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE +#else /* GNU, Sun and other compilers */ +#define DECLTYPE(x) (__typeof(x)) +#endif +#endif + +#ifdef NO_DECLTYPE +#define DECLTYPE(x) +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + char **_da_dst = (char**)(&(dst)); \ + *_da_dst = (char*)(src); \ +} while (0) +#else +#define DECLTYPE_ASSIGN(dst,src) \ +do { \ + (dst) = DECLTYPE(dst)(src); \ +} while (0) +#endif + +#ifndef uthash_malloc +#define uthash_malloc(sz) malloc(sz) /* malloc fcn */ +#endif +#ifndef uthash_free +#define uthash_free(ptr,sz) free(ptr) /* free fcn */ +#endif +#ifndef uthash_bzero +#define uthash_bzero(a,n) memset(a,'\0',n) +#endif +#ifndef uthash_strlen +#define uthash_strlen(s) strlen(s) +#endif + +#ifndef HASH_FUNCTION +#define HASH_FUNCTION(keyptr,keylen,hashv) HASH_JEN(keyptr, keylen, hashv) +#endif + +#ifndef HASH_KEYCMP +#define HASH_KEYCMP(a,b,n) memcmp(a,b,n) +#endif + +#ifndef uthash_noexpand_fyi +#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ +#endif +#ifndef uthash_expand_fyi +#define uthash_expand_fyi(tbl) /* can be defined to log expands */ +#endif + +#ifndef HASH_NONFATAL_OOM +#define HASH_NONFATAL_OOM 0 +#endif + +#if HASH_NONFATAL_OOM +/* malloc failures can be recovered from */ + +#ifndef uthash_nonfatal_oom +#define uthash_nonfatal_oom(obj) do {} while (0) /* non-fatal OOM error */ +#endif + +#define HASH_RECORD_OOM(oomed) do { (oomed) = 1; } while (0) +#define IF_HASH_NONFATAL_OOM(x) x + +#else +/* malloc failures result in lost memory, hash tables are unusable */ + +#ifndef uthash_fatal +#define uthash_fatal(msg) exit(-1) /* fatal OOM error */ +#endif + +#define HASH_RECORD_OOM(oomed) uthash_fatal("out of memory") +#define IF_HASH_NONFATAL_OOM(x) + +#endif + +/* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 5U /* lg2 of initial number of buckets */ +#define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ + +/* calculate the element whose hash handle address is hhp */ +#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) +/* calculate the hash handle from element address elp */ +#define HH_FROM_ELMT(tbl,elp) ((UT_hash_handle*)(void*)(((char*)(elp)) + ((tbl)->hho))) + +#define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \ +do { \ + struct UT_hash_handle *_hd_hh_item = (itemptrhh); \ + unsigned _hd_bkt; \ + HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + (head)->hh.tbl->buckets[_hd_bkt].count++; \ + _hd_hh_item->hh_next = NULL; \ + _hd_hh_item->hh_prev = NULL; \ +} while (0) + +#define HASH_VALUE(keyptr,keylen,hashv) \ +do { \ + HASH_FUNCTION(keyptr, keylen, hashv); \ +} while (0) + +#define HASH_FIND_BYHASHVALUE(hh,head,keyptr,keylen,hashval,out) \ +do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_bkt; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, hashval) != 0) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], keyptr, keylen, hashval, out); \ + } \ + } \ +} while (0) + +#define HASH_FIND(hh,head,keyptr,keylen,out) \ +do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_hashv; \ + HASH_VALUE(keyptr, keylen, _hf_hashv); \ + HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ + } \ +} while (0) + +#ifdef HASH_BLOOM +#define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8UL) + (((HASH_BLOOM_BITLEN%8UL)!=0UL) ? 1UL : 0UL) +#define HASH_BLOOM_MAKE(tbl,oomed) \ +do { \ + (tbl)->bloom_nbits = HASH_BLOOM; \ + (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ + if (!(tbl)->bloom_bv) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ + (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ + } \ +} while (0) + +#define HASH_BLOOM_FREE(tbl) \ +do { \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ +} while (0) + +#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8U] |= (1U << ((idx)%8U))) +#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8U] & (1U << ((idx)%8U))) + +#define HASH_BLOOM_ADD(tbl,hashv) \ + HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) + +#define HASH_BLOOM_TEST(tbl,hashv) \ + HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) + +#else +#define HASH_BLOOM_MAKE(tbl,oomed) +#define HASH_BLOOM_FREE(tbl) +#define HASH_BLOOM_ADD(tbl,hashv) +#define HASH_BLOOM_TEST(tbl,hashv) (1) +#define HASH_BLOOM_BYTELEN 0U +#endif + +#define HASH_MAKE_TABLE(hh,head,oomed) \ +do { \ + (head)->hh.tbl = (UT_hash_table*)uthash_malloc(sizeof(UT_hash_table)); \ + if (!(head)->hh.tbl) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head)->hh.tbl->tail = &((head)->hh); \ + (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ + (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ + (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ + (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ + if (!(head)->hh.tbl->buckets) { \ + HASH_RECORD_OOM(oomed); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } else { \ + uthash_bzero((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + uthash_free((head)->hh.tbl->buckets, \ + HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } \ + ) \ + } \ + } \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,replaced,cmpfcn) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ +} while (0) + +#define HASH_REPLACE_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add,replaced) \ +do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ +} while (0) + +#define HASH_REPLACE(hh,head,fieldname,keylen_in,add,replaced) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ +} while (0) + +#define HASH_REPLACE_INORDER(hh,head,fieldname,keylen_in,add,replaced,cmpfcn) \ +do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ +} while (0) + +#define HASH_APPEND_LIST(hh, head, add) \ +do { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail->next = (add); \ + (head)->hh.tbl->tail = &((add)->hh); \ +} while (0) + +#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ +do { \ + do { \ + if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) { \ + break; \ + } \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +} while (0) + +#ifdef NO_DECLTYPE +#undef HASH_AKBI_INNER_LOOP +#define HASH_AKBI_INNER_LOOP(hh,head,add,cmpfcn) \ +do { \ + char *_hs_saved_head = (char*)(head); \ + do { \ + DECLTYPE_ASSIGN(head, _hs_iter); \ + if (cmpfcn(head, add) > 0) { \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + break; \ + } \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +} while (0) +#endif + +#if HASH_NONFATAL_OOM + +#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ +do { \ + if (!(oomed)) { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + if (oomed) { \ + HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \ + HASH_DELETE_HH(hh, head, &(add)->hh); \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } else { \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + } \ + } else { \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } \ +} while (0) + +#else + +#define HASH_ADD_TO_TABLE(hh,head,keyptr,keylen_in,hashval,add,oomed) \ +do { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ +} while (0) + +#endif + + +#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh,head,keyptr,keylen_in,hashval,add,cmpfcn) \ +do { \ + IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( } ) \ + } else { \ + void *_hs_iter = (head); \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \ + if (_hs_iter) { \ + (add)->hh.next = _hs_iter; \ + if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) { \ + HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add); \ + } else { \ + (head) = (add); \ + } \ + HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \ + } else { \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \ +} while (0) + +#define HASH_ADD_KEYPTR_INORDER(hh,head,keyptr,keylen_in,add,cmpfcn) \ +do { \ + unsigned _hs_hashv; \ + HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE_INORDER(hh,head,fieldname,keylen_in,hashval,add,cmpfcn) \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) + +#define HASH_ADD_INORDER(hh,head,fieldname,keylen_in,add,cmpfcn) \ + HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) + +#define HASH_ADD_KEYPTR_BYHASHVALUE(hh,head,keyptr,keylen_in,hashval,add) \ +do { \ + IF_HASH_NONFATAL_OOM( int _ha_oomed = 0; ) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (const void*) (keyptr); \ + (add)->hh.keylen = (unsigned) (keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ + IF_HASH_NONFATAL_OOM( if (!_ha_oomed) { ) \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( } ) \ + } else { \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \ +} while (0) + +#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ +do { \ + unsigned _ha_hashv; \ + HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ +} while (0) + +#define HASH_ADD_BYHASHVALUE(hh,head,fieldname,keylen_in,hashval,add) \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) + +#define HASH_ADD(hh,head,fieldname,keylen_in,add) \ + HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) + +#define HASH_TO_BKT(hashv,num_bkts,bkt) \ +do { \ + bkt = ((hashv) & ((num_bkts) - 1U)); \ +} while (0) + +/* delete "delptr" from the hash table. + * "the usual" patch-up process for the app-order doubly-linked-list. + * The use of _hd_hh_del below deserves special explanation. + * These used to be expressed using (delptr) but that led to a bug + * if someone used the same symbol for the head and deletee, like + * HASH_DELETE(hh,users,users); + * We want that to work, but by changing the head (users) below + * we were forfeiting our ability to further refer to the deletee (users) + * in the patch-up process. Solution: use scratch space to + * copy the deletee pointer, then the latter references are via that + * scratch pointer rather than through the repointed (users) symbol. + */ +#define HASH_DELETE(hh,head,delptr) \ + HASH_DELETE_HH(hh, head, &(delptr)->hh) + +#define HASH_DELETE_HH(hh,head,delptrhh) \ +do { \ + const struct UT_hash_handle *_hd_hh_del = (delptrhh); \ + if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } else { \ + unsigned _hd_bkt; \ + if (_hd_hh_del == (head)->hh.tbl->tail) { \ + (head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \ + } \ + if (_hd_hh_del->prev != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next; \ + } else { \ + DECLTYPE_ASSIGN(head, _hd_hh_del->next); \ + } \ + if (_hd_hh_del->next != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev; \ + } \ + HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh, head, "HASH_DELETE_HH"); \ +} while (0) + +/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ +#define HASH_FIND_STR(head,findstr,out) \ +do { \ + unsigned _uthash_hfstr_keylen = (unsigned)uthash_strlen(findstr); \ + HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out); \ +} while (0) +#define HASH_ADD_STR(head,strfield,add) \ +do { \ + unsigned _uthash_hastr_keylen = (unsigned)uthash_strlen((add)->strfield); \ + HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add); \ +} while (0) +#define HASH_REPLACE_STR(head,strfield,add,replaced) \ +do { \ + unsigned _uthash_hrstr_keylen = (unsigned)uthash_strlen((add)->strfield); \ + HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, replaced); \ +} while (0) +#define HASH_FIND_INT(head,findint,out) \ + HASH_FIND(hh,head,findint,sizeof(int),out) +#define HASH_ADD_INT(head,intfield,add) \ + HASH_ADD(hh,head,intfield,sizeof(int),add) +#define HASH_REPLACE_INT(head,intfield,add,replaced) \ + HASH_REPLACE(hh,head,intfield,sizeof(int),add,replaced) +#define HASH_FIND_PTR(head,findptr,out) \ + HASH_FIND(hh,head,findptr,sizeof(void *),out) +#define HASH_ADD_PTR(head,ptrfield,add) \ + HASH_ADD(hh,head,ptrfield,sizeof(void *),add) +#define HASH_REPLACE_PTR(head,ptrfield,add,replaced) \ + HASH_REPLACE(hh,head,ptrfield,sizeof(void *),add,replaced) +#define HASH_DEL(head,delptr) \ + HASH_DELETE(hh,head,delptr) + +/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. + * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. + */ +#ifdef HASH_DEBUG +#include <stdio.h> /* fprintf, stderr */ +#define HASH_OOPS(...) do { fprintf(stderr, __VA_ARGS__); exit(-1); } while (0) +#define HASH_FSCK(hh,head,where) \ +do { \ + struct UT_hash_handle *_thh; \ + if (head) { \ + unsigned _bkt_i; \ + unsigned _count = 0; \ + char *_prev; \ + for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) { \ + unsigned _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char*)(_thh->hh_prev)) { \ + HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", \ + (where), (void*)_thh->hh_prev, (void*)_prev); \ + } \ + _bkt_count++; \ + _prev = (char*)(_thh); \ + _thh = _thh->hh_next; \ + } \ + _count += _bkt_count; \ + if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ + HASH_OOPS("%s: invalid bucket count %u, actual %u\n", \ + (where), (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid hh item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev != (char*)_thh->prev) { \ + HASH_OOPS("%s: invalid prev %p, actual %p\n", \ + (where), (void*)_thh->prev, (void*)_prev); \ + } \ + _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid app item count %u, actual %u\n", \ + (where), (head)->hh.tbl->num_items, _count); \ + } \ + } \ +} while (0) +#else +#define HASH_FSCK(hh,head,where) +#endif + +/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to + * the descriptor to which this macro is defined for tuning the hash function. + * The app can #include <unistd.h> to get the prototype for write(2). */ +#ifdef HASH_EMIT_KEYS +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ +do { \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ +} while (0) +#else +#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) +#endif + +/* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ +#define HASH_BER(key,keylen,hashv) \ +do { \ + unsigned _hb_keylen = (unsigned)keylen; \ + const unsigned char *_hb_key = (const unsigned char*)(key); \ + (hashv) = 0; \ + while (_hb_keylen-- != 0U) { \ + (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ + } \ +} while (0) + + +/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at + * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx + * (archive link: https://archive.is/Ivcan ) + */ +#define HASH_SAX(key,keylen,hashv) \ +do { \ + unsigned _sx_i; \ + const unsigned char *_hs_key = (const unsigned char*)(key); \ + hashv = 0; \ + for (_sx_i=0; _sx_i < keylen; _sx_i++) { \ + hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ + } \ +} while (0) +/* FNV-1a variation */ +#define HASH_FNV(key,keylen,hashv) \ +do { \ + unsigned _fn_i; \ + const unsigned char *_hf_key = (const unsigned char*)(key); \ + (hashv) = 2166136261U; \ + for (_fn_i=0; _fn_i < keylen; _fn_i++) { \ + hashv = hashv ^ _hf_key[_fn_i]; \ + hashv = hashv * 16777619U; \ + } \ +} while (0) + +#define HASH_OAT(key,keylen,hashv) \ +do { \ + unsigned _ho_i; \ + const unsigned char *_ho_key=(const unsigned char*)(key); \ + hashv = 0; \ + for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ + hashv += _ho_key[_ho_i]; \ + hashv += (hashv << 10); \ + hashv ^= (hashv >> 6); \ + } \ + hashv += (hashv << 3); \ + hashv ^= (hashv >> 11); \ + hashv += (hashv << 15); \ +} while (0) + +#define HASH_JEN_MIX(a,b,c) \ +do { \ + a -= b; a -= c; a ^= ( c >> 13 ); \ + b -= c; b -= a; b ^= ( a << 8 ); \ + c -= a; c -= b; c ^= ( b >> 13 ); \ + a -= b; a -= c; a ^= ( c >> 12 ); \ + b -= c; b -= a; b ^= ( a << 16 ); \ + c -= a; c -= b; c ^= ( b >> 5 ); \ + a -= b; a -= c; a ^= ( c >> 3 ); \ + b -= c; b -= a; b ^= ( a << 10 ); \ + c -= a; c -= b; c ^= ( b >> 15 ); \ +} while (0) + +#define HASH_JEN(key,keylen,hashv) \ +do { \ + unsigned _hj_i,_hj_j,_hj_k; \ + unsigned const char *_hj_key=(unsigned const char*)(key); \ + hashv = 0xfeedbeefu; \ + _hj_i = _hj_j = 0x9e3779b9u; \ + _hj_k = (unsigned)(keylen); \ + while (_hj_k >= 12U) { \ + _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + + ( (unsigned)_hj_key[2] << 16 ) \ + + ( (unsigned)_hj_key[3] << 24 ) ); \ + _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ + + ( (unsigned)_hj_key[6] << 16 ) \ + + ( (unsigned)_hj_key[7] << 24 ) ); \ + hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ + + ( (unsigned)_hj_key[10] << 16 ) \ + + ( (unsigned)_hj_key[11] << 24 ) ); \ + \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + \ + _hj_key += 12; \ + _hj_k -= 12U; \ + } \ + hashv += (unsigned)(keylen); \ + switch ( _hj_k ) { \ + case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); /* FALLTHROUGH */ \ + case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); /* FALLTHROUGH */ \ + case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); /* FALLTHROUGH */ \ + case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); /* FALLTHROUGH */ \ + case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); /* FALLTHROUGH */ \ + case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); /* FALLTHROUGH */ \ + case 5: _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ + case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); /* FALLTHROUGH */ \ + case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); /* FALLTHROUGH */ \ + case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); /* FALLTHROUGH */ \ + case 1: _hj_i += _hj_key[0]; /* FALLTHROUGH */ \ + default: ; \ + } \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ +} while (0) + +/* The Paul Hsieh hash function */ +#undef get16bits +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ + || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) +#define get16bits(d) (*((const uint16_t *) (d))) +#endif + +#if !defined (get16bits) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ + +(uint32_t)(((const uint8_t *)(d))[0]) ) +#endif +#define HASH_SFH(key,keylen,hashv) \ +do { \ + unsigned const char *_sfh_key=(unsigned const char*)(key); \ + uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ + \ + unsigned _sfh_rem = _sfh_len & 3U; \ + _sfh_len >>= 2; \ + hashv = 0xcafebabeu; \ + \ + /* Main loop */ \ + for (;_sfh_len > 0U; _sfh_len--) { \ + hashv += get16bits (_sfh_key); \ + _sfh_tmp = ((uint32_t)(get16bits (_sfh_key+2)) << 11) ^ hashv; \ + hashv = (hashv << 16) ^ _sfh_tmp; \ + _sfh_key += 2U*sizeof (uint16_t); \ + hashv += hashv >> 11; \ + } \ + \ + /* Handle end cases */ \ + switch (_sfh_rem) { \ + case 3: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 16; \ + hashv ^= (uint32_t)(_sfh_key[sizeof (uint16_t)]) << 18; \ + hashv += hashv >> 11; \ + break; \ + case 2: hashv += get16bits (_sfh_key); \ + hashv ^= hashv << 11; \ + hashv += hashv >> 17; \ + break; \ + case 1: hashv += *_sfh_key; \ + hashv ^= hashv << 10; \ + hashv += hashv >> 1; \ + break; \ + default: ; \ + } \ + \ + /* Force "avalanching" of final 127 bits */ \ + hashv ^= hashv << 3; \ + hashv += hashv >> 5; \ + hashv ^= hashv << 4; \ + hashv += hashv >> 17; \ + hashv ^= hashv << 25; \ + hashv += hashv >> 6; \ +} while (0) + +/* iterate over items in a known bucket to find desired item */ +#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,hashval,out) \ +do { \ + if ((head).hh_head != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ + } else { \ + (out) = NULL; \ + } \ + while ((out) != NULL) { \ + if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ + if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \ + break; \ + } \ + } \ + if ((out)->hh.hh_next != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ + } else { \ + (out) = NULL; \ + } \ + } \ +} while (0) + +/* add an item to a bucket */ +#define HASH_ADD_TO_BKT(head,hh,addhh,oomed) \ +do { \ + UT_hash_bucket *_ha_head = &(head); \ + _ha_head->count++; \ + (addhh)->hh_next = _ha_head->hh_head; \ + (addhh)->hh_prev = NULL; \ + if (_ha_head->hh_head != NULL) { \ + _ha_head->hh_head->hh_prev = (addhh); \ + } \ + _ha_head->hh_head = (addhh); \ + if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) \ + && !(addhh)->tbl->noexpand) { \ + HASH_EXPAND_BUCKETS(addhh,(addhh)->tbl, oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (oomed) { \ + HASH_DEL_IN_BKT(head,addhh); \ + } \ + ) \ + } \ +} while (0) + +/* remove an item from a given bucket */ +#define HASH_DEL_IN_BKT(head,delhh) \ +do { \ + UT_hash_bucket *_hd_head = &(head); \ + _hd_head->count--; \ + if (_hd_head->hh_head == (delhh)) { \ + _hd_head->hh_head = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_prev) { \ + (delhh)->hh_prev->hh_next = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_next) { \ + (delhh)->hh_next->hh_prev = (delhh)->hh_prev; \ + } \ +} while (0) + +/* Bucket expansion has the effect of doubling the number of buckets + * and redistributing the items into the new buckets. Ideally the + * items will distribute more or less evenly into the new buckets + * (the extent to which this is true is a measure of the quality of + * the hash function as it applies to the key domain). + * + * With the items distributed into more buckets, the chain length + * (item count) in each bucket is reduced. Thus by expanding buckets + * the hash keeps a bound on the chain length. This bounded chain + * length is the essence of how a hash provides constant time lookup. + * + * The calculation of tbl->ideal_chain_maxlen below deserves some + * explanation. First, keep in mind that we're calculating the ideal + * maximum chain length based on the *new* (doubled) bucket count. + * In fractions this is just n/b (n=number of items,b=new num buckets). + * Since the ideal chain length is an integer, we want to calculate + * ceil(n/b). We don't depend on floating point arithmetic in this + * hash, so to calculate ceil(n/b) with integers we could write + * + * ceil(n/b) = (n/b) + ((n%b)?1:0) + * + * and in fact a previous version of this hash did just that. + * But now we have improved things a bit by recognizing that b is + * always a power of two. We keep its base 2 log handy (call it lb), + * so now we can write this with a bit shift and logical AND: + * + * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) + * + */ +#define HASH_EXPAND_BUCKETS(hh,tbl,oomed) \ +do { \ + unsigned _he_bkt; \ + unsigned _he_bkt_i; \ + struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ + UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ + _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ + sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \ + if (!_he_new_buckets) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero(_he_new_buckets, \ + sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \ + (tbl)->ideal_chain_maxlen = \ + ((tbl)->num_items >> ((tbl)->log2_num_buckets+1U)) + \ + ((((tbl)->num_items & (((tbl)->num_buckets*2U)-1U)) != 0U) ? 1U : 0U); \ + (tbl)->nonideal_items = 0; \ + for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) { \ + _he_thh = (tbl)->buckets[ _he_bkt_i ].hh_head; \ + while (_he_thh != NULL) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[_he_bkt]); \ + if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) { \ + (tbl)->nonideal_items++; \ + if (_he_newbkt->count > _he_newbkt->expand_mult * (tbl)->ideal_chain_maxlen) { \ + _he_newbkt->expand_mult++; \ + } \ + } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head != NULL) { \ + _he_newbkt->hh_head->hh_prev = _he_thh; \ + } \ + _he_newbkt->hh_head = _he_thh; \ + _he_thh = _he_hh_nxt; \ + } \ + } \ + uthash_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + (tbl)->num_buckets *= 2U; \ + (tbl)->log2_num_buckets++; \ + (tbl)->buckets = _he_new_buckets; \ + (tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ? \ + ((tbl)->ineff_expands+1U) : 0U; \ + if ((tbl)->ineff_expands > 1U) { \ + (tbl)->noexpand = 1; \ + uthash_noexpand_fyi(tbl); \ + } \ + uthash_expand_fyi(tbl); \ + } \ +} while (0) + + +/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ +/* Note that HASH_SORT assumes the hash handle name to be hh. + * HASH_SRT was added to allow the hash handle name to be passed in. */ +#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) +#define HASH_SRT(hh,head,cmpfcn) \ +do { \ + unsigned _hs_i; \ + unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ + struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ + if (head != NULL) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping != 0U) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p != NULL) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) { \ + _hs_psize++; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + if (_hs_q == NULL) { \ + break; \ + } \ + } \ + _hs_qsize = _hs_insize; \ + while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) { \ + if (_hs_psize == 0U) { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } else if ((_hs_qsize == 0U) || (_hs_q == NULL)) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else if ((cmpfcn( \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)), \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q)) \ + )) <= 0) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? \ + HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } \ + if ( _hs_tail != NULL ) { \ + _hs_tail->next = ((_hs_e != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + if (_hs_e != NULL) { \ + _hs_e->prev = ((_hs_tail != NULL) ? \ + ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \ + } \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ + } \ + if (_hs_tail != NULL) { \ + _hs_tail->next = NULL; \ + } \ + if (_hs_nmerges <= 1U) { \ + _hs_looping = 0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2U; \ + } \ + HASH_FSCK(hh, head, "HASH_SRT"); \ + } \ +} while (0) + +/* This function selects items from one hash into another hash. + * The end result is that the selected items have dual presence + * in both hashes. There is no copy of the items made; rather + * they are added into the new hash through a secondary hash + * hash handle that must be present in the structure. */ +#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ +do { \ + unsigned _src_bkt, _dst_bkt; \ + void *_last_elt = NULL, *_elt; \ + UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ + ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ + if ((src) != NULL) { \ + for (_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ + for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ + _src_hh != NULL; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + IF_HASH_NONFATAL_OOM( int _hs_oomed = 0; ) \ + _dst_hh = (UT_hash_handle*)(void*)(((char*)_elt) + _dst_hho); \ + _dst_hh->key = _src_hh->key; \ + _dst_hh->keylen = _src_hh->keylen; \ + _dst_hh->hashv = _src_hh->hashv; \ + _dst_hh->prev = _last_elt; \ + _dst_hh->next = NULL; \ + if (_last_elt_hh != NULL) { \ + _last_elt_hh->next = _elt; \ + } \ + if ((dst) == NULL) { \ + DECLTYPE_ASSIGN(dst, _elt); \ + HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + uthash_nonfatal_oom(_elt); \ + (dst) = NULL; \ + continue; \ + } \ + ) \ + } else { \ + _dst_hh->tbl = (dst)->hh_dst.tbl; \ + } \ + HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ + HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], hh_dst, _dst_hh, _hs_oomed); \ + (dst)->hh_dst.tbl->num_items++; \ + IF_HASH_NONFATAL_OOM( \ + if (_hs_oomed) { \ + HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \ + HASH_DELETE_HH(hh_dst, dst, _dst_hh); \ + _dst_hh->tbl = NULL; \ + uthash_nonfatal_oom(_elt); \ + continue; \ + } \ + ) \ + HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ + } \ + } \ + } \ + HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \ +} while (0) + +#define HASH_CLEAR(hh,head) \ +do { \ + if ((head) != NULL) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, \ + (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } \ +} while (0) + +#define HASH_OVERHEAD(hh,head) \ + (((head) != NULL) ? ( \ + (size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ + ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ + sizeof(UT_hash_table) + \ + (HASH_BLOOM_BYTELEN))) : 0U) + +#ifdef NO_DECLTYPE +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((*(char**)(&(tmp)))=(char*)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((*(char**)(&(tmp)))=(char*)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#else +#define HASH_ITER(hh,head,el,tmp) \ +for(((el)=(head)), ((tmp)=DECLTYPE(el)((head!=NULL)?(head)->hh.next:NULL)); \ + (el) != NULL; ((el)=(tmp)), ((tmp)=DECLTYPE(el)((tmp!=NULL)?(tmp)->hh.next:NULL))) +#endif + +/* obtain a count of items in the hash */ +#define HASH_COUNT(head) HASH_CNT(hh,head) +#define HASH_CNT(hh,head) ((head != NULL)?((head)->hh.tbl->num_items):0U) + +typedef struct UT_hash_bucket { + struct UT_hash_handle *hh_head; + unsigned count; + + /* expand_mult is normally set to 0. In this situation, the max chain length + * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If + * the bucket's chain exceeds this length, bucket expansion is triggered). + * However, setting expand_mult to a non-zero value delays bucket expansion + * (that would be triggered by additions to this particular bucket) + * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. + * (The multiplier is simply expand_mult+1). The whole idea of this + * multiplier is to reduce bucket expansions, since they are expensive, in + * situations where we know that a particular bucket tends to be overused. + * It is better to let its chain length grow to a longer yet-still-bounded + * value, than to do an O(n) bucket expansion too often. + */ + unsigned expand_mult; + +} UT_hash_bucket; + +/* random signature used only to find hash tables in external analysis */ +#define HASH_SIGNATURE 0xa0111fe1u +#define HASH_BLOOM_SIGNATURE 0xb12220f2u + +typedef struct UT_hash_table { + UT_hash_bucket *buckets; + unsigned num_buckets, log2_num_buckets; + unsigned num_items; + struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ + ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ + + /* in an ideal situation (all buckets used equally), no bucket would have + * more than ceil(#items/#buckets) items. that's the ideal chain length. */ + unsigned ideal_chain_maxlen; + + /* nonideal_items is the number of items in the hash whose chain position + * exceeds the ideal chain maxlen. these items pay the penalty for an uneven + * hash distribution; reaching them in a chain traversal takes >ideal steps */ + unsigned nonideal_items; + + /* ineffective expands occur when a bucket doubling was performed, but + * afterward, more than half the items in the hash had nonideal chain + * positions. If this happens on two consecutive expansions we inhibit any + * further expansion, as it's not helping; this happens when the hash + * function isn't a good fit for the key domain. When expansion is inhibited + * the hash will still work, albeit no longer in constant time. */ + unsigned ineff_expands, noexpand; + + uint32_t signature; /* used only to find hash tables in external analysis */ +#ifdef HASH_BLOOM + uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ + uint8_t *bloom_bv; + uint8_t bloom_nbits; +#endif + +} UT_hash_table; + +typedef struct UT_hash_handle { + struct UT_hash_table *tbl; + void *prev; /* prev element in app order */ + void *next; /* next element in app order */ + struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ + struct UT_hash_handle *hh_next; /* next hh in bucket order */ + const void *key; /* ptr to enclosing struct's key */ + unsigned keylen; /* enclosing struct's key len */ + unsigned hashv; /* result of hash-fcn(key) */ +} UT_hash_handle; + +#endif /* UTHASH_H */ diff --git a/lib/uthash/src/utlist.h b/lib/uthash/src/utlist.h new file mode 100644 index 0000000..08fc59a --- /dev/null +++ b/lib/uthash/src/utlist.h @@ -0,0 +1,1076 @@ +/* +Copyright (c) 2007-2022, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTLIST_H +#define UTLIST_H + +#define UTLIST_VERSION 2.3.0 + +#include <assert.h> + +/* + * This file contains macros to manipulate singly and doubly-linked lists. + * + * 1. LL_ macros: singly-linked lists. + * 2. DL_ macros: doubly-linked lists. + * 3. CDL_ macros: circular doubly-linked lists. + * + * To use singly-linked lists, your structure must have a "next" pointer. + * To use doubly-linked lists, your structure must "prev" and "next" pointers. + * Either way, the pointer to the head of the list must be initialized to NULL. + * + * ----------------.EXAMPLE ------------------------- + * struct item { + * int id; + * struct item *prev, *next; + * } + * + * struct item *list = NULL: + * + * int main() { + * struct item *item; + * ... allocate and populate item ... + * DL_APPEND(list, item); + * } + * -------------------------------------------------- + * + * For doubly-linked lists, the append and delete macros are O(1) + * For singly-linked lists, append and delete are O(n) but prepend is O(1) + * The sort macro is O(n log(n)) for all types of single/double/circular lists. + */ + +/* These macros use decltype or the earlier __typeof GNU extension. + As decltype is only available in newer compilers (VS2010 or gcc 4.3+ + when compiling c++ source) this code uses whatever method is needed + or, for VS2008 where neither is available, uses casting workarounds. */ +#if !defined(LDECLTYPE) && !defined(NO_DECLTYPE) +#if defined(_MSC_VER) /* MS compiler */ +#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ +#define LDECLTYPE(x) decltype(x) +#else /* VS2008 or older (or VS2010 in C mode) */ +#define NO_DECLTYPE +#endif +#elif defined(__MCST__) /* Elbrus C Compiler */ +#define LDECLTYPE(x) __typeof(x) +#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) +#define NO_DECLTYPE +#else /* GNU, Sun and other compilers */ +#define LDECLTYPE(x) __typeof(x) +#endif +#endif + +/* for VS2008 we use some workarounds to get around the lack of decltype, + * namely, we always reassign our tmp variable to the list head if we need + * to dereference its prev/next pointers, and save/restore the real head.*/ +#ifdef NO_DECLTYPE +#define IF_NO_DECLTYPE(x) x +#define LDECLTYPE(x) char* +#define UTLIST_SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } +#define UTLIST_NEXT(elt,list,next) ((char*)((list)->next)) +#define UTLIST_NEXTASGN(elt,list,to,next) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } +/* #define UTLIST_PREV(elt,list,prev) ((char*)((list)->prev)) */ +#define UTLIST_PREVASGN(elt,list,to,prev) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } +#define UTLIST_RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } +#define UTLIST_CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } +#else +#define IF_NO_DECLTYPE(x) +#define UTLIST_SV(elt,list) +#define UTLIST_NEXT(elt,list,next) ((elt)->next) +#define UTLIST_NEXTASGN(elt,list,to,next) ((elt)->next)=(to) +/* #define UTLIST_PREV(elt,list,prev) ((elt)->prev) */ +#define UTLIST_PREVASGN(elt,list,to,prev) ((elt)->prev)=(to) +#define UTLIST_RS(list) +#define UTLIST_CASTASGN(a,b) (a)=(b) +#endif + +/****************************************************************************** + * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * + * Unwieldy variable names used here to avoid shadowing passed-in variables. * + *****************************************************************************/ +#define LL_SORT(list, cmp) \ + LL_SORT2(list, cmp, next) + +#define LL_SORT2(list, cmp, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ + } \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + + +#define DL_SORT(list, cmp) \ + DL_SORT2(list, cmp, prev, next) + +#define DL_SORT2(list, cmp, prev, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + IF_NO_DECLTYPE(LDECLTYPE(list) _tmp;) \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); _ls_q = UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while ((_ls_psize > 0) || ((_ls_qsize > 0) && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } else if ((_ls_qsize == 0) || (!_ls_q)) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + UTLIST_CASTASGN((list)->prev, _ls_tail); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,NULL,next); UTLIST_RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + +#define CDL_SORT(list, cmp) \ + CDL_SORT2(list, cmp, prev, next) + +#define CDL_SORT2(list, cmp, prev, next) \ +do { \ + LDECLTYPE(list) _ls_p; \ + LDECLTYPE(list) _ls_q; \ + LDECLTYPE(list) _ls_e; \ + LDECLTYPE(list) _ls_tail; \ + LDECLTYPE(list) _ls_oldhead; \ + LDECLTYPE(list) _tmp; \ + int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ + if (list) { \ + _ls_insize = 1; \ + _ls_looping = 1; \ + while (_ls_looping) { \ + UTLIST_CASTASGN(_ls_p,list); \ + UTLIST_CASTASGN(_ls_oldhead,list); \ + (list) = NULL; \ + _ls_tail = NULL; \ + _ls_nmerges = 0; \ + while (_ls_p) { \ + _ls_nmerges++; \ + _ls_q = _ls_p; \ + _ls_psize = 0; \ + for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ + _ls_psize++; \ + UTLIST_SV(_ls_q,list); \ + if (UTLIST_NEXT(_ls_q,list,next) == _ls_oldhead) { \ + _ls_q = NULL; \ + } else { \ + _ls_q = UTLIST_NEXT(_ls_q,list,next); \ + } \ + UTLIST_RS(list); \ + if (!_ls_q) break; \ + } \ + _ls_qsize = _ls_insize; \ + while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ + if (_ls_psize == 0) { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } else if (_ls_qsize == 0 || !_ls_q) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else if (cmp(_ls_p,_ls_q) <= 0) { \ + _ls_e = _ls_p; UTLIST_SV(_ls_p,list); _ls_p = \ + UTLIST_NEXT(_ls_p,list,next); UTLIST_RS(list); _ls_psize--; \ + if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ + } else { \ + _ls_e = _ls_q; UTLIST_SV(_ls_q,list); _ls_q = \ + UTLIST_NEXT(_ls_q,list,next); UTLIST_RS(list); _ls_qsize--; \ + if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ + } \ + if (_ls_tail) { \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_ls_e,next); UTLIST_RS(list); \ + } else { \ + UTLIST_CASTASGN(list,_ls_e); \ + } \ + UTLIST_SV(_ls_e,list); UTLIST_PREVASGN(_ls_e,list,_ls_tail,prev); UTLIST_RS(list); \ + _ls_tail = _ls_e; \ + } \ + _ls_p = _ls_q; \ + } \ + UTLIST_CASTASGN((list)->prev,_ls_tail); \ + UTLIST_CASTASGN(_tmp,list); \ + UTLIST_SV(_ls_tail,list); UTLIST_NEXTASGN(_ls_tail,list,_tmp,next); UTLIST_RS(list); \ + if (_ls_nmerges <= 1) { \ + _ls_looping=0; \ + } \ + _ls_insize *= 2; \ + } \ + } \ +} while (0) + +/****************************************************************************** + * singly linked list macros (non-circular) * + *****************************************************************************/ +#define LL_PREPEND(head,add) \ + LL_PREPEND2(head,add,next) + +#define LL_PREPEND2(head,add,next) \ +do { \ + (add)->next = (head); \ + (head) = (add); \ +} while (0) + +#define LL_CONCAT(head1,head2) \ + LL_CONCAT2(head1,head2,next) + +#define LL_CONCAT2(head1,head2,next) \ +do { \ + LDECLTYPE(head1) _tmp; \ + if (head1) { \ + _tmp = (head1); \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(head2); \ + } else { \ + (head1)=(head2); \ + } \ +} while (0) + +#define LL_APPEND(head,add) \ + LL_APPEND2(head,add,next) + +#define LL_APPEND2(head,add,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + (add)->next=NULL; \ + if (head) { \ + _tmp = (head); \ + while (_tmp->next) { _tmp = _tmp->next; } \ + _tmp->next=(add); \ + } else { \ + (head)=(add); \ + } \ +} while (0) + +#define LL_INSERT_INORDER(head,add,cmp) \ + LL_INSERT_INORDER2(head,add,cmp,next) + +#define LL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + LL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + LL_APPEND_ELEM2(head, _tmp, add, next); \ + } else { \ + (head) = (add); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define LL_LOWER_BOUND(head,elt,like,cmp) \ + LL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define LL_LOWER_BOUND2(head,elt,like,cmp,next) \ + do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if (cmp((elt)->next, like) >= 0) { \ + break; \ + } \ + } \ + } \ + } while (0) + +#define LL_DELETE(head,del) \ + LL_DELETE2(head,del,next) + +#define LL_DELETE2(head,del,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (del))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (del)->next; \ + } \ + } \ +} while (0) + +#define LL_COUNT(head,el,counter) \ + LL_COUNT2(head,el,counter,next) \ + +#define LL_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + LL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define LL_FOREACH(head,el) \ + LL_FOREACH2(head,el,next) + +#define LL_FOREACH2(head,el,next) \ + for ((el) = (head); el; (el) = (el)->next) + +#define LL_FOREACH_SAFE(head,el,tmp) \ + LL_FOREACH_SAFE2(head,el,tmp,next) + +#define LL_FOREACH_SAFE2(head,el,tmp,next) \ + for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) + +#define LL_SEARCH_SCALAR(head,out,field,val) \ + LL_SEARCH_SCALAR2(head,out,field,val,next) + +#define LL_SEARCH_SCALAR2(head,out,field,val,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((out)->field == (val)) break; \ + } \ +} while (0) + +#define LL_SEARCH(head,out,elt,cmp) \ + LL_SEARCH2(head,out,elt,cmp,next) + +#define LL_SEARCH2(head,out,elt,cmp,next) \ +do { \ + LL_FOREACH2(head,out,next) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while (0) + +#define LL_REPLACE_ELEM2(head, el, add, next) \ +do { \ + LDECLTYPE(head) _tmp; \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ +} while (0) + +#define LL_REPLACE_ELEM(head, el, add) \ + LL_REPLACE_ELEM2(head, el, add, next) + +#define LL_PREPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + LDECLTYPE(head) _tmp; \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + _tmp = (head); \ + while (_tmp->next && (_tmp->next != (el))) { \ + _tmp = _tmp->next; \ + } \ + if (_tmp->next) { \ + _tmp->next = (add); \ + } \ + } \ + } else { \ + LL_APPEND2(head, add, next); \ + } \ +} while (0) \ + +#define LL_PREPEND_ELEM(head, el, add) \ + LL_PREPEND_ELEM2(head, el, add, next) + +#define LL_APPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (el)->next = (add); \ + } else { \ + LL_PREPEND2(head, add, next); \ + } \ +} while (0) \ + +#define LL_APPEND_ELEM(head, el, add) \ + LL_APPEND_ELEM2(head, el, add, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef LL_CONCAT2 +#define LL_CONCAT2(head1,head2,next) \ +do { \ + char *_tmp; \ + if (head1) { \ + _tmp = (char*)(head1); \ + while ((head1)->next) { (head1) = (head1)->next; } \ + (head1)->next = (head2); \ + UTLIST_RS(head1); \ + } else { \ + (head1)=(head2); \ + } \ +} while (0) + +#undef LL_APPEND2 +#define LL_APPEND2(head,add,next) \ +do { \ + if (head) { \ + (add)->next = head; /* use add->next as a temp variable */ \ + while ((add)->next->next) { (add)->next = (add)->next->next; } \ + (add)->next->next=(add); \ + } else { \ + (head)=(add); \ + } \ + (add)->next=NULL; \ +} while (0) + +#undef LL_INSERT_INORDER2 +#define LL_INSERT_INORDER2(head,add,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, add)) >= 0) { \ + (add)->next = (head); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next != NULL && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ +} while (0) + +#undef LL_DELETE2 +#define LL_DELETE2(head,del,next) \ +do { \ + if ((head) == (del)) { \ + (head)=(head)->next; \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next && ((head)->next != (del))) { \ + (head) = (head)->next; \ + } \ + if ((head)->next) { \ + (head)->next = ((del)->next); \ + } \ + UTLIST_RS(head); \ + } \ +} while (0) + +#undef LL_REPLACE_ELEM2 +#define LL_REPLACE_ELEM2(head, el, add, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = head; \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ + } \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ + } \ + } \ + (add)->next = (el)->next; \ +} while (0) + +#undef LL_PREPEND_ELEM2 +#define LL_PREPEND_ELEM2(head, el, add, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->next = (head); \ + while ((add)->next->next && ((add)->next->next != (el))) { \ + (add)->next = (add)->next->next; \ + } \ + if ((add)->next->next) { \ + (add)->next->next = (add); \ + } \ + } \ + (add)->next = (el); \ + } else { \ + LL_APPEND2(head, add, next); \ + } \ +} while (0) \ + +#endif /* NO_DECLTYPE */ + +/****************************************************************************** + * doubly linked list macros (non-circular) * + *****************************************************************************/ +#define DL_PREPEND(head,add) \ + DL_PREPEND2(head,add,prev,next) + +#define DL_PREPEND2(head,add,prev,next) \ +do { \ + (add)->next = (head); \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev = (add); \ + } else { \ + (add)->prev = (add); \ + } \ + (head) = (add); \ +} while (0) + +#define DL_APPEND(head,add) \ + DL_APPEND2(head,add,prev,next) + +#define DL_APPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (head)->prev->next = (add); \ + (head)->prev = (add); \ + (add)->next = NULL; \ + } else { \ + (head)=(add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define DL_INSERT_INORDER(head,add,cmp) \ + DL_INSERT_INORDER2(head,add,cmp,prev,next) + +#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + DL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + DL_APPEND_ELEM2(head, _tmp, add, prev, next); \ + } else { \ + (head) = (add); \ + (head)->prev = (head); \ + (head)->next = NULL; \ + } \ +} while (0) + +#define DL_LOWER_BOUND(head,elt,like,cmp) \ + DL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define DL_LOWER_BOUND2(head,elt,like,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != NULL; (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ +} while (0) + +#define DL_CONCAT(head1,head2) \ + DL_CONCAT2(head1,head2,prev,next) + +#define DL_CONCAT2(head1,head2,prev,next) \ +do { \ + LDECLTYPE(head1) _tmp; \ + if (head2) { \ + if (head1) { \ + UTLIST_CASTASGN(_tmp, (head2)->prev); \ + (head2)->prev = (head1)->prev; \ + (head1)->prev->next = (head2); \ + UTLIST_CASTASGN((head1)->prev, _tmp); \ + } else { \ + (head1)=(head2); \ + } \ + } \ +} while (0) + +#define DL_DELETE(head,del) \ + DL_DELETE2(head,del,prev,next) + +#define DL_DELETE2(head,del,prev,next) \ +do { \ + assert((head) != NULL); \ + assert((del)->prev != NULL); \ + if ((del)->prev == (del)) { \ + (head)=NULL; \ + } else if ((del) == (head)) { \ + assert((del)->next != NULL); \ + (del)->next->prev = (del)->prev; \ + (head) = (del)->next; \ + } else { \ + (del)->prev->next = (del)->next; \ + if ((del)->next) { \ + (del)->next->prev = (del)->prev; \ + } else { \ + (head)->prev = (del)->prev; \ + } \ + } \ +} while (0) + +#define DL_COUNT(head,el,counter) \ + DL_COUNT2(head,el,counter,next) \ + +#define DL_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + DL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define DL_FOREACH(head,el) \ + DL_FOREACH2(head,el,next) + +#define DL_FOREACH2(head,el,next) \ + for ((el) = (head); el; (el) = (el)->next) + +/* this version is safe for deleting the elements during iteration */ +#define DL_FOREACH_SAFE(head,el,tmp) \ + DL_FOREACH_SAFE2(head,el,tmp,next) + +#define DL_FOREACH_SAFE2(head,el,tmp,next) \ + for ((el) = (head); (el) && ((tmp) = (el)->next, 1); (el) = (tmp)) + +/* these are identical to their singly-linked list counterparts */ +#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR +#define DL_SEARCH LL_SEARCH +#define DL_SEARCH_SCALAR2 LL_SEARCH_SCALAR2 +#define DL_SEARCH2 LL_SEARCH2 + +#define DL_REPLACE_ELEM2(head, el, add, prev, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((head) == (el)) { \ + (head) = (add); \ + (add)->next = (el)->next; \ + if ((el)->next == NULL) { \ + (add)->prev = (add); \ + } else { \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + } \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->prev->next = (add); \ + if ((el)->next == NULL) { \ + (head)->prev = (add); \ + } else { \ + (add)->next->prev = (add); \ + } \ + } \ +} while (0) + +#define DL_REPLACE_ELEM(head, el, add) \ + DL_REPLACE_ELEM2(head, el, add, prev, next) + +#define DL_PREPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } else { \ + (add)->prev->next = (add); \ + } \ + } else { \ + DL_APPEND2(head, add, prev, next); \ + } \ +} while (0) \ + +#define DL_PREPEND_ELEM(head, el, add) \ + DL_PREPEND_ELEM2(head, el, add, prev, next) + +#define DL_APPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } else { \ + DL_PREPEND2(head, add, prev, next); \ + } \ +} while (0) \ + +#define DL_APPEND_ELEM(head, el, add) \ + DL_APPEND_ELEM2(head, el, add, prev, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef DL_INSERT_INORDER2 +#define DL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = NULL; \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((head)->next && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (head)->next = (add); \ + UTLIST_RS(head); \ + if ((add)->next) { \ + (add)->next->prev = (add); \ + } else { \ + (head)->prev = (add); \ + } \ + } \ +} while (0) +#endif /* NO_DECLTYPE */ + +/****************************************************************************** + * circular doubly linked list macros * + *****************************************************************************/ +#define CDL_APPEND(head,add) \ + CDL_APPEND2(head,add,prev,next) + +#define CDL_APPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + (head) = (add); \ + } \ +} while (0) + +#define CDL_PREPEND(head,add) \ + CDL_PREPEND2(head,add,prev,next) + +#define CDL_PREPEND2(head,add,prev,next) \ +do { \ + if (head) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (head)->prev = (add); \ + (add)->prev->next = (add); \ + } else { \ + (add)->prev = (add); \ + (add)->next = (add); \ + } \ + (head) = (add); \ +} while (0) + +#define CDL_INSERT_INORDER(head,add,cmp) \ + CDL_INSERT_INORDER2(head,add,cmp,prev,next) + +#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + LDECLTYPE(head) _tmp; \ + if (head) { \ + CDL_LOWER_BOUND2(head, _tmp, add, cmp, next); \ + CDL_APPEND_ELEM2(head, _tmp, add, prev, next); \ + } else { \ + (head) = (add); \ + (head)->next = (head); \ + (head)->prev = (head); \ + } \ +} while (0) + +#define CDL_LOWER_BOUND(head,elt,like,cmp) \ + CDL_LOWER_BOUND2(head,elt,like,cmp,next) + +#define CDL_LOWER_BOUND2(head,elt,like,cmp,next) \ +do { \ + if ((head) == NULL || (cmp(head, like)) >= 0) { \ + (elt) = NULL; \ + } else { \ + for ((elt) = (head); (elt)->next != (head); (elt) = (elt)->next) { \ + if ((cmp((elt)->next, like)) >= 0) { \ + break; \ + } \ + } \ + } \ +} while (0) + +#define CDL_DELETE(head,del) \ + CDL_DELETE2(head,del,prev,next) + +#define CDL_DELETE2(head,del,prev,next) \ +do { \ + if (((head)==(del)) && ((head)->next == (head))) { \ + (head) = NULL; \ + } else { \ + (del)->next->prev = (del)->prev; \ + (del)->prev->next = (del)->next; \ + if ((del) == (head)) (head)=(del)->next; \ + } \ +} while (0) + +#define CDL_COUNT(head,el,counter) \ + CDL_COUNT2(head,el,counter,next) \ + +#define CDL_COUNT2(head, el, counter,next) \ +do { \ + (counter) = 0; \ + CDL_FOREACH2(head,el,next) { ++(counter); } \ +} while (0) + +#define CDL_FOREACH(head,el) \ + CDL_FOREACH2(head,el,next) + +#define CDL_FOREACH2(head,el,next) \ + for ((el)=(head);el;(el)=(((el)->next==(head)) ? NULL : (el)->next)) + +#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ + CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) + +#define CDL_FOREACH_SAFE2(head,el,tmp1,tmp2,prev,next) \ + for ((el) = (head), (tmp1) = (head) ? (head)->prev : NULL; \ + (el) && ((tmp2) = (el)->next, 1); \ + (el) = ((el) == (tmp1) ? NULL : (tmp2))) + +#define CDL_SEARCH_SCALAR(head,out,field,val) \ + CDL_SEARCH_SCALAR2(head,out,field,val,next) + +#define CDL_SEARCH_SCALAR2(head,out,field,val,next) \ +do { \ + CDL_FOREACH2(head,out,next) { \ + if ((out)->field == (val)) break; \ + } \ +} while (0) + +#define CDL_SEARCH(head,out,elt,cmp) \ + CDL_SEARCH2(head,out,elt,cmp,next) + +#define CDL_SEARCH2(head,out,elt,cmp,next) \ +do { \ + CDL_FOREACH2(head,out,next) { \ + if ((cmp(out,elt))==0) break; \ + } \ +} while (0) + +#define CDL_REPLACE_ELEM2(head, el, add, prev, next) \ +do { \ + assert((head) != NULL); \ + assert((el) != NULL); \ + assert((add) != NULL); \ + if ((el)->next == (el)) { \ + (add)->next = (add); \ + (add)->prev = (add); \ + (head) = (add); \ + } else { \ + (add)->next = (el)->next; \ + (add)->prev = (el)->prev; \ + (add)->next->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } \ +} while (0) + +#define CDL_REPLACE_ELEM(head, el, add) \ + CDL_REPLACE_ELEM2(head, el, add, prev, next) + +#define CDL_PREPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el); \ + (add)->prev = (el)->prev; \ + (el)->prev = (add); \ + (add)->prev->next = (add); \ + if ((head) == (el)) { \ + (head) = (add); \ + } \ + } else { \ + CDL_APPEND2(head, add, prev, next); \ + } \ +} while (0) + +#define CDL_PREPEND_ELEM(head, el, add) \ + CDL_PREPEND_ELEM2(head, el, add, prev, next) + +#define CDL_APPEND_ELEM2(head, el, add, prev, next) \ +do { \ + if (el) { \ + assert((head) != NULL); \ + assert((add) != NULL); \ + (add)->next = (el)->next; \ + (add)->prev = (el); \ + (el)->next = (add); \ + (add)->next->prev = (add); \ + } else { \ + CDL_PREPEND2(head, add, prev, next); \ + } \ +} while (0) + +#define CDL_APPEND_ELEM(head, el, add) \ + CDL_APPEND_ELEM2(head, el, add, prev, next) + +#ifdef NO_DECLTYPE +/* Here are VS2008 / NO_DECLTYPE replacements for a few functions */ + +#undef CDL_INSERT_INORDER2 +#define CDL_INSERT_INORDER2(head,add,cmp,prev,next) \ +do { \ + if ((head) == NULL) { \ + (add)->prev = (add); \ + (add)->next = (add); \ + (head) = (add); \ + } else if ((cmp(head, add)) >= 0) { \ + (add)->prev = (head)->prev; \ + (add)->next = (head); \ + (add)->prev->next = (add); \ + (head)->prev = (add); \ + (head) = (add); \ + } else { \ + char *_tmp = (char*)(head); \ + while ((char*)(head)->next != _tmp && (cmp((head)->next, add)) < 0) { \ + (head) = (head)->next; \ + } \ + (add)->prev = (head); \ + (add)->next = (head)->next; \ + (add)->next->prev = (add); \ + (head)->next = (add); \ + UTLIST_RS(head); \ + } \ +} while (0) +#endif /* NO_DECLTYPE */ + +#endif /* UTLIST_H */ diff --git a/lib/uthash/src/utringbuffer.h b/lib/uthash/src/utringbuffer.h new file mode 100644 index 0000000..6034117 --- /dev/null +++ b/lib/uthash/src/utringbuffer.h @@ -0,0 +1,108 @@ +/* +Copyright (c) 2015-2022, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* a ring-buffer implementation using macros + */ +#ifndef UTRINGBUFFER_H +#define UTRINGBUFFER_H + +#define UTRINGBUFFER_VERSION 2.3.0 + +#include <stdlib.h> +#include <string.h> +#include "utarray.h" // for "UT_icd" + +typedef struct { + unsigned i; /* index of next available slot; wraps at n */ + unsigned n; /* capacity */ + unsigned char f; /* full */ + UT_icd icd; /* initializer, copy and destructor functions */ + char *d; /* n slots of size icd->sz */ +} UT_ringbuffer; + +#define utringbuffer_init(a, _n, _icd) do { \ + memset(a, 0, sizeof(UT_ringbuffer)); \ + (a)->icd = *(_icd); \ + (a)->n = (_n); \ + if ((a)->n) { (a)->d = (char*)malloc((a)->n * (_icd)->sz); } \ +} while(0) + +#define utringbuffer_clear(a) do { \ + if ((a)->icd.dtor) { \ + if ((a)->f) { \ + unsigned _ut_i; \ + for (_ut_i = 0; _ut_i < (a)->n; ++_ut_i) { \ + (a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \ + } \ + } else { \ + unsigned _ut_i; \ + for (_ut_i = 0; _ut_i < (a)->i; ++_ut_i) { \ + (a)->icd.dtor(utringbuffer_eltptr(a, _ut_i)); \ + } \ + } \ + } \ + (a)->i = 0; \ + (a)->f = 0; \ +} while(0) + +#define utringbuffer_done(a) do { \ + utringbuffer_clear(a); \ + free((a)->d); (a)->d = NULL; \ + (a)->n = 0; \ +} while(0) + +#define utringbuffer_new(a,n,_icd) do { \ + a = (UT_ringbuffer*)malloc(sizeof(UT_ringbuffer)); \ + utringbuffer_init(a, n, _icd); \ +} while(0) + +#define utringbuffer_free(a) do { \ + utringbuffer_done(a); \ + free(a); \ +} while(0) + +#define utringbuffer_push_back(a,p) do { \ + if ((a)->icd.dtor && (a)->f) { (a)->icd.dtor(_utringbuffer_internalptr(a,(a)->i)); } \ + if ((a)->icd.copy) { (a)->icd.copy( _utringbuffer_internalptr(a,(a)->i), p); } \ + else { memcpy(_utringbuffer_internalptr(a,(a)->i), p, (a)->icd.sz); }; \ + if (++(a)->i == (a)->n) { (a)->i = 0; (a)->f = 1; } \ +} while(0) + +#define utringbuffer_len(a) ((a)->f ? (a)->n : (a)->i) +#define utringbuffer_empty(a) ((a)->i == 0 && !(a)->f) +#define utringbuffer_full(a) ((a)->f != 0) + +#define _utringbuffer_real_idx(a,j) ((a)->f ? ((j) + (a)->i) % (a)->n : (j)) +#define _utringbuffer_internalptr(a,j) ((void*)((a)->d + ((a)->icd.sz * (j)))) +#define utringbuffer_eltptr(a,j) ((0 <= (j) && (j) < utringbuffer_len(a)) ? _utringbuffer_internalptr(a,_utringbuffer_real_idx(a,j)) : NULL) + +#define _utringbuffer_fake_idx(a,j) ((a)->f ? ((j) + (a)->n - (a)->i) % (a)->n : (j)) +#define _utringbuffer_internalidx(a,e) (((char*)(e) >= (a)->d) ? (((char*)(e) - (a)->d)/(a)->icd.sz) : -1) +#define utringbuffer_eltidx(a,e) _utringbuffer_fake_idx(a, _utringbuffer_internalidx(a,e)) + +#define utringbuffer_front(a) utringbuffer_eltptr(a,0) +#define utringbuffer_next(a,e) ((e)==NULL ? utringbuffer_front(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)+1)) +#define utringbuffer_prev(a,e) ((e)==NULL ? utringbuffer_back(a) : utringbuffer_eltptr(a, utringbuffer_eltidx(a,e)-1)) +#define utringbuffer_back(a) (utringbuffer_empty(a) ? NULL : utringbuffer_eltptr(a, utringbuffer_len(a) - 1)) + +#endif /* UTRINGBUFFER_H */ diff --git a/lib/uthash/src/utstack.h b/lib/uthash/src/utstack.h new file mode 100644 index 0000000..94b8c51 --- /dev/null +++ b/lib/uthash/src/utstack.h @@ -0,0 +1,88 @@ +/* +Copyright (c) 2018-2022, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef UTSTACK_H +#define UTSTACK_H + +#define UTSTACK_VERSION 2.3.0 + +/* + * This file contains macros to manipulate a singly-linked list as a stack. + * + * To use utstack, your structure must have a "next" pointer. + * + * ----------------.EXAMPLE ------------------------- + * struct item { + * int id; + * struct item *next; + * }; + * + * struct item *stack = NULL; + * + * int main() { + * int count; + * struct item *tmp; + * struct item *item = malloc(sizeof *item); + * item->id = 42; + * STACK_COUNT(stack, tmp, count); assert(count == 0); + * STACK_PUSH(stack, item); + * STACK_COUNT(stack, tmp, count); assert(count == 1); + * STACK_POP(stack, item); + * free(item); + * STACK_COUNT(stack, tmp, count); assert(count == 0); + * } + * -------------------------------------------------- + */ + +#define STACK_TOP(head) (head) + +#define STACK_EMPTY(head) (!(head)) + +#define STACK_PUSH(head,add) \ + STACK_PUSH2(head,add,next) + +#define STACK_PUSH2(head,add,next) \ +do { \ + (add)->next = (head); \ + (head) = (add); \ +} while (0) + +#define STACK_POP(head,result) \ + STACK_POP2(head,result,next) + +#define STACK_POP2(head,result,next) \ +do { \ + (result) = (head); \ + (head) = (head)->next; \ +} while (0) + +#define STACK_COUNT(head,el,counter) \ + STACK_COUNT2(head,el,counter,next) \ + +#define STACK_COUNT2(head,el,counter,next) \ +do { \ + (counter) = 0; \ + for ((el) = (head); el; (el) = (el)->next) { ++(counter); } \ +} while (0) + +#endif /* UTSTACK_H */ diff --git a/lib/uthash/src/utstring.h b/lib/uthash/src/utstring.h new file mode 100644 index 0000000..f0270fb --- /dev/null +++ b/lib/uthash/src/utstring.h @@ -0,0 +1,407 @@ +/* +Copyright (c) 2008-2022, Troy D. Hanson https://troydhanson.github.io/uthash/ +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* a dynamic string implementation using macros + */ +#ifndef UTSTRING_H +#define UTSTRING_H + +#define UTSTRING_VERSION 2.3.0 + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> + +#ifdef __GNUC__ +#define UTSTRING_UNUSED __attribute__((__unused__)) +#else +#define UTSTRING_UNUSED +#endif + +#ifdef oom +#error "The name of macro 'oom' has been changed to 'utstring_oom'. Please update your code." +#define utstring_oom() oom() +#endif + +#ifndef utstring_oom +#define utstring_oom() exit(-1) +#endif + +typedef struct { + char *d; /* pointer to allocated buffer */ + size_t n; /* allocated capacity */ + size_t i; /* index of first unused byte */ +} UT_string; + +#define utstring_reserve(s,amt) \ +do { \ + if (((s)->n - (s)->i) < (size_t)(amt)) { \ + char *utstring_tmp = (char*)realloc( \ + (s)->d, (s)->n + (amt)); \ + if (!utstring_tmp) { \ + utstring_oom(); \ + } \ + (s)->d = utstring_tmp; \ + (s)->n += (amt); \ + } \ +} while(0) + +#define utstring_init(s) \ +do { \ + (s)->n = 0; (s)->i = 0; (s)->d = NULL; \ + utstring_reserve(s,100); \ + (s)->d[0] = '\0'; \ +} while(0) + +#define utstring_done(s) \ +do { \ + if ((s)->d != NULL) free((s)->d); \ + (s)->n = 0; \ +} while(0) + +#define utstring_free(s) \ +do { \ + utstring_done(s); \ + free(s); \ +} while(0) + +#define utstring_new(s) \ +do { \ + (s) = (UT_string*)malloc(sizeof(UT_string)); \ + if (!(s)) { \ + utstring_oom(); \ + } \ + utstring_init(s); \ +} while(0) + +#define utstring_renew(s) \ +do { \ + if (s) { \ + utstring_clear(s); \ + } else { \ + utstring_new(s); \ + } \ +} while(0) + +#define utstring_clear(s) \ +do { \ + (s)->i = 0; \ + (s)->d[0] = '\0'; \ +} while(0) + +#define utstring_bincpy(s,b,l) \ +do { \ + utstring_reserve((s),(l)+1); \ + if (l) memcpy(&(s)->d[(s)->i], b, l); \ + (s)->i += (l); \ + (s)->d[(s)->i]='\0'; \ +} while(0) + +#define utstring_concat(dst,src) \ +do { \ + utstring_reserve((dst),((src)->i)+1); \ + if ((src)->i) memcpy(&(dst)->d[(dst)->i], (src)->d, (src)->i); \ + (dst)->i += (src)->i; \ + (dst)->d[(dst)->i]='\0'; \ +} while(0) + +#define utstring_len(s) ((s)->i) + +#define utstring_body(s) ((s)->d) + +UTSTRING_UNUSED static void utstring_printf_va(UT_string *s, const char *fmt, va_list ap) { + int n; + va_list cp; + for (;;) { +#ifdef _WIN32 + cp = ap; +#else + va_copy(cp, ap); +#endif + n = vsnprintf (&s->d[s->i], s->n-s->i, fmt, cp); + va_end(cp); + + if ((n > -1) && ((size_t) n < (s->n-s->i))) { + s->i += n; + return; + } + + /* Else try again with more space. */ + if (n > -1) utstring_reserve(s,n+1); /* exact */ + else utstring_reserve(s,(s->n)*2); /* 2x */ + } +} +#ifdef __GNUC__ +/* support printf format checking (2=the format string, 3=start of varargs) */ +static void utstring_printf(UT_string *s, const char *fmt, ...) + __attribute__ (( format( printf, 2, 3) )); +#endif +UTSTRING_UNUSED static void utstring_printf(UT_string *s, const char *fmt, ...) { + va_list ap; + va_start(ap,fmt); + utstring_printf_va(s,fmt,ap); + va_end(ap); +} + +/******************************************************************************* + * begin substring search functions * + ******************************************************************************/ +/* Build KMP table from left to right. */ +UTSTRING_UNUSED static void _utstring_BuildTable( + const char *P_Needle, + size_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + + i = 0; + j = i - 1; + P_KMP_Table[i] = j; + while (i < (long) P_NeedleLen) + { + while ( (j > -1) && (P_Needle[i] != P_Needle[j]) ) + { + j = P_KMP_Table[j]; + } + i++; + j++; + if (i < (long) P_NeedleLen) + { + if (P_Needle[i] == P_Needle[j]) + { + P_KMP_Table[i] = P_KMP_Table[j]; + } + else + { + P_KMP_Table[i] = j; + } + } + else + { + P_KMP_Table[i] = j; + } + } + + return; +} + + +/* Build KMP table from right to left. */ +UTSTRING_UNUSED static void _utstring_BuildTableR( + const char *P_Needle, + size_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + + i = P_NeedleLen - 1; + j = i + 1; + P_KMP_Table[i + 1] = j; + while (i >= 0) + { + while ( (j < (long) P_NeedleLen) && (P_Needle[i] != P_Needle[j]) ) + { + j = P_KMP_Table[j + 1]; + } + i--; + j--; + if (i >= 0) + { + if (P_Needle[i] == P_Needle[j]) + { + P_KMP_Table[i + 1] = P_KMP_Table[j + 1]; + } + else + { + P_KMP_Table[i + 1] = j; + } + } + else + { + P_KMP_Table[i + 1] = j; + } + } + + return; +} + + +/* Search data from left to right. ( Multiple search mode. ) */ +UTSTRING_UNUSED static long _utstring_find( + const char *P_Haystack, + size_t P_HaystackLen, + const char *P_Needle, + size_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + long V_FindPosition = -1; + + /* Search from left to right. */ + i = j = 0; + while ( (j < (int)P_HaystackLen) && (((P_HaystackLen - j) + i) >= P_NeedleLen) ) + { + while ( (i > -1) && (P_Needle[i] != P_Haystack[j]) ) + { + i = P_KMP_Table[i]; + } + i++; + j++; + if (i >= (int)P_NeedleLen) + { + /* Found. */ + V_FindPosition = j - i; + break; + } + } + + return V_FindPosition; +} + + +/* Search data from right to left. ( Multiple search mode. ) */ +UTSTRING_UNUSED static long _utstring_findR( + const char *P_Haystack, + size_t P_HaystackLen, + const char *P_Needle, + size_t P_NeedleLen, + long *P_KMP_Table) +{ + long i, j; + long V_FindPosition = -1; + + /* Search from right to left. */ + j = (P_HaystackLen - 1); + i = (P_NeedleLen - 1); + while ( (j >= 0) && (j >= i) ) + { + while ( (i < (int)P_NeedleLen) && (P_Needle[i] != P_Haystack[j]) ) + { + i = P_KMP_Table[i + 1]; + } + i--; + j--; + if (i < 0) + { + /* Found. */ + V_FindPosition = j + 1; + break; + } + } + + return V_FindPosition; +} + + +/* Search data from left to right. ( One time search mode. ) */ +UTSTRING_UNUSED static long utstring_find( + UT_string *s, + long P_StartPosition, /* Start from 0. -1 means last position. */ + const char *P_Needle, + size_t P_NeedleLen) +{ + long V_StartPosition; + long V_HaystackLen; + long *V_KMP_Table; + long V_FindPosition = -1; + + if (P_StartPosition < 0) + { + V_StartPosition = s->i + P_StartPosition; + } + else + { + V_StartPosition = P_StartPosition; + } + V_HaystackLen = s->i - V_StartPosition; + if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) ) + { + V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); + if (V_KMP_Table != NULL) + { + _utstring_BuildTable(P_Needle, P_NeedleLen, V_KMP_Table); + + V_FindPosition = _utstring_find(s->d + V_StartPosition, + V_HaystackLen, + P_Needle, + P_NeedleLen, + V_KMP_Table); + if (V_FindPosition >= 0) + { + V_FindPosition += V_StartPosition; + } + + free(V_KMP_Table); + } + } + + return V_FindPosition; +} + + +/* Search data from right to left. ( One time search mode. ) */ +UTSTRING_UNUSED static long utstring_findR( + UT_string *s, + long P_StartPosition, /* Start from 0. -1 means last position. */ + const char *P_Needle, + size_t P_NeedleLen) +{ + long V_StartPosition; + long V_HaystackLen; + long *V_KMP_Table; + long V_FindPosition = -1; + + if (P_StartPosition < 0) + { + V_StartPosition = s->i + P_StartPosition; + } + else + { + V_StartPosition = P_StartPosition; + } + V_HaystackLen = V_StartPosition + 1; + if ( (V_HaystackLen >= (long) P_NeedleLen) && (P_NeedleLen > 0) ) + { + V_KMP_Table = (long *)malloc(sizeof(long) * (P_NeedleLen + 1)); + if (V_KMP_Table != NULL) + { + _utstring_BuildTableR(P_Needle, P_NeedleLen, V_KMP_Table); + + V_FindPosition = _utstring_findR(s->d, + V_HaystackLen, + P_Needle, + P_NeedleLen, + V_KMP_Table); + + free(V_KMP_Table); + } + } + + return V_FindPosition; +} +/******************************************************************************* + * end substring search functions * + ******************************************************************************/ + +#endif /* UTSTRING_H */ diff --git a/linked_list_cycle.c b/linked_list_cycle.c new file mode 100644 index 0000000..de0b0ba --- /dev/null +++ b/linked_list_cycle.c @@ -0,0 +1,39 @@ +// 141. Linked List Cycle +#include "leetcode.h" + +/* + * given the 'head' of a linked list, determine if the linked list has a cycle + * in it. there is a cycle in a linked list if there is some node in the list + * that can be reached again by continuously following the 'next' pointer. + * internally, 'pos' is used to denote the index of the node that tail's 'next' + * pointer is connected to. note that 'pos' is not passed as a parameter. return + * true if there is a cycle in the linked list. otherwise return false. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +struct hash_entry { + int id; + char name[10]; + UT_hash_handle hh; +}; + +bool hasCycle(struct ListNode *head) { + struct ListNode *tmp = head; + struct hash_entry *s, *users = NULL; + while (tmp) { + long user_id = tmp; + HASH_FIND_INT(users, &user_id, s); + if (!s) { + s = malloc(sizeof(*s)); + s->id = tmp; + HASH_ADD_INT(users, id, s); + } else + return true; + tmp = tmp->next; + } + return false; +} diff --git a/linked_list_cycle.py b/linked_list_cycle.py new file mode 100644 index 0000000..bd94c8e --- /dev/null +++ b/linked_list_cycle.py @@ -0,0 +1,35 @@ +# 141. Linked List Cycle + +""" +given the 'head' of a linked list, determine if the linked list has a cycle +in it. there is a cycle in a linked list if there is some node in the list +that can be reached again by continuously following the 'next' pointer. +internally, 'pos' is used to denote the index of the node that tail's 'next' +pointer is connected to. note that 'pos' is not passed as a parameter. return +true if there is a cycle in the linked list. otherwise return false. +""" + + +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, x): + self.val = x + self.next = None + + +class Solution(object): + def hasCycle(self, head): + """ + :type head: ListNode + :rtype: bool + """ + fast = slow = head + while fast and fast.next: + slow, fast = slow.next, fast.next.next + if fast == slow: + return True + return False + + +if __name__ == "__main__": + obj = Solution() diff --git a/linked_list_cycle2.c b/linked_list_cycle2.c new file mode 100644 index 0000000..d6f9cb4 --- /dev/null +++ b/linked_list_cycle2.c @@ -0,0 +1,34 @@ +// 142. Linked List Cycle II +#include <stdio.h> +#include <stdlib.h> + +/* + * given 'head' of linked list, return node where the cycle begins. if there is + * no cycle return null. there is a cycle in linked list of there is some node + * in the list that can be reached again by continuously following the 'next' + * pointer. internally, 'pos' is used to denote the index of the node that + * tail's 'next' pointer is connected to. it is -1 if there is no cycle. note + * 'pos' is not passed as parameter. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +struct ListNode *detectCycle(struct ListNode *head) { + struct ListNode *slow = head, *fast = head; + while (fast && fast->next) { + slow = slow->next; + fast = fast->next->next; + if (slow == fast) + break; + } + if (!(fast && fast->next)) + return NULL; + while (head != slow) { + head = head->next; + slow = slow->next; + } + return head; +} diff --git a/linked_list_cycle2.cpp b/linked_list_cycle2.cpp new file mode 100644 index 0000000..43dccea --- /dev/null +++ b/linked_list_cycle2.cpp @@ -0,0 +1,31 @@ +// 142. Linked List Cycle II +#include "leetcode.h" + +/* + * given 'head' of linked list, return node where the cycle begins. if there is + * no cycle return null. there is a cycle in linked list of there is some node + * in the list that can be reached again by continuously following the 'next' + * pointer. internally, 'pos' is used to denote the index of the node that + * tail's 'next' pointer is connected to. it is -1 if there is no cycle. note + * 'pos' is not passed as parameter. + */ + +class Solution { +public: + ListNode *detectCycle(ListNode *head) { + ListNode *slow = head, *fast = head; + while (fast && fast->next) { + slow = slow->next; + fast = fast->next->next; + if (slow == fast) + break; + } + if (!(fast && fast->next)) + return NULL; + while (head != slow) { + head = head->next; + slow = slow->next; + } + return head; + } +}; diff --git a/linked_list_random.c b/linked_list_random.c new file mode 100644 index 0000000..6215989 --- /dev/null +++ b/linked_list_random.c @@ -0,0 +1,49 @@ +// 382. Linked List Random Node +#include <stddef.h> +#include <stdlib.h> + +/* + * given singly linked list, return a random node's value from the linked list. + * each node must have the same probability of being chosen. implement + * 'Solution' class: f1: initialises object with head of signly linked list + * 'head' f2: chooses node randomly from list and returns its value. all nodes + * should be equally likely to be chosen + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +typedef struct { + struct ListNode *list; + size_t size; +} Solution; + +Solution *solutionCreate(struct ListNode *head) { + Solution *obj = (Solution *)malloc(sizeof(Solution)); + obj->list = head; + while (head->next) + head = head->next; + head->next = obj->list; + return obj; +} + +int solutionGetRandom(Solution *obj) { + struct ListNode *node = obj->list; + int n = rand() % 10; + while (n--) + node = node->next; + return node->val; +} + +void solutionFree(Solution *obj) { + free(obj->list); + free(obj); +} + +int main() { + struct ListNode *head; + Solution *obj = solutionCreate(head); + int param_1 = solutionGetRandom(obj); +} diff --git a/linked_list_random.cpp b/linked_list_random.cpp new file mode 100644 index 0000000..ae147c5 --- /dev/null +++ b/linked_list_random.cpp @@ -0,0 +1,40 @@ +// 382. Linked List Random Node +#include "leetcode.h" + +/* + * given singly linked list, return a random node's value from the linked list. + * each node must have the same probability of being chosen. implement + * 'Solution' class: f1: initialises object with head of signly linked list + * 'head' f2: chooses node randomly from list and returns its value. all nodes + * should be equally likely to be chosen + */ + +class Solution { +public: + Solution(ListNode *head) { + this->head = head; + while (head != NULL) { + this->n++; + head = head->next; + } + } + int getRandom() { + int i = rand() % this->n; + ListNode *p = this->head; + while (i) { + p = p->next; + i -= 1; + } + return p->val; + } + +private: + int n = 0; + ListNode *head = NULL; +}; + +int main() { + ListNode *head; + Solution *obj = new Solution(head); + int param_1 = obj->getRandom(); +} diff --git a/long_nice_subarr.c b/long_nice_subarr.c new file mode 100644 index 0000000..cfa50f3 --- /dev/null +++ b/long_nice_subarr.c @@ -0,0 +1,53 @@ +// 2401. Longest Nice Subarray +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array 'nums' consisting of positive integers. we call a subarray of + * 'nums' nice if the bitwise AND of every pair of elements that are in + * different positions in the subarray is equal to 0. return the length of the + * longest nice subarray. a subarray is contiguous part of an array. note that + * subarrays of length 1 are always considered nice. + */ + +bool check(int *bit, int n) { + for (int i = 0; i < n; i++) + if (bit[i] > 1) + return false; + return true; +} + +int longestNiceSubarray(int *nums, int nums_size) { + int *bit = calloc(32, sizeof(int)); + int left = 0, right = 0; + while (right < nums_size) { + int k = nums[right], pos = 0; + while (k) { + if (k % 2 == 1) + bit[pos]++; + k /= 2; + pos++; + } + right++; + if (!check(bit, 32)) { + k = nums[left]; + pos = 0; + while (k) { + if (k % 2 == 1) + bit[pos]--; + k /= 2; + pos++; + } + left++; + } + } + return right - left; +} + +int main() { + int n1[] = {1, 3, 8, 48, 10}, ns1 = 5; + int n2[] = {3, 1, 5, 11, 13}, ns2 = 5; + printf("%d\n", longestNiceSubarray(n1, ns1)); // expect: 3 + printf("%d\n", longestNiceSubarray(n2, ns2)); // expect: 1 +} diff --git a/longest_arithmetic_subseq.c b/longest_arithmetic_subseq.c new file mode 100644 index 0000000..56dec29 --- /dev/null +++ b/longest_arithmetic_subseq.c @@ -0,0 +1,44 @@ +// 1027. Longest Arithmetic Subsequence +#include <stdio.h> +#include <string.h> + +/* + * given an array 'nums' of integers, return the length of the longest + * arithmetic subsequence in 'nums'. note that + * - a subsequence is an array that can be derived from another array by + * deleting some or no elements without changing the order of the remaining + * elements. + * - a sequence 'seq' is arithmetic if 'seq[i + 1] - seq[i]' are all the same + * value (for '0 <= i < seq.len() - 1') + */ + +int longestArithSeqLength(int *nums, int nums_size) { + if (!nums) + return 0; + int min = nums[0], max = min; + for (int i = 0; i < nums_size; i++) { + if (nums[i] < min) + min = nums[i]; + if (nums[i] > max) + max = nums[i]; + } + int tmp = max - min, map[nums_size][2 * tmp + 1], ans = 0; + memset(map, 0, sizeof(map[0][0]) * nums_size * (2 * tmp + 1)); + for (int i = 0; i < nums_size; i++) + for (int j = 0; j < i; j++) { + int diff = nums[i] - nums[j] + tmp; + map[i][diff] = map[j][diff] + 1; + if (map[i][diff] > ans) + ans = map[i][diff]; + } + return ans + 1; +} + +int main() { + int n1[] = {3, 6, 9, 12}, ns1 = 4; + int n2[] = {9, 4, 7, 2, 10}, ns2 = 5; + int n3[] = {20, 1, 15, 3, 10, 5, 8}, ns3 = 7; + printf("%d\n", longestArithSeqLength(n1, ns1)); // expect: 4 + printf("%d\n", longestArithSeqLength(n2, ns2)); // expect: 3 + printf("%d\n", longestArithSeqLength(n3, ns3)); // expect: 4 +} diff --git a/longest_arithmetic_subseq.cpp b/longest_arithmetic_subseq.cpp new file mode 100644 index 0000000..5b661db --- /dev/null +++ b/longest_arithmetic_subseq.cpp @@ -0,0 +1,37 @@ +// 1027. Longest Arithmetic Subsequence +#include "leetcode.h" + +/* + * given an array 'nums' of integers, return the length of the longest + * arithmetic subsequence in 'nums'. note that + * - a subsequence is an array that can be derived from another array by + * deleting some or no elements without changing the order of the remaining + * elements. + * - a sequence 'seq' is arithmetic if 'seq[i + 1] - seq[i]' are all the same + * value (for '0 <= i < seq.len() - 1') + */ + +class Solution { +public: + int longestArithmeticSeqLength(vector<int> &nums) { + int n = nums.size(), ans = 0; + vvd(int) dp(n, vector<int>(n, 1)); + for (int i = 1; i < n - 1; ++i) + for (int j = i + 1; j < n; ++j) { + for (int k = i - 1; k >= 0; k--) + if (nums[i] - nums[k] == nums[j] - nums[i]) + dp[i][j] = max(dp[i][j], dp[k][i] + 1); + ans = max(ans, dp[i][j]); + } + return ans + 1; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {3, 6, 9, 12}, n2 = {9, 4, 7, 2, 10}, + n3 = {20, 1, 15, 3, 10, 5, 8}; + printf("%d\n", obj.longestArithmeticSeqLength(n1)); // expect: 4 + printf("%d\n", obj.longestArithmeticSeqLength(n2)); // expect: 3 + printf("%d\n", obj.longestArithmeticSeqLength(n3)); // expect: 4 +} diff --git a/longest_arithmetic_subseq_diff.c b/longest_arithmetic_subseq_diff.c new file mode 100644 index 0000000..015afde --- /dev/null +++ b/longest_arithmetic_subseq_diff.c @@ -0,0 +1,32 @@ +// 1218. Longest Arithmetic Subsequence of Given Difference +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array 'arr' and an integer 'difference', return the length + * of the longest subsequence in 'arr' which is an arithmetic sequence such that + * the difference between adjacent elements in the subsequence equals + * 'difference'. a subsequence is a sequence that can be derived from 'arr' by + * deleting some or no elements without changing the order of the remaining + * elements. + */ + +int longestSubsequence(int *arr, int arr_size, int difference) { + int idx, max = 0, cnt[20001] = {0}; + for (int i = 0; i < arr_size; i++) { + idx = 10000 + arr[i]; + if (max < cnt[idx]) + max = cnt[idx]; + if (idx + difference >= 0 && idx + difference <= 2000) + cnt[idx + difference] = cnt[idx] + 1; + } + return max + 1; +} + +int main() { + int a1[] = {1, 2, 3, 4}, a2[] = {1, 3, 5, 7}, + a3[] = {1, 5, 7, 8, 5, 3, 4, 2, 1}; + printf("%d\n", longestSubsequence(a1, 4, 1)); // expect: 4 + printf("%d\n", longestSubsequence(a2, 4, 1)); // expect: 1 + printf("%d\n", longestSubsequence(a3, 9, -2)); // expect: 4 +} diff --git a/longest_arithmetic_subseq_diff.cpp b/longest_arithmetic_subseq_diff.cpp new file mode 100644 index 0000000..dc6e9ff --- /dev/null +++ b/longest_arithmetic_subseq_diff.cpp @@ -0,0 +1,33 @@ +// 1218. Longest Arithmetic Subsequence of Given Difference +#include "leetcode.h" + +/* + * given an integer array 'arr' and an integer 'difference', return the length + * of the longest subsequence in 'arr' which is an arithmetic sequence such that + * the difference between adjacent elements in the subsequence equals + * 'difference'. a subsequence is a sequence that can be derived from 'arr' by + * deleting some or no elements without changing the order of the remaining + * elements. + */ + +class Solution { +public: + int longestSubsequence(vector<int> &arr, int difference) { + int ans = 1; + unordered_map<int, int> max; + for (int i = 0; i < arr.size(); i++) + max[arr[i]] = max[arr[i] - difference] + 1; + for (auto i : max) + ans = std::max(ans, i.second); + return ans; + } +}; + +int main() { + Solution obj; + vector<int> a1 = {1, 2, 3, 4}, a2 = {1, 3, 5, 7}, + a3 = {1, 5, 7, 8, 5, 3, 4, 2, 1}; + printf("%d\n", obj.longestSubsequence(a1, 1)); // expect: 4 + printf("%d\n", obj.longestSubsequence(a2, 1)); // expect: 1 + printf("%d\n", obj.longestSubsequence(a3, -2)); // expect: 4 +} diff --git a/longest_common_subseq.c b/longest_common_subseq.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/longest_common_subseq.c diff --git a/longest_common_subseq.cpp b/longest_common_subseq.cpp new file mode 100644 index 0000000..56cbaf9 --- /dev/null +++ b/longest_common_subseq.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + int longestCommonSubsequence(string text1, string text2) { + short ans[2][1000] = {}; + for (int i = 0; i < text1.size(); ++i) + for (int j = 0; j < text2.size(); ++j) + ans[!(i % 2)][j + 1] = text1[i] == text2[j] + ? ans[i % 2][j] + 1 + : max(ans[i % 2][j + 1], ans[!(i % 2)][j]); + return ans[text1.size() % 2][text2.size()]; + } +}; + +int main() { + Solution obj; + cout << obj.longestCommonSubsequcne("abcde", "ace"); // 3 + cout << endl << obj.longestCommonSubsequcne("abc", "abc"); // 3 +} diff --git a/longest_common_subseq.py b/longest_common_subseq.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/longest_common_subseq.py diff --git a/longest_common_subseq.rs b/longest_common_subseq.rs new file mode 100644 index 0000000..212070a --- /dev/null +++ b/longest_common_subseq.rs @@ -0,0 +1,23 @@ +struct Solution; + +impl Solution { + pub fn longest_common_subsequence(text1: String, text2: String) -> i32 { + let mut dp: Vec<Vec<usize>> = vec![vec![0; text2.len() + 1]; text1.len() + 1]; + for (i, c1) in text1.chars().enumerate() { + for (j, c2) in text2.chars().enumerate() { + dp[i + 1][j + 1] = if c1 == c2 { + dp[i][j] + 1 + } else { + std::cmp::max(dp[i][j + 1], dp[i + 1][j]) + } + } + } + dp[text1.len()][text2.len()] as i32 + } +} + +fn main() { + let text1 = String::from("abcde"); + let text2 = String::from("ace"); + print!("{}", Solution::longest_common_subsequence(text1, text2)); //3 +} diff --git a/longest_common_subseq2.c b/longest_common_subseq2.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/longest_common_subseq2.c diff --git a/longest_common_subseq2.py b/longest_common_subseq2.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/longest_common_subseq2.py diff --git a/longest_consecutive_sequence.cpp b/longest_consecutive_sequence.cpp new file mode 100644 index 0000000..2fda5e6 --- /dev/null +++ b/longest_consecutive_sequence.cpp @@ -0,0 +1,36 @@ +#include "leetcode.h" + +class Solution { +public: + int longestConsecutive(vector<int> &nums) { + unordered_set<int> us; + int ans = 0; + for (int i = 0; i < nums.size(); i++) + us.insert(nums[i]); + while (us.size() > 0) { + int num = *us.begin(); + int count = 1; + us.erase(num); + int smaller = num - 1; + int bigger = num + 1; + while (us.count(smaller) > 0) { + us.erase(smaller); + smaller--; + count++; + } + while (us.count(bigger) > 0) { + us.erase(bigger); + bigger++; + count++; + } + ans = max(ans, count); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums = {100, 4, 200, 1, 3, 2}; + cout << obj.longestConsecutive(nums); +} diff --git a/longest_cycle_graph.c b/longest_cycle_graph.c new file mode 100644 index 0000000..9203678 --- /dev/null +++ b/longest_cycle_graph.c @@ -0,0 +1,57 @@ +// 2360. Longest Cycle in a Graph +#include <math.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given a directed graph of 'n' nodes numbered from 0 to n - 1, where each node + * has at most one outgoing edge. the graph is represented with a given + * 0-indexed array 'edges' of size n, indicating that there is a directed edge + * from node i to node edges[i]. if there is no outgoing edge from node i, then + * edges[i] == -1. return length of longest cycle in the graph. if no cycle + * exists, return -1. a cycle path starts at same node. + */ + +typedef struct set { + int cycle; + int seq; +} set_t; + +int longestCycle(int *edges, int edges_size) { + int n = edges_size, ans = -1, run = 1; + bool *visited = calloc(n, sizeof(bool)); + set_t **hash = calloc(n, sizeof(set_t *)); + for (int i = 0; i < n; i++) { + if (edges[i] == -1 || visited[i]) + continue; + int idx = -1, p = i; + while (p != -1) { + idx++; + if (visited[p] == false) { + hash[p] = malloc(sizeof(set_t)); + hash[p]->cycle = run; + hash[p]->seq = idx; + visited[p] = true; + } else { + if (hash[p]->cycle == run) + ans = fmax(ans, idx - hash[p]->seq); + break; + } + p = edges[p]; + } + run++; + } + for (int i = 0; i < n; i++) + if (hash[i] != NULL) + free(hash[i]); + free(hash); + free(visited); + return ans; +} + +int main() { + int e1[] = {3, 3, 4, 2, 3}, e2[] = {2, -1, 3, 1}; + printf("%d\n", longestCycle(e1, 5)); // expect: 3 + printf("%d\n", longestCycle(e2, 4)); // expect: -1 +} diff --git a/longest_cycle_graph.cpp b/longest_cycle_graph.cpp new file mode 100644 index 0000000..b0cdf49 --- /dev/null +++ b/longest_cycle_graph.cpp @@ -0,0 +1,58 @@ +// 2360. Longest Cycle in a Graph +#include "leetcode.h" + +/* + * given a directed graph of 'n' nodes numbered from 0 to n - 1, where each node + * has at most one outgoing edge. the graph is represented with a given + * 0-indexed array 'edges' of size n, indicating that there is a directed edge + * from node i to node edges[i]. if there is no outgoing edge from node i, then + * edges[i] == -1. return length of longest cycle in the graph. if no cycle + * exists, return -1. a cycle path starts at same node. + */ + +class Solution { +public: + int longestCycle(vector<int> &edges) { + vector<bool> vis(edges.size(), 0); + for (int i = 0; i < edges.size(); i++) { + if (vis[i]) + continue; + vector<int> store; + dfs(edges, i, vis, store); + } + return max_len; + } + +private: + int max_len = -1; + void dfs(vector<int> &edges, int si, vector<bool> &vis, vector<int> &store) { + if (si == -1) + return; + if (vis[si]) { + int cnt = -1; + for (int i = 0; i < store.size(); i++) { + if (store[i] == si) { + cnt = i; + break; + } + } + if (cnt == -1) + return; + int size = store.size() - cnt; + max_len = max(max_len, size); + return; + } + vis[si] = true; + store.push_back(si); + dfs(edges, edges[si], vis, store); + return; + } +}; + +int main() { + Solution obj; + vector<int> e1 = {3, 3, 4, 2, 3}; + vector<int> e2 = {2, -1, 3, 1}; + printf("%d\n", obj.longestCycle(e1)); + printf("%d\n", obj.longestCycle(e2)); +} diff --git a/longest_ideal_subseq.c b/longest_ideal_subseq.c new file mode 100644 index 0000000..2971cd3 --- /dev/null +++ b/longest_ideal_subseq.c @@ -0,0 +1,38 @@ +// 2370. Longest Ideal Subsequence +#include "leetcode.h" + +/* + * given a string 's' consisting of lowercase letters and an integer 'k', we + * call a string 't' ideal if the following conditions are satisfied. 't' is a + * subsequence of the string 's'. the absolute difference in the alphabet order + * of every two adjacent letters in 't' is less than or equal to 'k'. return the + * length of the longest ideal sting. a subsequence is a string that can be + * derived from another string by deleting some or no characters without + * changing the order of the remaining characters. note that the alphabet order + * is not cyclic. for example, the absolute difference in the alphabet order of + * 'a' and 'z' is 25, not 1. + */ + +int longestIdealString(char *s, int k) { + int n = strlen(s), ans = 0; + int *dp = (int *)malloc(n * sizeof(int)); + int *prev = (int *)malloc(26 * sizeof(int)); + for (int i = 0; i < n; i++) + dp[i] = 1; + for (int i = 0; i < 26; i++) + prev[i] = -1; + for (int i = 0; i < n; i++) { + for (int j = fmax(0, s[i] - 'a' - k); j <= fmin(25, s[i] - 'a' + k); j++) + if (prev[j] != -1) + dp[i] = fmax(dp[i], 1 + dp[prev[j]]); + prev[s[i] - 'a'] = i; + ans = fmax(ans, dp[i]); + } + return ans; +} + +int main() { + char *s1 = "acfgbd", *s2 = "abcd"; + printf("%d\n", longestIdealString(s1, 2)); // expect: 4 + printf("%d\n", longestIdealString(s2, 4)); // expect: 4 +} diff --git a/longest_ideal_subseq.py b/longest_ideal_subseq.py new file mode 100644 index 0000000..b5e05d8 --- /dev/null +++ b/longest_ideal_subseq.py @@ -0,0 +1,33 @@ +# 2370. Longest Ideal Subsequence + +""" +given a string 's' consisting of lowercase letters and an integer 'k', we +call a string 't' ideal if the following conditions are satisfied. 't' is a +subsequence of the string 's'. the absolute difference in the alphabet order +of every two adjacent letters in 't' is less than or equal to 'k'. return the +length of the longest ideal sting. a subsequence is a string that can be +derived from another string by deleting some or no characters without +changing the order of the remaining characters. note that the alphabet order +is not cyclic. for example, the absolute difference in the alphabet order of +'a' and 'z' is 25, not 1. +""" + + +class Solution(object): + def longestIdealString(self, s, k): + """ + :type s: str + :type k: int + :rtype: int + """ + dp = [0] * 128 + for c in s: + i = ord(c) + dp[i] = max(dp[i - k : i + k + 1]) + 1 + return max(dp) + + +if __name__ == "__main__": + obj = Solution() + print(obj.longestIdealString("acfbd", 2)) # expect: 4 + print(obj.longestIdealString("abcd", 3)) # expect: 4 diff --git a/longest_increasing_matrix_path.cpp b/longest_increasing_matrix_path.cpp new file mode 100644 index 0000000..1ee5b99 --- /dev/null +++ b/longest_increasing_matrix_path.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class Solution { +public: + int longestIncreasingPath(vector<vector<int>> &matrix) { + int rows = matrix.size(), cols = matrix[0].size(); + if (!rows) + return 0; + vector<vector<int>> dp(rows, vector<int>(cols, 0)); + function<int(int, int)> dfs = [&](int x, int y) { + if (dp[x][y]) + return dp[x][y]; + vector<vector<int>> dirs = {{-1, 0}, {1, 0}, {0, 1}, {0, -1}}; + for (auto &dir : dirs) { + int x2 = x + dir[0], y2 = y + dir[1]; + if (x2 < 0 || x2 >= rows || y2 < 0 || y2 >= cols) + continue; + if (matrix[x2][y2] <= matrix[x][y]) + continue; + dp[x][y] = max(dp[x][y], dfs(x2, y2)); + } + return ++dp[x][y]; + }; + int ans = 0; + for (int i = 0; i < rows; ++i) + for (int j = 0; i < cols; ++j) + ans = max(ans, dfs(i, j)); + return ans; + } +}; + +int main() {} diff --git a/longest_increasing_subseq.c b/longest_increasing_subseq.c new file mode 100644 index 0000000..afe7fde --- /dev/null +++ b/longest_increasing_subseq.c @@ -0,0 +1,28 @@ +// 300. Longest Increasing Subsequence +#include "leetcode.h" + +/* + * given an integer array 'nums', return the length of the longest strictly + * increasing subsequence. + */ + +int lengthOfLIS(int *nums, int nums_size) { + int dp[nums_size], max_len = 0; + for (int i = 0; i < nums_size; ++i) + dp[i] = 1; + for (int i = 0; i < nums_size; ++i) + for (int j = 0; j < i; ++j) + if (nums[i] > nums[j]) + dp[i] = fmax(dp[i], dp[j] + 1); + for (int i = 0; i < nums_size; ++i) + max_len = fmax(max_len, dp[i]); + return max_len; +} + +int main() { + int n1[] = {10, 9, 2, 5, 3, 7, 101, 18}, n2[] = {0, 1, 0, 3, 2, 3}, + n3[] = {7, 7, 7, 7, 7, 7, 7}; + printf("%d\n", lengthOfLIS(n1, ARRAY_SIZE(n1))); // expect: 4 + printf("%d\n", lengthOfLIS(n2, ARRAY_SIZE(n2))); // expect: 4 + printf("%d\n", lengthOfLIS(n3, ARRAY_SIZE(n3))); // expect: 1 +} diff --git a/longest_increasing_subseq.cpp b/longest_increasing_subseq.cpp new file mode 100644 index 0000000..127a984 --- /dev/null +++ b/longest_increasing_subseq.cpp @@ -0,0 +1,48 @@ +#include "leetcode.h" + +class maxBit { +public: + vector<int> bit; + maxBit(int size) { bit.resize(size + 1); } + int get(int idx) { + int ans = 0; + for (; idx > 0; idx -= idx & -idx) + ans = max(ans, bit[idx]); + return ans; + } + void update(int idx, int val) { + for (; idx < bit.size(); idx += idx & -idx) + bit[idx] = max(bit[idx], val); + } +}; + +class Solution { +public: + int lengthOisLIS(vector<int> &nums) { + int uniqueNum = compress(nums); + maxBit bit(uniqueNum); + for (int x : nums) { + int subLongest = bit.get(x - 1); + bit.update(x, subLongest + 1); + } + return bit.get(uniqueNum); + } + +private: + int compress(vector<int> &arr) { + vector<int> uniqueSorted(arr); + sort(uniqueSorted.begin(), uniqueSorted.end()); + uniqueSorted.erase(unique(uniqueSorted.begin(), uniqueSorted.end()), + uniqueSorted.end()); + for (int &x : arr) + x = lower_bound(uniqueSorted.begin(), uniqueSorted.end(), x) - + uniqueSorted.begin() + 1; + return uniqueSorted.size(); + } +}; + +int main() { + Solution obj; + vector<int> nums = {10, 9, 2, 5, 3, 7, 101, 18}; + cout << obj.lengthOisLIS(nums); +} diff --git a/longest_increasing_subseq.py b/longest_increasing_subseq.py new file mode 100644 index 0000000..0547dbf --- /dev/null +++ b/longest_increasing_subseq.py @@ -0,0 +1,28 @@ +# 300. Longest Increasing Subsequence + +""" +given an integer array 'nums', return the length of the longest strictly +increasing subsequence. +""" + + +class Solution(object): + def lengthOfLIS(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + n = len(nums) + dp = [1] * n + for i in range(1, n): + for j in range(i): + if nums[i] > nums[j]: + dp[i] = max(dp[i], dp[j] + 1) + return max(dp) + + +if __name__ == "__main__": + obj = Solution() + print(obj.lengthOfLIS(nums=[10, 9, 2, 5, 3, 7, 101, 18])) # expect: 4 + print(obj.lengthOfLIS(nums=[0, 1, 0, 3, 2, 3])) # expect: 4 + print(obj.lengthOfLIS(nums=[7, 7, 7, 7, 7, 7, 7])) # expect: 1 diff --git a/longest_increasing_subseq2.c b/longest_increasing_subseq2.c new file mode 100644 index 0000000..3b92a1d --- /dev/null +++ b/longest_increasing_subseq2.c @@ -0,0 +1,42 @@ +// 1143. Longest Common Subsequence +#include "leetcode.h" + +/* + * given two strings 'text1' and 'text2', return the length of their longest + * common subsequence. if there is no common subsequence, return 0. a + * subsequence of a string is a new string generated from the original string + * with some characers (can be none) deleted without changing the relative order + * of the remaining characters. a common subsequence of two strings is a + * subsequence that is common to both strings. + */ + +int longestCommonSubsequence(char *text1, char *text2) { + int x = strlen(text1) + 1; + int y = strlen(text2) + 1; + int **matrix = malloc(y * sizeof(int *)); + for (int i = 0; i < y; i++) { + matrix[i] = malloc(x * sizeof(int)); + matrix[i][0] = 0; + } + for (int i = 0; i < x; i++) + matrix[0][i] = 0; + for (int i = 1; i < y; i++) + for (int j = 1; j < x; j++) { + if (text1[j - 1] == text2[i - 1]) + matrix[i][j] = matrix[i - 1][j - 1] + 1; + else if (matrix[i - 1][j] >= matrix[i][j - 1]) + matrix[i][j] = matrix[i - 1][j]; + else + matrix[i][j] = matrix[i][j - 1]; + } + return matrix[y - 1][x - 1]; +} + +int main() { + char *t11 = "abcde", *t21 = "ace"; + char *t12 = "abc", *t22 = "abc"; + char *t13 = "abc", *t23 = "def"; + printf("%d\n", longestCommonSubsequence(t11, t21)); // expect: 3 + printf("%d\n", longestCommonSubsequence(t12, t22)); // expect: 3 + printf("%d\n", longestCommonSubsequence(t13, t23)); // expect: 0 +} diff --git a/longest_increasing_subseq2.py b/longest_increasing_subseq2.py new file mode 100644 index 0000000..6bd7f0f --- /dev/null +++ b/longest_increasing_subseq2.py @@ -0,0 +1,33 @@ +# 1143. Longest Common Subsequence + +""" +given two strings 'text1' and 'text2', return the length of their longest +common subsequence. if there is no common subsequence, return 0. a +subsequence of a string is a new string generated from the original string +with some characers (can be none) deleted without changing the relative order +of the remaining characters. a common subsequence of two strings is a +subsequence that is common to both strings. +""" + + +class Solution(object): + def longestCommonSubsequence(self, text1, text2): + """ + :type text1: str + :type text2: str + :rtype: int + """ + dp = [[0] * (len(text2) + 1) for _ in range(len(text1) + 1)] + for i, c in enumerate(text1): + for j, d in enumerate(text2): + dp[i + 1][j + 1] = ( + 1 + dp[i][j] if c == d else max(dp[i][j + 1], dp[i + 1][j]) + ) + return dp[-1][-1] + + +if __name__ == "__main__": + obj = Solution() + print(obj.longestCommonSubsequence("abcde", "ace")) # expect: 3 + print(obj.longestCommonSubsequence("abc", "abc")) # expect: 3 + print(obj.longestCommonSubsequence("abc", "def")) # expect: 0 diff --git a/longest_palindrome.c b/longest_palindrome.c new file mode 100644 index 0000000..d64c06d --- /dev/null +++ b/longest_palindrome.c @@ -0,0 +1,27 @@ +// 409. Longest Palindrome +#include "leetcode.h" + +/* + * given a sting 's' which consists of lowercase or uppercase letters, return + * the length of the longest palindrome that can be built with those letters. + * letters are case sensitive for example "Aa" is not considered a palindrome + */ + +int longestPalindrome(char *s) { + static int freq[128]; + int mirror = 0, centre = 0; + memset(freq, 0, sizeof(freq)); + while (*s != '\0') + ++freq[*s++]; + for (int i = 0; i < 128; ++i) { + mirror += freq[i] / 2; + centre |= freq[i] & 1; + } + return mirror * 2 + centre; +} + +int main() { + char *s1 = "abccccdd", *s2 = "a"; + printf("%d\n", longestPalindrome(s1)); // expect: 7 + printf("%d\n", longestPalindrome(s2)); // expect: 1 +} diff --git a/longest_palindrome.py b/longest_palindrome.py new file mode 100644 index 0000000..58cd217 --- /dev/null +++ b/longest_palindrome.py @@ -0,0 +1,34 @@ +# 409. Longest Palindrome + +""" +given a sting 's' which consists of lowercase or uppercase letters, return +the length of the longest palindrome that can be built with those letters. +letters are case sensitive for example "Aa" is not considered a palindrome +""" + + +class Solution(object): + def longestPalindrome(self, s): + """ + :type s: str + :rtype: int + """ + odd_cnt, d = 0, {} + for c in s: + if c in d: + d[c] += 1 + else: + d[c] = 1 + if d[c] % 2 == 1: + odd_cnt += 1 + else: + odd_cnt -= 1 + if odd_cnt > 1: + return len(s) - odd_cnt + 1 + return len(s) + + +if __name__ == "__main__": + obj = Solution() + print(obj.longestPalindrome("abccccdd")) + print(obj.longestPalindrome("a")) diff --git a/longest_palindrome_concat.cpp b/longest_palindrome_concat.cpp new file mode 100644 index 0000000..3a42e0a --- /dev/null +++ b/longest_palindrome_concat.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +class Solution { +public: + int longestPalindrome(vector<string> &words) { + unordered_map<string, int> um; + for (auto w : words) + ++um[w]; + int ans = 0, center = 0, sz = 2; + for (auto [w, cnt] : um) { + auto reversed = string(rbegin(w), rend(w)); + if (w == reversed) { + ans += 2 * (cnt / 2); + center |= cnt % 2; + } else { + auto it = um.find(reversed); + if (it != end(um)) + ans += min(cnt, it->second); + } + } + return sz * ans + (center ? sz : 0); + } +}; + +int main() { + Solution obj; + vector<string> words = {"lc", "cl", "gg"}; + cout << obj.longestPalindrome(words); +} diff --git a/longest_palindrome_concat.rs b/longest_palindrome_concat.rs new file mode 100644 index 0000000..2a97ed4 --- /dev/null +++ b/longest_palindrome_concat.rs @@ -0,0 +1,39 @@ +struct Solution; + +impl Solution { + pub fn longest_palindrome(words: Vec<String>) -> i32 { + let (mut hist, mut ans, a_code) = (vec![vec![0; 26];26], 0, 'a' as usize); + for w in words.iter() { + if let Some(i) = w.chars().nth(0) { + if let Some(j) = w.chars().nth(1) { + let i = i as usize - a_code; + let j = j as usize - a_code; + match hist[j][i] { + cnt if cnt > 0 => { + ans += 4; + hist[j][i] -= 1; + }, + _ => { + hist[i][j] += 1; + } + } + } + } + } + for i in 0..26 { + match hist[i][i] { + cnt if cnt > 0 => { + ans += 2; + break; + }, + _ => (), + } + } + ans + } +} + +fn main() { + let words = vec!["lc".to_string(), "cl".to_string(), "gg".to_string()]; + print!("{}", Solution::longest_palindrome(words)); +} diff --git a/longest_palindromic_subseq.c b/longest_palindromic_subseq.c new file mode 100644 index 0000000..d70f778 --- /dev/null +++ b/longest_palindromic_subseq.c @@ -0,0 +1,40 @@ +// 516. Longest Palindromic Subsequence +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given string 's', find the longest palindromic susbsequences + * of ngth in 's'. a subsequcnes is a sequence that can be derived + * from another sequence by deleting some or no elements without + * changing the order of the remaining elements + */ + +#define MAX(a, b) (a > b ? a : b) + +int longestPalindromeSubseq(char *s) { + int i, j, n = strlen(s); + if (n <= 1) + return n; + int **dp = (int **)malloc(sizeof(int *) * n); + for (i = 0; i < n; i++) { + dp[i] = (int *)calloc(sizeof(int), n); + for (j = 0; j < n; j++) + dp[i][i] = 1; + } + for (i = n - 1; i >= 0; i--) { + for (j = i + 1; j < n; j++) { + if (s[i] == s[j]) + dp[i][j] = dp[i + 1][j - 1] + 2; + else + dp[i][j] = MAX(dp[i + 1][j], dp[i][j - 1]); + } + } + return dp[0][n - 1]; +} + +int main() { + char s1[] = {"bbbab"}, s2[] = {"cbbd"}; + printf("%d\n", longestPalindromeSubseq(s1)); // expect: 4 + printf("%d\n", longestPalindromeSubseq(s2)); // expect: 2 +} diff --git a/longest_palindromic_subseq.cpp b/longest_palindromic_subseq.cpp new file mode 100644 index 0000000..f2a074f --- /dev/null +++ b/longest_palindromic_subseq.cpp @@ -0,0 +1,35 @@ +// 516. Longest Palindromic Subsequence +#include "leetcode.h" + +/* + * given string 's', find the longest palindromic susbsequences + * of length in 's'. a subsequcnes is a sequence that can be derived + * from another sequence by deleting some or no elements without + * changing the order of the remaining elements + */ + +class Solution { +public: + int longestPalindromeSubseq(string s) { + int n = s.size(); + vector<int> dp(n, 0); + for (int i = n - 1; i >= 0; i--) { + vector<int> new_dp(n, 0); + new_dp[i] = 1; + for (int j = i + 1; j < n; j++) { + if (s[i] == s[j]) + new_dp[j] = 2 + dp[j - 1]; + else + new_dp[j] = max(dp[j], new_dp[j - 1]); + } + dp = new_dp; + } + return dp[n - 1]; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.longestPalindromeSubseq("bbbab")); // expect: 4 + printf("%d\n", obj.longestPalindromeSubseq("cbbd")); // expect: 2 +} diff --git a/longest_palindromic_substr.c b/longest_palindromic_substr.c new file mode 100644 index 0000000..5ce7741 --- /dev/null +++ b/longest_palindromic_substr.c @@ -0,0 +1,35 @@ +// 5. Longest Palindromic Substring +#include "leetcode.h" + +/* + * given a string 's', return the longest palindromic substring in 's' + */ + +char *longestPalindrome(char *s) { + char *start, *end, *p = s, *sub_start = s; + int max_len = 1; + while (*p) { + start = p; + end = p; + while (*(end + 1) && *(end + 1) == *end) + end++; + p = end + 1; + while (*(end + 1) && (start > s) && *(end + 1) == *(start - 1)) { + start--; + end++; + } + if (end - start + 1 > max_len) { + max_len = end - start + 1; + sub_start = start; + } + } + char *ans = (char *)calloc(max_len + 1, sizeof(char)); + strncpy(ans, sub_start, max_len); + return ans; +} + +int main() { + char s1[] = {"babad"}, s2[] = {"cbbd"}; + printf("%s\n", longestPalindrome(s1)); // expect: bab + printf("%s\n", longestPalindrome(s2)); // expect: bb +} diff --git a/longest_palindromic_substr.cpp b/longest_palindromic_substr.cpp new file mode 100644 index 0000000..4ecba25 --- /dev/null +++ b/longest_palindromic_substr.cpp @@ -0,0 +1,35 @@ +#include "leetcode.h" + +class Solution { +public: + string longestPalindrome(string s) { + if (s.size() == 0) + return ""; + int i = 0, j = 0, n = s.size(); + bool p[n][n] = {false}; + for (int x = 0; x < n; x++) { + p[x][x] = true; + if (x == n - 1) + break; + p[x][x + 1] = (s[x] == s[x + 1]); + } + for (int i = n - 3; i >= 0; --i) + for (int j = i + 2; j < n; ++j) + p[i][j] = (p[i + 1][j - 1] && s[i] == s[j]); + int max = 0; + string ans = ""; + for (int i = 0; i < n; i++) + for (int j = i; j < n; j++) + if (p[i][j] == true && j - i + 1 > max) { + max = j - i + 1; + ans = s.substr(i, j - i + 1); + } + return ans; + } +}; + +int main() { + Solution obj; + string s = "babad"; + cout << obj.longestPalindrome(s); +} diff --git a/longest_palindromic_substr.py b/longest_palindromic_substr.py new file mode 100644 index 0000000..5372629 --- /dev/null +++ b/longest_palindromic_substr.py @@ -0,0 +1,30 @@ +# 5. Longest Palindromic Substring + +""" +given a string 's', return the longest palindromic substring in 's' +""" + + +class Solution(object): + def helper(self, s, l, r): + while l >= 0 and r < len(s) and s[l] == s[r]: + l -= 1 + r += 1 + return s[l + 1 : r] + + def longestPalindrome(self, s): + ans = "" + for i in range(len(s)): + tmp = self.helper(s, i, i) + if len(tmp) > len(ans): + ans = tmp + tmp = self.helper(s, i, i + 1) + if len(tmp) > len(ans): + ans = tmp + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.longestPalindrome("babad")) # expect: bab + print(obj.longestPalindrome("cbbd")) # expect: bb diff --git a/longest_path_diff_char.cpp b/longest_path_diff_char.cpp new file mode 100644 index 0000000..8eb9878 --- /dev/null +++ b/longest_path_diff_char.cpp @@ -0,0 +1,36 @@ +#include "leetcode.h" + +class Solution { +public: + int longestPath(vector<int> &parent, string s) { + int n = parent.size(), ans = 1; + queue<int> q; + vector<int> cnt(n), top1(n, 1), top2(n, 1); + for (int i = 1; i < n; ++i) + ++cnt[parent[i]]; + for (int i = 1; i < n; ++i) + if (cnt[i] == 0) + q.push(i); + while (!q.empty() && q.front() != 0) { + int i = q.front(), p = parent[i]; + q.pop(); + if (int len = 1 + (s[i] != s[p] ? top1[i] : 0); top1[p] <= len) { + top2[p] = top1[p]; + top1[p] = len; + } else + top2[p] = max(top2[p], len); + if (--cnt[p] == 0) { + q.push(p); + ans = max(ans, top1[p] + top2[p] - 1); + } + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> parent1 = {-1, 0, 0, 1, 1, 2}, parent2 = {-1, 0, 0, 0}; + cout << obj.longestPath(parent1, "abacbe") << endl; // expect: 3 + cout << obj.longestPath(parent2, "aabc") << endl; // expect: 3 +} diff --git a/longest_path_diff_char.rs b/longest_path_diff_char.rs new file mode 100644 index 0000000..4539ad3 --- /dev/null +++ b/longest_path_diff_char.rs @@ -0,0 +1,63 @@ +use std::collections::HashMap; +use std::cmp::max; +struct Solution; + +static mut res: i32 = 0; +impl Solution { + pub fn longest_path(parent: Vec<i32>, s: String) -> i32 { + unsafe { + res = 0 + } + let mut graph = HashMap::new(); + for (i, &u) in parent.iter().enumerate() { + if u == -1 { + continue; + } + let u = u as usize; + if !graph.contains_key(&u) { + graph.insert(u, vec![]); + } + graph.entry(u).or_insert(vec![]).push(i); + } + let sa: Vec<char> = s.chars().collect(); + Self::dfs(0, &graph, &sa); + let mut ans: i32 = 0; + unsafe { + ans = res; + } + ans + } + fn dfs(root: usize, graph: &HashMap<usize, Vec<usize>>, s: &Vec<char>) -> i32 { + if !graph.contains_key(&root) { + unsafe { + res = max(res, 1); + } + return 1; + } + let (mut a1, mut a2) = (0, 0); + for &v in graph[&root].iter() { + if s[root] == s[v] { + Self::dfs(v, graph, s); + continue; + } + let curr = Self::dfs(v, graph, s); + if curr >= a1 { + a2 = a1; + a1 = curr; + } else if curr > a2 { + a2 = curr + } + } + unsafe { + res = max(res, a1 + a2 + 1); + } + a1 + 1 + } +} + +fn main() { + let parent1 = vec![-1,0,0,1,1,2]; + let parent2 = vec![-1,0,0,0]; + println!("{}", Solution::longest_path(parent1, String::from("abacbe"))); //expect: 3 + println!("{}", Solution::longest_path(parent2, String::from("aabc"))); //expect: 3 +} diff --git a/longest_repeat_char.c b/longest_repeat_char.c new file mode 100644 index 0000000..fe1ad65 --- /dev/null +++ b/longest_repeat_char.c @@ -0,0 +1,32 @@ +// 424. Longest Repeating Character Replacement +#include "leetcode.h" + +/* + * given a string 's' and an integer 'k'. you can choose any character of the + * string and change it to any other uppercase english character. you can + * perform this operation at most 'k' times. return the length of the longest + * substring containing the same letter you can get after performing the above + * operations. + */ + +int characterReplacement(char *s, int k) { + int n = strlen(s), left = 0, right = 0, max_cnt = 0; + int *freq = calloc(26, sizeof(int)); + while (right < n) { + freq[s[right] - 'A']++; + max_cnt = fmax(max_cnt, freq[s[right] - 'A']); + right++; + if (right - left > max_cnt + k) { + freq[s[left] - 'A']--; + left++; + } + } + free(freq); + return right - left; +} + +int main() { + char s1[] = {"ABAB"}, s2[] = {"AABABBA"}; + printf("%d\n", characterReplacement(s1, 2)); // expect: 4 + printf("%d\n", characterReplacement(s2, 1)); // expect: 4 +} diff --git a/longest_repeat_char.py b/longest_repeat_char.py new file mode 100644 index 0000000..169fd33 --- /dev/null +++ b/longest_repeat_char.py @@ -0,0 +1,29 @@ +# 424. Longest Repeating Character Replacement + +""" +given a string 's' and an integer 'k'. you can choose any character of the +string and change it to any other uppercase english character. you can +perform this operation at most 'k' times. return the length of the longest +substring containing the same letter you can get after performing the above +operations. +""" + + +class Solution(object): + def characterReplacement(self, s, k): + max_cnt = ans = 0 + cnt = collections.Counter() + for i in range(len(s)): + cnt[s[i]] += 1 + max_cnt = max(max_cnt, count[s[i]]) + if ans - max_cnt < k: + ans += 1 + else: + cnt[s[i - ans]] -= 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.characterReplacement("ABAB", 2)) # expect: 4 + print(obj.characterReplacement("AABABBA", 1)) # expect: 4 diff --git a/longest_string_chain.c b/longest_string_chain.c new file mode 100644 index 0000000..3053fc6 --- /dev/null +++ b/longest_string_chain.c @@ -0,0 +1,75 @@ +// 1048. Longest String Chain +#include <math.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * you are given an array of 'words' where each word consists of lowercase + * english letters. 'word[a]' is a predecessor of 'word[b]' if and only if we + * can insert exactly one letter anywhere in 'word[a]' without changing the + * order of the other characters to make it equal to 'word[b]'. return the + * length of the longest possible word chain with words chosen from the given + * list of words. + */ + +int cmp(const void *a, const void *b) { + char *s1 = *(char **)a; + char *s2 = *(char **)b; + return strlen(s1) - strlen(s2); +} + +bool strcmp_ex(char *s1, char *s2) { + int len1 = strlen(s1), len2 = strlen(s2); + int idx1 = 0, idx2 = 0; + while (idx1 < len1 && idx2 < len2) { + if (s1[idx1] == s2[idx2]) { + idx1++; + idx2++; + } else { + idx2++; + } + } + if (idx1 != len1) + return false; + else + return true; +} + +// int longestStrChain(char **words, int words_size) { +int longestStrChain(int c, char words[][c], int words_size) { + qsort(words, words_size, sizeof(char *), cmp); + int *dp = malloc(words_size * sizeof(int)); + int i, j, m, n, lsc = 1; + dp[0] = 1; + for (i = 1; i < words_size; i++) { + if (strlen(words[i]) == 1) + dp[i] = 1; + else + break; + } + for (j = i; j < words_size; j++) { + dp[j] = 1; + for (m = j - 1; m >= 0; m--) { + if (strlen(words[m]) == strlen(words[j])) + continue; + if (strlen(words[m]) < strlen(words[j]) - 1) + break; + if (strcmp_ex(words[m], words[j])) + dp[j] = fmax(dp[m] + 1, dp[j]); + } + lsc = fmax(lsc, dp[j]); + } + free(dp); + return lsc; +} + +int main() { + char w1[][4] = {"a", "b", "ba", "bca", "bda", "bdca"}; + char w2[][6] = {"xbc", "pcxbcf", "xb", "cxbc", "pcxbc"}; + char w3[][5] = {"abcd", "dbqca"}; + printf("%d\n", longestStrChain(4, w1, 6)); // expect: 4 + printf("%d\n", longestStrChain(6, w2, 6)); // expect: 4 + printf("%d\n", longestStrChain(5, w3, 6)); // expect: 4 +} diff --git a/longest_string_chain.cpp b/longest_string_chain.cpp new file mode 100644 index 0000000..afa805c --- /dev/null +++ b/longest_string_chain.cpp @@ -0,0 +1,34 @@ +#include "leetcode.h" + +class Solution { +public: + int longestStrChain(vector<string> &words) { + vector<unordered_set<string>> vus(17); + for (auto i : words) + vus[i.size()].insert(i); + unordered_map<string, int> um; + int ans = 1; + for (int i = 16; i; i--) { + if (vus[i - 1].empty()) + continue; + for (auto j : vus[i]) { + int wVal = um[j] ? um[j] : 1; + for (int k = 0; k < j.size(); k++) { + string prev = j.substr(0, k) + j.substr(k + 1); + int pVal = um[prev] ? um[prev] : 1; + if (vus[i - 1].find(prev) != vus[i - 1].end() && wVal >= pVal) { + um[prev] = wVal + 1; + ans = max(ans, wVal + 1); + } + } + } + } + return ans; + } +}; + +int main() { + Solution obj; + vector<string> words = {"a", "b", "ba", "bca", "bda", "bdca"}; + cout << obj.longestStrChain(words); +} diff --git a/longest_string_chain.py b/longest_string_chain.py new file mode 100644 index 0000000..954fe23 --- /dev/null +++ b/longest_string_chain.py @@ -0,0 +1,25 @@ +# 1048. Longest String Chain + +""" +you are given an array of 'words' where each word consists of lowercase +english letters. 'word[a]' is a predecessor of 'word[b]' if and only if we +can insert exactly one letter anywhere in 'word[a]' without changing the +order of the other characters to make it equal to 'word[b]'. return the +length of the longest possible word chain with words chosen from the given +list of words. +""" + + +class Solution(object): + def longestStrChain(self, words): + dp = {} + for w in sorted(words, key=len): + dp[w] = max(dp.get(w[:i] + w[i + 1 :], 0) + 1 for i in xrange(len(w))) + return max(dp.values()) + + +if __name__ == "__main__": + obj = Solution() + print(obj.longestStrChain(["a", "b", "ba", "bca", "bda", "bdca"])) # expect: 4 + print(obj.longestStrChain(["xbc", "pcxbcf", "xb", "cxbc", "pcxbc"])) # expect: 5 + print(obj.longestStrChain(["abcd", "dbqca"])) # expect: 1 diff --git a/longest_subarr_ones.c b/longest_subarr_ones.c new file mode 100644 index 0000000..049ce33 --- /dev/null +++ b/longest_subarr_ones.c @@ -0,0 +1,31 @@ +// 1493. Longest Subarray of 1's After Deleting One Element +#include <math.h> +#include <stdio.h> + +/* + * given a binary array 'nums', you should delete one element from it. return + * the size of the longest non-empty subarray containing only 1's in the + * resulting array. return 0 if there is no such subarray. + */ + +int longestSubarray(int *nums, int nums_size) { + int n = nums_size, zero_cnt = 0, ans = 0, left = 0; + for (int right = 0; right < n; right++) { + if (!nums[right]) + zero_cnt++; + while (zero_cnt > 1) { + if (!nums[left]) + zero_cnt--; + left++; + } + ans = fmax(ans, right - left); + } + return ans; +} + +int main() { + int n1[] = {1, 1, 0, 1}, n2[] = {0, 1, 1, 1, 0, 1, 1, 0, 1}, n3[] = {1, 1, 1}; + printf("%d\n", longestSubarray(n1, 4)); // expect: 3 + printf("%d\n", longestSubarray(n2, 9)); // expect: 5 + printf("%d\n", longestSubarray(n3, 3)); // expect: 2 +} diff --git a/longest_subarr_ones.cpp b/longest_subarr_ones.cpp new file mode 100644 index 0000000..35f2353 --- /dev/null +++ b/longest_subarr_ones.cpp @@ -0,0 +1,31 @@ +// 1493. Longest Subarray of 1's After Deleting One Element +#include "leetcode.h" + +/* + * given a binary array 'nums', you should delete one element from it. return + * the size of the longest non-empty subarray containing only 1's in the + * resulting array. return 0 if there is no such subarray. + */ + +class Solution { +public: + int longestSubarray(vector<int> &nums) { + int ans = 0; + for (int i = 0, j = 0, skip = 0; i < nums.size(); ++i) { + skip += !nums[i]; + if (skip > 1) + skip -= !nums[j++]; + ans = max(ans, i - j); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 1, 0, 1}, n2 = {0, 1, 1, 1, 0, 1, 1, 0, 1}, + n3 = {1, 1, 1}; + printf("%d\n", obj.longestSubarray(n1)); // expect: 3 + printf("%d\n", obj.longestSubarray(n2)); // expect: 5 + printf("%d\n", obj.longestSubarray(n3)); // expect: 2 +} diff --git a/longest_subseq_lim_sum.cpp b/longest_subseq_lim_sum.cpp new file mode 100644 index 0000000..9613667 --- /dev/null +++ b/longest_subseq_lim_sum.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> answerQueries(vector<int> &nums, vector<int> &queries) { + int n = nums.size(), m = queries.size(); + sort(nums.begin(), nums.end()); + vector<int> ans, pre(n + 1, 0); + for (int i = 1; i < n; i++) + pre[i] = pre[i - 1] + nums[i - 1]; + for (int i = 0; i < m; i++) { + int sum = queries[i]; + auto z = lower_bound(pre.begin(), pre.end(), sum) - pre.begin(); + if (z < n + 1) { + if (pre[z] == sum) + ans.push_back(z); + else + ans.push_back(z - 1); + } else if (z == n + 1) + ans.push_back(n); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums = {4, 5, 2, 1}, queries = {3, 10, 21}; + for (auto i : obj.answerQueries(nums, queries)) + cout << i << ' '; +} diff --git a/longest_subseq_lim_sum.rs b/longest_subseq_lim_sum.rs new file mode 100644 index 0000000..037b606 --- /dev/null +++ b/longest_subseq_lim_sum.rs @@ -0,0 +1,17 @@ +struct Solution; + +impl Solution { + pub fn answer_queries(mut nums: Vec<i32>, queries: Vec<i32>) -> Vec<i32> { + nums.sort_unstable(); + nums.iter_mut().fold(0, |acc, x| { *x += acc; *x}); + queries.iter().map(|x| + nums.binary_search(x).unwrap_or_else(|i| i - 1) as i32 + 1 + ).collect() + } +} + +fn main() { + let nums = vec![4,5,2,1]; + let queries = vec![3,10,21]; + print!("{:?}", Solution::answer_queries(nums, queries)); +} diff --git a/longest_substring_no_repeat.c b/longest_substring_no_repeat.c new file mode 100644 index 0000000..bf353be --- /dev/null +++ b/longest_substring_no_repeat.c @@ -0,0 +1,39 @@ +// 3. Longest Substring Without Repeating Characters +#include <assert.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a string 's', find the length of the longest substring without + * repeating characters. + */ + +int lengthOfLongestSubstring(char *s) { + int cnt[512], n = strlen(s), win_start = 0, best = 0, i; + memset(cnt, 0, sizeof(int) * 512); + for (i = 0; i < n; i++) { + int c = s[i]; + if (cnt[c] >= 1) { + assert(cnt[c] >= 1); + while (win_start < i) { + int to_delete = s[win_start]; + cnt[to_delete]--; + win_start++; + if (!cnt[c]) + break; + } + } + cnt[c]++; + best = fmax(best, i - win_start + 1); + } + return best; +} + +int main() { + char s1[] = {"abcabcbb"}, s2[] = {"bbbbb"}, s3[] = {"pwwkew"}; + printf("%d\n", lengthOfLongestSubstring(s1)); // expect: 3 + printf("%d\n", lengthOfLongestSubstring(s2)); // expect: 1 + printf("%d\n", lengthOfLongestSubstring(s3)); // expect: 3 +} diff --git a/longest_substring_no_repeat.cpp b/longest_substring_no_repeat.cpp new file mode 100644 index 0000000..0735fc7 --- /dev/null +++ b/longest_substring_no_repeat.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +class Solution { +public: + int lengthOfLongestSubstring(string s) { + if (s.size() == 0) + return 0; + map<char, int> charsInSub; + int ans = 0, j = 0; + for (int i = 0; i < s.size(); ++i) { + if (charsInSub.find(s[i]) != charsInSub.end()) + charsInSub.find(s[i])->second++; + else + charsInSub.insert(pair<char, int>(s[i], 1)); + while (charsInSub.find(s[i])->second > 1) { + charsInSub.find(s[j])->second--; + ++j; + } + ans = ans >= i - j + 1 ? ans : i - j + 1; + } + return ans; + } +}; + +int main() { + Solution obj; + string s = "abcabcbb"; + cout << obj.lengthOfLongestSubstring(s); +} diff --git a/longest_uploaded_prefix.c b/longest_uploaded_prefix.c new file mode 100644 index 0000000..25a2b4d --- /dev/null +++ b/longest_uploaded_prefix.c @@ -0,0 +1,64 @@ +// 2424. Longest Uploaded Prefix +#include "leetcode.h" + +/* + * given a string of 'n' videos, each represented by a distinct number from 1 to + * n that you need to upload to a server. you need to implement a data structure + * that calculates the length of the longest uploaded prefix at various points + * in the upload process. we consider i to be uploaded prefix if all videos in + * the range 1 to i inclusive have been uploaded to the server. the longest + * uploaded prefix is the maximum value of 'i' that satisfies this definition. + */ + +typedef struct { + bool *data; + int size; + int longest; +} LUPrefix; + +LUPrefix *lUPrefixCreate(int n) { + LUPrefix *res = malloc(sizeof(LUPrefix)); + res->data = calloc(n + 1, sizeof(bool)); + res->size = n; + res->longest = 0; + return res; +} + +void lUPrefixUpload(LUPrefix *obj, int video) { + obj->data[video] = 1; + if (obj->data[1]) { + int i = obj->longest + 1; + for (i = obj->longest + 1; i <= obj->size; i++) + if (!obj->data[i]) + break; + obj->longest = i - 1; + } +} + +int lUPrefixLongest(LUPrefix *obj) { return obj->longest; } + +void lUPrefixFree(LUPrefix *obj) { + free(obj->data); + free(obj); +} + +/** + * Your LUPrefix struct will be instantiated and called as such: + * LUPrefix* obj = lUPrefixCreate(n); + * lUPrefixUpload(obj, video); + + * int param_2 = lUPrefixLongest(obj); + + * lUPrefixFree(obj); +*/ + +int main() { + LUPrefix *obj = lUPrefixCreate(4); + lUPrefixUpload(obj, 3); + printf("%d\n", lUPrefixLongest(obj)); // expect: 0 + lUPrefixUpload(obj, 1); + printf("%d\n", lUPrefixLongest(obj)); // expect: 1 + lUPrefixUpload(obj, 2); + printf("%d\n", lUPrefixLongest(obj)); // expect: 3 + lUPrefixFree(obj); +} diff --git a/longest_uploaded_prefix.py b/longest_uploaded_prefix.py new file mode 100644 index 0000000..9224b4e --- /dev/null +++ b/longest_uploaded_prefix.py @@ -0,0 +1,49 @@ +# 2424. Longest Uploaded Prefix + +""" +given a string of 'n' videos, each represented by a distinct number from 1 to +n that you need to upload to a server. you need to implement a data structure +that calculates the length of the longest uploaded prefix at various points +in the upload process. we consider i to be uploaded prefix if all videos in +the range 1 to i inclusive have been uploaded to the server. the longest +uploaded prefix is the maximum value of 'i' that satisfies this definition. +""" + + +class LUPrefix(object): + + def __init__(self, n): + """ + :type n: int + """ + self._longest = 0 + self._nums = set() + + def upload(self, video): + """ + :type video: int + :rtype: None + """ + self._nums.add(video) + while self._longest + 1 in self._nums: + self._longest += 1 + + def longest(self): + """ + :rtype: int + """ + return self._longest + + +# Your LUPrefix object will be instantiated and called as such: +# obj = LUPrefix(n) +# obj.upload(video) +# param_2 = obj.longest() +if __name__ == "__main__": + obj = LUPrefix(4) + obj.upload(3) + print(obj.longest()) # expect: 0 + obj.upload(1) + print(obj.longest()) # expect: 1 + obj.upload(2) + print(obj.longest()) # expect: 3 diff --git a/longest_valid_course.cpp b/longest_valid_course.cpp new file mode 100644 index 0000000..87f07a6 --- /dev/null +++ b/longest_valid_course.cpp @@ -0,0 +1,49 @@ +// 1964. Find the Longest Valid Obstacle Course at Each Position +#include "leetcode.h" + +/* + * you want to build obstacle courses. you are given a 0-indexed integer array + * 'obstacles' of length 'n' where 'obstacles[i]' describes the height of the + * i'th obstacle. for every index 'i' between 0 and 'n - 1' (inclusive), find + * the length of the longest obstacle course in 'obstacles' such that: + * - you choose any number of obstacles between 0 and 'i' inclusive + * - you must include the i'th obstacle in the course + * - you must put the chosen obstacles in the same order as they appear in + * 'obstacles' + * - every obstacle (except the first) is taller than or the same height as the + * obstacle immediately before it return an array 'ans' of length 'n', where + * 'ans[i]' is the length of the longest obstacle course for index 'i' as + * described aboveeeeeeeee + */ + +class Solution { +public: + vector<int> longestObstacleCourseAtEachEachPosition(vector<int> &obstacles) { + vector<int> n; + for (int i = 0; i < obstacles.size(); ++i) { + auto it = upper_bound(n.begin(), n.end(), obstacles[i]); + if (it == n.end()) { + n.push_back(obstacles[i]); + it = prev(n.end()); + } else { + *it = obstacles[i]; + } + obstacles[i] = it - n.begin() + 1; + } + return obstacles; + } +}; + +int main() { + Solution obj; + vector<int> o1 = {1, 2, 3, 2}, o2 = {2, 2, 1}, o3 = {3, 1, 5, 6, 4, 2}; + for (auto i : obj.longestObstacleCourseAtEachEachPosition(o1)) + printf("%d ", i); // expect: 1 2 3 3 + printf("\n"); + for (auto i : obj.longestObstacleCourseAtEachEachPosition(o2)) + printf("%d ", i); // expect: 1 2 1 + printf("\n"); + for (auto i : obj.longestObstacleCourseAtEachEachPosition(o3)) + printf("%d ", i); // expect: 1 1 2 3 2 2 + printf("\n"); +} diff --git a/longest_valid_parentheses.cpp b/longest_valid_parentheses.cpp new file mode 100644 index 0000000..953e8be --- /dev/null +++ b/longest_valid_parentheses.cpp @@ -0,0 +1,41 @@ +#include "leetcode.h" + +class Solution { +public: + int longestValidParentheses(string s) { + int n = s.size(), ans = 0; + stack<int> stk; + for (int i = 0; i < n; i++) { + if (s[i] == '(') + stk.push(i); + else { + if (!stk.empty()) { + if (s[stk.top()] == '(') + stk.pop(); + else + stk.push(i); + } else + stk.push(i); + } + } + if (stk.empty()) + ans = n; + else { + int a = n, b = 0; + while (!stk.empty()) { + b = stk.top(); + stk.pop(); + ans = max(ans, a - b - 1); + a = b; + } + ans = max(ans, a); + } + return ans; + } +}; + +int main() { + Solution obj; + string s = ")()())"; + cout << obj.longestValidParentheses(s); +} diff --git a/longest_well_perform_int.c b/longest_well_perform_int.c new file mode 100644 index 0000000..b73aa4d --- /dev/null +++ b/longest_well_perform_int.c @@ -0,0 +1,32 @@ +// 1124. Longest Well-Performing Interval +#include "leetcode.h" + +/* + * given 'hours', a list of number of hours worked per day for a given employee. + * a day is considered to be a tiring day if and only if the number of hours + * worked is strictly greater than 8. a well performing interval is an interval + * of days for which the number of tiring days is strictly larger than the + * number of non tiring days. return the length of the longest well performing + * interval + */ + +int longestWPI(int *hours, int hours_size) { + int cnt[10001] = {0}, t = 0, max = 0; + for (int i = 0; i <= hours_size; i++) + cnt[i] -= 1; + for (int i = 0; i < hours_size; i++) { + if (hours[i] > 8) + t++; + else + t--; + if (t < 0 && cnt[abs(t - 1)] >= 0 && i - cnt[abs(t - 1)] > max) + max = i - cnt[abs(t - 1)]; + } + return max; +} + +int main() { + int h1[] = {9, 9, 6, 0, 6, 6, 9}, h2[] = {6, 6, 6}; + printf("%d\n", longestWPI(h1, ARRAY_SIZE(h1))); // expect: 3 + printf("%d\n", longestWPI(h2, ARRAY_SIZE(h2))); // expect: 0 +} diff --git a/longest_well_perform_int.py b/longest_well_perform_int.py new file mode 100644 index 0000000..a4a1025 --- /dev/null +++ b/longest_well_perform_int.py @@ -0,0 +1,30 @@ +# 1124. Longest Well-Performing Interval + +""" +given 'hours', a list of number of hours worked per day for a given employee. +a day is considered to be a tiring day if and only if the number of hours +worked is strictly greater than 8. a well performing interval is an interval +of days for which the number of tiring days is strictly larger than the +number of non tiring days. return the length of the longest well performing +interval +""" + + +class Solution(object): + def longestWPI(self, hours): + ans = score = 0 + seen = {} + for i, h in enumerate(hours): + score = score + 1 if h > 8 else score - 1 + if score > 0: + ans = i + 1 + seen.setdefault(score, i) + if score - 1 in seen: + ans = max(ans, i - seen[score - 1]) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.longestWPI([9, 9, 6, 0, 6, 6, 9])) # expect: 3 + print(obj.longestWPI([6, 6, 6])) # expect: 0 diff --git a/longest_word_dict.cpp b/longest_word_dict.cpp new file mode 100644 index 0000000..3be4538 --- /dev/null +++ b/longest_word_dict.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + string findLongestWord(string s, vector<string> &dictionary) { + string ans; + for (auto d : dictionary) + if (canForm(d, s)) + if (d.size() > ans.size() || (d.size() == ans.size() && d < ans)) + ans = d; + return ans; + } + +private: + bool canForm(string w, string s) { + int w1 = 0, s1 = 0; + while (w1 < w.size() && s1 < s.size()) { + if (w[w1] == s[s1]) + w1++; + s1++; + } + return w1 == w.size(); + } +}; + +int main() { + Solution obj; + string s = "abpcplea"; + vector<string> dictionary = {"ale", "apple", "monkey", "plea"}; + cout << obj.findLongestWord(s, dictionary); +} diff --git a/longest_zigzag_bt.c b/longest_zigzag_bt.c new file mode 100644 index 0000000..e5f1e9d --- /dev/null +++ b/longest_zigzag_bt.c @@ -0,0 +1,47 @@ +// 1372. Longest ZigZag Path in a Binary Tree +#include <math.h> +#include <stdlib.h> + +/* + * given the 'root' of a binary tree. a zigzag path for a binary tree is defined + * as follows + * - choose any node in the binary tree and a direction (left or right) + * - if the current direction is right, move to the right child of the current + * node + * - change the direction from right to left or from left to right + * - repeat the second nd third steps until you cannot move in the tree + * zigzag length is defined as the number of nodes visited - 1. return longest + * zigzag + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +typedef struct { + int left; + int right; +} data; + +data process(struct TreeNode *root, int *max) { + data res; + if (!root) { + res.left = -1; + res.right = -1; + return res; + } + data l_tree = process(root->left, max); + data r_tree = process(root->right, max); + res.left = 1 + r_tree.right; + res.right = 1 + l_tree.left; + *max = fmax(fmax(res.left, *max), res.right); + return res; +} + +int longestZigZag(struct TreeNode *root) { + int max = 0; + process(root, &max); + return max; +} diff --git a/longest_zigzag_bt.cpp b/longest_zigzag_bt.cpp new file mode 100644 index 0000000..b0ebe7f --- /dev/null +++ b/longest_zigzag_bt.cpp @@ -0,0 +1,46 @@ +// 1372. Longest ZigZag Path in a Binary Tree +#include "leetcode.h" + +/* + * given the 'root' of a binary tree. a zigzag path for a binary tree is defined + * as follows + * - choose any node in the binary tree and a direction (left or right) + * - if the current direction is right, move to the right child of the current + * node + * - change the direction from right to left or from left to right + * - repeat the second nd third steps until you cannot move in the tree + * zigzag length is defined as the number of nodes visited - 1. return longest + * zigzag + */ + +class Solution { + int ans = 0; + map<pair<TreeNode *, bool>, int> mp; + int find(TreeNode *root, bool check) { + if (mp.find({root, check}) != mp.end()) + return mp[{root, check}]; + if (check) { + if (root->right) + return mp[{root, check}] = 1 + find(root->right, !check); + else if (root->left) + return mp[{root, check}] = 1 + find(root->left, !check); + } + return mp[{root, check}] = 1; + } + void preorder(TreeNode *root) { + if (root) { + if (root->left) + ans = max(ans, find(root->left, true)); + if (root->right) + ans = max(ans, find(root->right, false)); + preorder(root->left); + preorder(root->right); + } + } + +public: + int longestZigZag(TreeNode *root) { + preorder(root); + return ans; + } +}; diff --git a/lowest_common_ancestor.cpp b/lowest_common_ancestor.cpp new file mode 100644 index 0000000..ec99f32 --- /dev/null +++ b/lowest_common_ancestor.cpp @@ -0,0 +1,33 @@ +#include "leetcode.h" + +class Solution { +public: + TreeNode *lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q) { + frame ans; + stack<frame> st; + st.push({root, &ans}); + while (st.size()) { + frame *top = &st.top(), *parent = top->parent; + TreeNode *node = top->node; + if (!node || node == p || node == q) { + parent->subs.push_back(node); + st.pop(); + } else if (top->subs.empty()) { + st.push({node->right, top}); + st.push({node->left, top}); + } else { + TreeNode *left = top->subs[0], *right = top->subs[1]; + parent->subs.push_back(!left ? right : !right ? left : node); + st.pop(); + } + } + return ans.subs[0]; + } + +private: + struct frame { + TreeNode *node; + frame *parent; + vector<TreeNode *> subs; + }; +}; diff --git a/lowest_common_ancestor_bst.cpp b/lowest_common_ancestor_bst.cpp new file mode 100644 index 0000000..d496c2c --- /dev/null +++ b/lowest_common_ancestor_bst.cpp @@ -0,0 +1,17 @@ +#include "leetcode.h" + +class Solution { +public: + TreeNode *lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q) { + int small = min(p->val, q->val), large = max(p->val, q->val); + while (root != nullptr) { + if (root->val > large) + root = root->left; + else if (root->val < small) + root = root->right; + else + return root; + } + return nullptr; + } +}; diff --git a/lru_cache.c b/lru_cache.c new file mode 100644 index 0000000..f0c43a0 --- /dev/null +++ b/lru_cache.c @@ -0,0 +1,404 @@ +// 146. LRU Cache +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#define DEBUG_MODE 0 +#define REALLY_DEBUG 0 + +/* + * design a data structure that follows the constraints of a least recently used + * cache (LRU). implete the 'LRUCache' class. the functions 'get' and 'put' must + * each run in O(1) average time complexity + */ + +typedef struct QNode { + struct QNode *prev, *next; + unsigned bucket; + int key; + int data; +} QNode; + +typedef struct Queue { + unsigned count; + unsigned capacity; + QNode *front, *rear; +} Queue; + +typedef struct Hash { + int capacity; + QNode **array; // array of pointers, or pointer to a range of pointers. +} Hash; + +typedef struct LRUCache { + unsigned int capacity; + Queue *queue; + Hash *hash; + +} LRUCache; + +struct QNode *newQNode(unsigned bucket) { + struct QNode *temp = malloc(sizeof(struct QNode)); + temp->bucket = bucket; + temp->prev = temp->next = NULL; + return temp; +} + +struct Queue *createQueue(int capacity) { + struct Queue *queue = malloc(sizeof(struct Queue)); + queue->count = 0; + queue->capacity = capacity; + queue->front = queue->rear = NULL; + return queue; +} + +struct Hash *createHash(int capacity) { + struct Hash *hash = malloc(sizeof(struct Hash)); + hash->capacity = capacity; + hash->array = malloc(sizeof(struct QNode) * hash->capacity); + for (int i = 0; i < hash->capacity; i++) { + hash->array[i] = NULL; + } + return hash; +} + +unsigned int hashfunc(unsigned capacity, int key); +void Enqueue(struct LRUCache *cache, struct Queue *queue, struct Hash *hash, + int value, int key); +int searchCache(struct LRUCache *cache, int key); + +void deQueue(Queue *queue) { // we could have return QNode but how would affect + // memory mgmt? + + if (DEBUG_MODE) { + QNode *n = queue->front; + int c = 0; + QNode *p = n->prev; + while (n != NULL) { + if (REALLY_DEBUG) + printf("QueueNode %d data = %d n->prev:%d, n->next:%d\n", c, n->data, + n->prev != NULL, n->next != NULL); + c++; + n = n->next; + } + if (REALLY_DEBUG) + printf("next queue node is NULL\n"); + if (p == NULL) + if (REALLY_DEBUG) + printf("Front's prev points to null\n"); + } + if (queue->rear == NULL) + return; + if (queue->front == queue->rear) { + queue->front = NULL; + queue->rear = NULL; + queue->count--; + return; + } + // QNode* temp = queue->rear; + // LL two or more + + queue->rear = queue->rear->prev; // could be front if size = 2. That's fine + if (queue->rear) + queue->rear->next = + NULL; // orphan the remaining, no need for memory freeing until it runs + + queue->count--; + return; + // free(temp); // This creates an AddressSanitizer error heap-use-after-free. +} + +void dehash(Queue *queue, Hash *hash, unsigned bucket, + int key) { // sets hash to null. Doesn't free + unsigned test_bucket = hashfunc( + hash->capacity, key); // should be same as passed in. for checking + if (test_bucket != bucket) { + if (REALLY_DEBUG) + printf( + "Warning, hash values coming out differently in dehash function\n"); + } + if (hash->array[bucket]) { // we have to be certain this is right bucket + // adjusted for collision + if (hash->array[bucket]->key == key) { // double check for debug + // QNode* tmp = hash->array[bucket]; + if (REALLY_DEBUG) + printf("Goodbye to hash[%d] with data %d\n", bucket, + hash->array[bucket]->data); + hash->array[bucket] = NULL; + // free(tmp); + } else if (REALLY_DEBUG) + printf("entry found in hash but keys don't match. No action taken.\n"); + return; + } +} + +unsigned getGoodBucket(Hash *hash, int key) { + unsigned try_bucket = hashfunc(hash->capacity, key); + int hc = hash->capacity; + if (REALLY_DEBUG) + printf("try bucket and key %d , %d\n", try_bucket, key); + if (hash->array[try_bucket] == NULL) + return try_bucket; + unsigned original_try = try_bucket; + int c = 0; + while (hash->array[try_bucket] != NULL) { // spot is taken + // try_bucket = ((try_bucket + 1)) % hash->capacity; //THIS IS NOT WORKING + // FOR SOME REASON, STAYING AT 1 1 1 1 1 1 1 1 1 1 if (try_bucket == + // original_try) + if (REALLY_DEBUG) + printf("Try bucket %d and original try %d\n", try_bucket, original_try); + try_bucket++; + if (try_bucket == hc) + try_bucket = 0; + if (c == hc) { // no space found (erroneously I think) + if (REALLY_DEBUG) + printf("Sorry no space found in hash for new node, looped through " + "everything (but should be found as hash entry should have been " + "dequeued\n"); + return -1; + } + c++; + } + return try_bucket; // hope this works no collisions. +} + +void EnqueueNewNode(struct LRUCache *cache, struct Queue *queue, + struct Hash *hash, int value, int key) { + // remember queue was just dequeueed + QNode *temp = newQNode(0); + temp->data = value; // obviously have to put the value in there + temp->key = key; // needed for handling hash collisions + int goodBucket = getGoodBucket(hash, key); + if (REALLY_DEBUG) + printf("GoodBucket to hash index on %d\n", goodBucket); + temp->bucket = goodBucket; // Get it a bucket + temp->prev = NULL; // because it will go at head + temp->next = queue->front; + + // attach node + if (queue->rear == NULL) { // should mean queue is empty but double check + if (queue->front != NULL) + if (REALLY_DEBUG) + printf("Rear null but head not, error\n"); + queue->rear = temp; + queue->front = temp; + } else if (queue->front == queue->rear) { + queue->front = temp; + queue->front->next = queue->rear; + queue->front->next->prev = queue->front; + } else { // min capacity 3 + queue->front->prev = temp; + queue->front = temp; + } + hash->array[goodBucket] = temp; // pass to hash + queue->count++; + return; +} + +void MoveNodeToFront(struct LRUCache *cache, struct Queue *queue, + struct Hash *hash, int value, int key, + int bucket) { // can happen on get requests + QNode *tmp = hash->array[bucket]; // pointer to the node in question + if (tmp == queue->front) { // Already at head, don't need to do anything. + return; + } else if (queue->front == + queue->rear) { // shouldn't be triggered based on above condition. + if (REALLY_DEBUG) + printf("This should never run. Should be handled by the above condition. " + "Implying error\n"); + if (REALLY_DEBUG) + printf("Q count should be 1. Queue count is %d\n", queue->count); + return; + } else // standard case + { // if in hash, should(!!) also be in the queue. If not, VERY BAD. Not super + // easy to check + if (REALLY_DEBUG) + printf("bucket is still %d and key is %d (1)\n", bucket, key); + if (tmp == NULL) + if (REALLY_DEBUG) + printf("QNode not found in Enqueue function bucket\n"); + if (tmp->prev == NULL) + if (REALLY_DEBUG) + printf( + "Temp previous is null but should not be (because not at head)\n"); + + if (REALLY_DEBUG) + printf("hash[bucket]->data is %d\n", tmp->data); + + tmp->prev->next = tmp->next; + if (tmp != queue->rear) + tmp->next->prev = tmp->prev; // SEG FAULT if tmp is rear!! + if (tmp == queue->rear) + queue->rear = tmp->prev; + tmp->prev->next = tmp->next; + queue->front->prev = tmp; + tmp->next = queue->front; + queue->front = + tmp; // queue front could point to queue->rear, or to an intermediary + queue->front->prev = NULL; // Now the node in question is right pointed + return; // queue count doesn't change. we're done? Will it work? + } + return; +} + +void Enqueue(struct LRUCache *cache, struct Queue *queue, struct Hash *hash, + int value, int key) { + int bucket = searchCache( + cache, key); // bucket can be -1 not found or bucket where exists + if (REALLY_DEBUG) + printf("Enqueuing key %d and bucket is: %d\n", key, bucket); + + if (queue->count == queue->capacity && bucket < 0) { + if (REALLY_DEBUG) + printf("Ready to dequeue rear and add new node\n"); + unsigned hashbucket = queue->rear->bucket; + deQueue(queue); + dehash(queue, hash, hashbucket, hash->array[hashbucket]->key); + } + + if (bucket == -1) { + EnqueueNewNode(cache, queue, hash, value, key); + return; + } else if (bucket >= 0) { // explicitly double checked, existing in cache + MoveNodeToFront(cache, queue, hash, value, key, bucket); + return; + } +} + +unsigned int hashfunc(unsigned capacity, int key) { + unsigned int provisional_bucket = (key * 353) % capacity; + return provisional_bucket; // may need adjustment (linear probing) +} + +int searchCache(struct LRUCache *cache, int key) { + // look in hash for item of "key"; double check key=key in case of collision + unsigned test_bucket = hashfunc(cache->capacity, key); + if (REALLY_DEBUG) + printf("test bucket %d\n ", test_bucket); // 9 + if (cache->hash->array[test_bucket] != NULL) { + if (cache->hash->array[test_bucket]->key == key) { + return test_bucket; // simplest case, returns location + } else { // linear probe time + int cap = cache->capacity; + unsigned original_test_bucket = test_bucket; + while (cache->hash->array[test_bucket] != NULL) { + test_bucket = ((test_bucket + 1) % cap); + if (test_bucket == + original_test_bucket) { // back to start, avoid infinite looping + if (REALLY_DEBUG) + printf("Probed hash, object not found. returning -1\n"); + return -1; // returns -1 + } + if (cache->hash->array[test_bucket] != NULL && + cache->hash->array[test_bucket]->key == key) + return test_bucket; + } + } + } else { // just have else for good measure. Simply not found in array + return -1; + } + return -1; +} +// Declarations +void freeQueue(Queue *queue); +void freeHash(Hash *hash); +void freeQNode(QNode *qnode); +void printQueueData(LRUCache *cache, char *op); + +struct LRUCache *lRUCacheCreate(int capacity) { + struct LRUCache *cache = malloc(sizeof(struct LRUCache)); + cache->capacity = capacity; + cache->queue = createQueue(capacity); + cache->hash = createHash(capacity); + return cache; +} // THIS IS WHERE THE ERROR HAPPEN(ED) -- fixed- (sort of), but not understood + +int lRUCacheGet(struct LRUCache *obj, int key) { + if (REALLY_DEBUG) + printf("\nGetting key %d\n", key); + int location = searchCache(obj, key); + if (location >= 0) { // found, else searchCache returns -1 + // printf("location found at %d\n", location); // PRINTF + struct QNode *tempNode = + obj->hash->array[location]; // found in hash SEG FAULT HERE!! + int tempData = tempNode->data; // Preserve Data before enqeueing + Enqueue(obj, obj->queue, obj->hash, tempData, + key); // TODO redundantly recalculates hash. Should be separate + // funtion "reorder" or "move_to_head"? + return tempData; + } else { + return location; // is -1 already + } +} + +void lRUCachePut(struct LRUCache *obj, int key, int value) { + int bucket = searchCache(obj, key); // already checks that key is right + if (bucket >= 0) { + int existing_value = obj->hash->array[bucket]->data; + if (value != existing_value) { + obj->hash->array[bucket]->data = value; + } + MoveNodeToFront(obj, obj->queue, obj->hash, value, key, bucket); + return; + } + // unsigned bucket = hashfunc(obj->capacity, key); // gets original bucket + if (REALLY_DEBUG) + printf("\nPutting key %d value %d\n", key, value); + Enqueue(obj, obj->queue, obj->hash, value, + key); // also dequeues/dehashes, adds to hash, moves to front +} + +void lRUCacheFree(struct LRUCache *obj) { + freeQueue(obj->queue); + freeHash(obj->hash); + free(obj); + return; +} + +void freeQueue(struct Queue *queue) { + struct QNode *curr = queue->front; + while (curr) { + QNode *tmp = curr; + curr = curr->next; + free(tmp); + } + free(queue); +} +void freeHash( + Hash *hash) { // if you free the nodes associated with the hash in the + // linked list, you also free them in the hash right? Because + // they're pointed at. They'll point at null or rather out of + // range things (seg fault territory?) + free(hash); +} +void freeQNode(QNode *qnode); + +void printQueueData(LRUCache *cache, char *op) { + QNode *n = cache->queue->front; + int c = 0; + QNode *p = n->prev; + while (n != NULL) { + printf("QC:%d ", cache->queue->capacity); + printf("QueueNode %d k:%d data = %d n->prev:%d, n->next:%d\n", c, n->key, + n->data, n->prev != NULL, n->next != NULL); + c++; + n = n->next; + } + if (p == NULL) + printf("Front's prev points to null. "); + printf("next queue node is NULL\n"); + QNode *r = cache->queue->rear; + if (r) + printf("Queue Rear exists:%d and its data: %d\n", r != NULL, r->data); +} + +void printCurrentState(LRUCache *cache, char *op) { + if (DEBUG_MODE) { + printf("\nCURRENT STATE after %s::::::::::\n", op); + printf("cache has capacity of %d\n", cache->capacity); + printQueueData(cache, op); + for (int i = 0; i < cache->capacity; i++) { + if (cache->hash->array[i] != NULL) + printf("Hashtable[%d] = %d\n", i, cache->hash->array[i]->data); + } + } +} diff --git a/lru_cache.cpp b/lru_cache.cpp new file mode 100644 index 0000000..f8d1656 --- /dev/null +++ b/lru_cache.cpp @@ -0,0 +1,60 @@ +// 146. LRU Cache +#include "leetcode.h" + +/* + * design a data structure that follows the constraints of a least recently used + * cache (LRU). implete the 'LRUCache' class. the functions 'get' and 'put' must + * each run in O(1) average time complexity + */ + +class LRUCache { +private: + typedef list<int> li; + typedef pair<int, li::iterator> pii; + typedef unordered_map<int, pii> hipii; + hipii cache; + li used; + int _capacity; + void touch(hipii::iterator i) { + int key = i->first; + used.erase(i->second.second); + used.push_front(key); + i->second.second = used.begin(); + } + +public: + LRUCache(int capacity) { _capacity = capacity; } + int get(int key) { + auto i = cache.find(key); + if (i == cache.end()) + return -1; + touch(i); + return i->second.first; + } + void put(int key, int value) { + auto i = cache.find(key); + if (i != cache.end()) + touch(i); + else { + if (cache.size() == _capacity) { + cache.erase(used.back()); + used.pop_back(); + } + used.push_front(key); + } + cache[key] = {value, used.begin()}; + } +}; + +int main() { + LRUCache *obj = new LRUCache(2); + obj->put(1, 1); + obj->put(2, 2); + printf("%d\n", obj->get(1)); // expect: 1 + obj->put(3, 3); + printf("%d\n", obj->get(2)); // expect: -1 + obj->put(4, 4); + printf("%d\n", obj->get(1)); // expect: -1 + printf("%d\n", obj->get(3)); // expect: 3 + printf("%d\n", obj->get(4)); // expect: 4 +} diff --git a/magical_string.c b/magical_string.c new file mode 100644 index 0000000..d04a5d1 --- /dev/null +++ b/magical_string.c @@ -0,0 +1,38 @@ +// 481. Magical String +#include <stdio.h> +#include <stdlib.h> + +/* + * a magical string 's' consists of only '1' & '2' and obeys the following rules + * the string 's' is magical because concatenating the number of contiguous + * occurences of characters '1' & '2' generates the string 's' itself. given + * integer 'n', return the number of 1's in the first 'n' number in the magical + * string 's'. + */ + +int magicalString(int n) { + char *s = malloc(sizeof(char) * (n + 1)); + s[0] = '1'; + s[1] = '2'; + s[2] = '2'; + int i = 2, cnt = 0, k = i; + while (k < n - 1) { + int c_i = s[i] - '0'; + char ch = s[k]; + for (int j = 0; j < c_i; j++) { + s[k + 1] = ch ^ 3; + k++; + } + i++; + } + s[k + 1] = '\0'; + for (i = 0; i < n; i++) + if (s[i] == '1') + cnt++; + return cnt; +} + +int main() { + printf("%d\n", magicalString(6)); // expect: 3 + printf("%d\n", magicalString(1)); // expect: 1 +} diff --git a/magnetic_force_2_balls.cpp b/magnetic_force_2_balls.cpp new file mode 100644 index 0000000..af40160 --- /dev/null +++ b/magnetic_force_2_balls.cpp @@ -0,0 +1,35 @@ +#include "leetcode.h" + +class Solution { +public: + int maxDistance(vector<int> &position, int m) { + sort(position.begin(), position.end()); + int ans = 1, i = 999999999; + while (ans < i) { + int mid = (ans + i) / 2 + 1; + if (check(position, m, mid)) + ans = mid; + else + i = mid - 1; + } + return ans; + } + +private: + int check(vector<int> &position, int m, int force) { + int pos = position[0]; + for (auto i = 1; i < position.size() && m > 1; ++i) + if (position[i] - pos >= force) { + --m; + pos = position[i]; + } + return m < 2; + } +}; + +int main() { + Solution obj; + vector<int> position = {1, 2, 3, 4, 7}; + int m = 3; + cout << obj.maxDistance(position, m); +} diff --git a/majority_element.c b/majority_element.c new file mode 100644 index 0000000..a62f167 --- /dev/null +++ b/majority_element.c @@ -0,0 +1,30 @@ +// 169. Majority Element +#include "leetcode.h" + +/* + * given an array 'nums' of size 'n', return the majority element. the majority + * element is the element that appears more than 'floor(n / 2)' times. you may + * assume that the majority element always exists in the array. + */ + +int majorityElement(int *nums, int nums_size) { + int key, j; + if (nums_size == 1) + return nums[0]; + for (int i = 0; i < nums_size; i++) { + key = nums[i]; + j = i - 1; + while (j >= 0 && nums[j] > key) { + nums[j + 1] = nums[j]; + j--; + } + nums[j + 1] = key; + } + return nums[nums_size / 2]; +} + +int main() { + int n1[] = {3, 2, 3}, n2[] = {2, 2, 1, 1, 1, 2, 2}; + printf("%d\n", majorityElement(n1, ARRAY_SIZE(n1))); // expect: 3 + printf("%d\n", majorityElement(n2, ARRAY_SIZE(n2))); // expect: 2 +} diff --git a/majority_element.py b/majority_element.py new file mode 100644 index 0000000..24865c7 --- /dev/null +++ b/majority_element.py @@ -0,0 +1,24 @@ +# 169. Majority Element + +""" +given an array 'nums' of size 'n', return the majority element. the majority +element is the element that appears more than 'floor(n / 2)' times. you may +assume that the majority element always exists in the array. +""" + + +class Solution(object): + def majorityElement(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + nums.sort() + n = len(nums) + return nums[n // 2] + + +if __name__ == "__main__": + obj = Solution() + print(obj.majorityElement([3, 2, 3])) + print(obj.majorityElement([2, 2, 1, 1, 1, 2, 2])) diff --git a/majority_element2.c b/majority_element2.c new file mode 100644 index 0000000..57a1e82 --- /dev/null +++ b/majority_element2.c @@ -0,0 +1,71 @@ +// 229. Majority Element II +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array of size 'n', find all elements that appear more than n + * / 3 times (floored) + */ + +int *majorityElement(int *nums, int nums_size, int *return_size) { + int one = INT_MIN, two = INT_MIN, cnt1 = 0, cnt2 = 0, n = nums_size; + for (int i = 0; i < n; i++) { + if (nums[i] == one) + cnt1++; + else if (nums[i] == two) + cnt2++; + else { + if (!cnt1) { + one = nums[i]; + cnt1 = 1; + } else if (!cnt2) { + two = nums[i]; + cnt2 = 1; + } else { + cnt1--; + cnt2--; + } + } + } + cnt1 = 0; + cnt2 = 0; + for (int i = 0; i < n; i++) { + if (nums[i] == one) + cnt1++; + else if (nums[i] == two) + cnt2++; + } + int *ans; + if (cnt1 > n / 3 && cnt2 > n / 3) { + ans = malloc(2 * sizeof(int)); + ans[0] = one; + ans[1] = two; + *return_size = 2; + return ans; + } else if (cnt1 > n / 3) { + ans = malloc(sizeof(int)); + ans[0] = one; + *return_size = 2; + return ans; + } else if (cnt1 > n / 3) { + ans = malloc(sizeof(int)); + ans[0] = two; + *return_size = 1; + return ans; + } else { + *return_size = 0; + return ans; + } +} + +int main() { + int n1[] = {3, 2, 3}, n2[] = {1}, n3[] = {1, 2}; + int *me1 = majorityElement(n1, 3, NULL); + int *me2 = majorityElement(n2, 1, NULL); + int *me3 = majorityElement(n3, 2, NULL); + printf("%d\n", me1[0]); // expect: 3 + printf("%d\n", me2[0]); // expect: 1 + printf("%d", me3[0]); // expect: 1 + printf("%d\n", me3[1]); // expect: 2 +} diff --git a/majority_element2.py b/majority_element2.py new file mode 100644 index 0000000..fccbf19 --- /dev/null +++ b/majority_element2.py @@ -0,0 +1,32 @@ +# 229. Majority Element II + +""" +given an integer array of size 'n', find all elements that appear more than n +/ 3 times (floored) +""" + + +class Solution(object): + def majorityElement(self, nums): + if not nums: + return [] + cnt1, cnt2, cdd1, cdd2 = 0, 0, 0, 1 + for n in nums: + if n == cdd1: + cnt1 += 1 + elif n == cdd2: + cnt2 += 1 + elif cnt1 == 0: + cdd1, cnt1 = n, 1 + elif cnt2 == 0: + cdd2, cnt2 = n, 1 + else: + cnt1, cnt2 = cnt1 - 1, cnt2 - 1 + return [n for n in (cdd1, cdd2) if nums.count(n) > len(nums) // 3] + + +if __name__ == "__main__": + obj = Solution() + print(obj.majorityElement([3, 2, 3])) # expect: 3 + print(obj.majorityElement([1])) # expect: 1 + print(obj.majorityElement([1, 2])) # expect: 1 2 diff --git a/make_array_empty.c b/make_array_empty.c new file mode 100644 index 0000000..e0628d0 --- /dev/null +++ b/make_array_empty.c @@ -0,0 +1,43 @@ +// 2659. Make Array Empty +#include "leetcode.h" + +/* + * given an integer array 'nums' containing distinct numbers and you can perform + * the following operations until the array is emtpy. if the first element has + * the smallest value, remove it. otherwise, put the first element at the end of + * the array. return an integer denoting the number of operations it takes to + * make 'nums' empty. + */ + +typedef struct { + int val; + int idx; +} pair; + +int cmp(const void *a, const void *b) { + return ((pair *)a)->val - ((pair *)b)->val; +} + +long long countOperationsToEmptyArray(int *nums, int numsSize) { + pair p[numsSize]; + for (int i = 0; i < numsSize; i++) { + p[i].val = nums[i]; + p[i].idx = i; + } + qsort(p, numsSize, sizeof(pair), cmp); + long long ans = numsSize; + for (int i = 1; i < numsSize; i++) + if (p[i].idx < p[i - 1].idx) + ans += numsSize - i; + return ans; +} + +int main() { + int n1[] = {3, 4, -1}, n2[] = {1, 2, 4, 3}, n3[] = {1, 2, 3}; + printf("%lld\n", countOperationsToEmptyArray(n1, ARRAY_SIZE(n1))); // expect: + // 5 + printf("%lld\n", countOperationsToEmptyArray(n2, ARRAY_SIZE(n2))); // expect: + // 5 + printf("%lld\n", countOperationsToEmptyArray(n3, ARRAY_SIZE(n3))); // expect: + // 3 +} diff --git a/make_array_empty.py b/make_array_empty.py new file mode 100644 index 0000000..cbe93b1 --- /dev/null +++ b/make_array_empty.py @@ -0,0 +1,31 @@ +# 2659. Make Array Empty + +""" +given an integer array 'nums' containing distinct numbers and you can perform +the following operations until the array is emtpy. if the first element has +the smallest value, remove it. otherwise, put the first element at the end of +the array. return an integer denoting the number of operations it takes to +make 'nums' empty. +""" + + +class Solution(object): + def countOperationsToEmptyArray(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + pos = {n: i for i, n in enumerate(nums)} + ans = n = len(nums) + nums.sort() + for i in range(1, n): + if pos[nums[i]] < pos[nums[i - 1]]: + ans += n - i + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.countOperationsToEmptyArray([3, 4, -1])) + print(obj.countOperationsToEmptyArray([1, 2, 4, 3])) + print(obj.countOperationsToEmptyArray([1, 2, 3])) diff --git a/make_array_increasing.cpp b/make_array_increasing.cpp new file mode 100644 index 0000000..482c0da --- /dev/null +++ b/make_array_increasing.cpp @@ -0,0 +1,59 @@ +// 1187. Make Array Strictly Increasing +#include <algorithm> +#include <limits.h> +#include <stdio.h> +#include <unordered_map> +#include <vector> +using namespace std; + +/* + * given two integer arrays 'arr1' and 'arr2', return the minimum number of + * operations (possibly zero) needed to make 'arr1' strictly Increasing in one + * opration, you can choose two indices '0 <= i <= arr1.len' and '0 <= j < + * arr2.len' and do the assignment 'arr1[i] = arr2[j]' if there is no way to + * make 'arr1' strictly increasing, return -1 + */ + +class Solution { + int check(int curr, int left, vector<int> &arr1, vector<int> &arr2, + vector<unordered_map<int, int>> &dp) { + if (curr == arr1.size()) + return 0; + if (dp[curr].find(left) != dp[curr].end()) + return dp[curr][left]; + int exclude, include; + if (arr1[curr] > left) + exclude = check(curr + 1, arr1[curr], arr1, arr2, dp); + else + exclude = INT_MAX; + int rep = upper_bound(arr2.begin(), arr2.end(), left) - arr2.begin(); + if (rep == arr2.size()) + include = INT_MAX; + else + include = check(curr + 1, arr2[rep], arr1, arr2, dp); + if (include == INT_MAX) + dp[curr][left] = exclude; + else + dp[curr][left] = min(exclude, include + 1); + return dp[curr][left]; + } + +public: + int makeArrayIncreasing(vector<int> &arr1, vector<int> &arr2) { + sort(arr2.begin(), arr2.end()); + vector<unordered_map<int, int>> dp(2001); + int val = check(0, INT_MIN, arr1, arr2, dp); + if (val == INT_MAX) + return -1; + return val; + } +}; + +int main() { + Solution obj; + vector<int> a1123 = {1, 5, 3, 6, 7}; + vector<int> a21 = {1, 3, 2, 4}, a22 = {4, 3, 1}, a23 = {1, 6, 3, 3}; + printf("%d\n", obj.makeArrayIncreasing(a1123, a21)); // expect: 1 + printf("%d\n", obj.makeArrayIncreasing(a1123, a22)); // expect: 1 + printf("%d\n", obj.makeArrayIncreasing(a1123, a23)); // expect: 1 +} diff --git a/make_string_great.c b/make_string_great.c new file mode 100644 index 0000000..b26fd39 --- /dev/null +++ b/make_string_great.c @@ -0,0 +1,40 @@ +// 1544. make the string great +#include "leetcode.h" + +/* + * given a string 's' of lower and upper case english letters. a good string is + * a string which doesn't have two adjacent characters 's[i]' and 's[i + 1]' + * where 0 <= i <= s.len - 2. s[i] is a lower case letter and s[i + 1] is the + * same letter but in upper case, or vice versa. to make the string good, you + * can choose two adjacent characters that make the string bad and remove them. + * you can keep doing this until the string becomes good. return the string + * after making it good. the answer is guaranteed to be unique under the given + * constraints. notice that an empty string is also good. + */ + +char *makeGood(char *s) { + int n = strlen(s), idx = -1; + char *ans = (char *)malloc((n + 1) * sizeof(char)); + for (int i = 0; i < n; i++) { + if (idx == -1) { + idx++; + ans[idx] = s[i]; + } else { + if (fabs(s[i] - ans[idx]) == 'a' - 'A') + idx--; + else + idx++, ans[idx] = s[i]; + } + } + idx++; + ans[idx] = '\0'; + ans = realloc(ans, idx + 1); + return ans; +} + +int main() { + char *s1 = "leEeetcode", *s2 = "abBAcC", *s3 = "s"; + printf("%s\n", makeGood(s1)); + printf("%s\n", makeGood(s2)); + printf("%s\n", makeGood(s3)); +} diff --git a/make_string_great.cpp b/make_string_great.cpp new file mode 100644 index 0000000..190bbed --- /dev/null +++ b/make_string_great.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +class Solution { +public: + string makeGood(string s) { + int n = s.size(); + if (n < 2) + return s; + while (n > 1) { + bool pair = false; + for (int i = 0; i < n; i++) { + char curr = s[i], next = s[i + 1]; + if (abs(curr - next) == 32) { + s = s.substr(0, i) + s.substr(i + 2); + pair = true; + break; + } + } + if (!pair) + break; + } + return s; + } +}; + +int main() { + Solution obj; + cout << obj.makeGood("HhvmLxpqQPXlMVQWwq"); +} diff --git a/make_string_great.py b/make_string_great.py new file mode 100644 index 0000000..aa63fa7 --- /dev/null +++ b/make_string_great.py @@ -0,0 +1,38 @@ +# 1544. make the string great + +""" +given a string 's' of lower and upper case english letters. a good string is +a string which doesn't have two adjacent characters 's[i]' and 's[i + 1]' +where 0 <= i <= s.len - 2. s[i] is a lower case letter and s[i + 1] is the +same letter but in upper case, or vice versa. to make the string good, you +can choose two adjacent characters that make the string bad and remove them. +you can keep doing this until the string becomes good. return the string +after making it good. the answer is guaranteed to be unique under the given +constraints. notice that an empty string is also good. +""" + + +class Solution(object): + def makeGood(self, s): + """ + :type s: str + :rtype: str + """ + ans = [] + for c in s: + if not ans: + ans.append(c) + elif ans[-1].isupper() and ans[-1].lower() == c: + ans.pop() + elif ans[-1].islower() and ans[-1].upper() == c: + ans.pop() + else: + ans.append(c) + return "".join(ans) + + +if __name__ == "__main__": + obj = Solution() + print(obj.makeGood("leEeetcode")) + print(obj.makeGood("abBAcC")) + print(obj.makeGood("s")) diff --git a/make_string_great.rs b/make_string_great.rs new file mode 100644 index 0000000..76a28a2 --- /dev/null +++ b/make_string_great.rs @@ -0,0 +1,21 @@ +struct Solution; + +impl Solution { + pub fn make_good(s: String) -> String { + let diff_cases = |c1: char, c2: char| c1.to_ascii_lowercase() == c2.to_ascii_lowercase() && c1 != c2; + s.chars().into_iter().fold(Vec::with_capacity(s.len()), |mut v: Vec<char>, c| { + match v.last() { + Some(prev_c) if diff_cases(c, *prev_c) => { + v.pop(); + } + _ => v.push(c) + } + v + }).iter().collect() + } +} + +fn main() { + let s = "leEeetcode".to_string(); + print!("{}", Solution::make_good(s)); +} diff --git a/marbles_in_bags.c b/marbles_in_bags.c new file mode 100644 index 0000000..71c2560 --- /dev/null +++ b/marbles_in_bags.c @@ -0,0 +1,43 @@ +// 2551. Put Marbles in Bags +#include <stdio.h> +#include <stdlib.h> + +/* + * you have 'k' bags. you are given a 0-indexed integer array 'weights' where + * 'weights[i]' is the weight of the i'th marble. you are also given the integer + * 'k'. divide the marbles into the 'k' bags according to the following rules + * - no bag is empty + * - if the i'th marble and the j'th marble are in a bag, then all the marbles + * with an index between the i'th and j'th indices should also be in that same + * bag. + * - if a bag onsists of all the marbles with an index from 'i' to 'j' + * inclusively, then the cost of the bag is 'weights[i] + weights[j]' the score + * after distributing the marbles is the sum of the costs of all the 'k' bags. + * return the difference between the maximum and minimum scores among marble + * distributions + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +long long putMarbles(int *weights, int weights_size, int k) { + int n = weights_size; + if (n == k || k == 1) + return 0; + int *data = malloc((n - 1) * sizeof(int)); + for (int i = 0; i < n - 1; i++) + data[i] = weights[i] + weights[i + 1]; + qsort(data, n - 1, sizeof(int), cmp); + long long min = weights[0] + weights[n - 1]; + long long max = weights[0] + weights[n - 1]; + for (int i = 0; i < k - 1; i++) { + min += data[i]; + max += data[n - 2 - i]; + } + return max - min; +} + +int main() { + int w1[] = {1, 3, 5, 1}, w2[] = {1, 3}; + printf("%lld\n", putMarbles(w1, 4, 2)); // expect: 4 + printf("%lld\n", putMarbles(w2, 2, 2)); // expect: 0 +} diff --git a/marbles_in_bags.cpp b/marbles_in_bags.cpp new file mode 100644 index 0000000..4640eb9 --- /dev/null +++ b/marbles_in_bags.cpp @@ -0,0 +1,48 @@ +// 2551. Put Marbles in Bags +#include "leetcode.h" + +/* + * you have 'k' bags. you are given a 0-indexed integer array 'weights' where + * 'weights[i]' is the weight of the i'th marble. you are also given the integer + * 'k'. divide the marbles into the 'k' bags according to the following rules + * - no bag is empty + * - if the i'th marble and the j'th marble are in a bag, then all the marbles + * with an index between the i'th and j'th indices should also be in that same + * bag. + * - if a bag onsists of all the marbles with an index from 'i' to 'j' + * inclusively, then the cost of the bag is 'weights[i] + weights[j]' the score + * after distributing the marbles is the sum of the costs of all the 'k' bags. + * return the difference between the maximum and minimum scores among marble + * distributions + */ + +class Solution { +public: + long long putMarbles(vector<int> &weights, int k) { + priority_queue<int> pq1; + priority_queue<int, vector<int>, greater<int>> pq2; + for (int i = 0; i < weights.size() - 1; i++) { + pq1.push(weights[i] + weights[i + 1]); + pq2.push(weights[i] + weights[i + 1]); + if (pq1.size() > k - 1) { + pq1.pop(); + pq2.pop(); + } + } + long long ans1 = 0, ans2 = 0; + while (!pq1.empty()) { + ans1 += pq1.top(); + ans2 += pq2.top(); + pq1.pop(); + pq2.pop(); + } + return ans2 - ans1; + } +}; + +int main() { + Solution obj; + vector<int> w1 = {1, 3, 5, 1}, w2 = {1, 3}; + printf("%lld\n", obj.putMarbles(w1, 2)); // expect: 4 + printf("%lld\n", obj.putMarbles(w2, 2)); // expect: 0 +} diff --git a/matchsticks_square.c b/matchsticks_square.c new file mode 100644 index 0000000..7cb561f --- /dev/null +++ b/matchsticks_square.c @@ -0,0 +1,61 @@ +// 473. Matchsticks to Square +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array 'matchsticks' where 'matchsticks[i]' is the length of + * the i'th matchstick. you want to use all the matchsticks to make one square. + * you should not break any stick, but you can link them up, and each matchstick + * can be used exactly one time. return 1 if you make square, 0 if not. + */ + +int cmp(const void *a, const void *b) { return *(int *)b - *(int *)a; } + +bool dfs(int *nums, bool *visited, int curr, int n, int group, long long target, + long long sum) { + if (group == 4) + return true; + if (sum > target) + return false; + if (sum == target) + return dfs(nums, visited, group, n, group + 1, target, 0); + int last = -1; + for (int i = curr; i < n; i++) { + if (visited[i] == true) + continue; + if (nums[i] == last) + continue; + visited[i] = true; + if (dfs(nums, visited, i + 1, n, group, target, sum + nums[i]) == true) + return true; + visited[i] = false; + last = nums[i]; + } + return false; +} + +bool makeSquare(int *matchsticks, int matchsticksSize) { + int n = matchsticksSize; + bool ans; + long long sum = 0; + for (int i = 0; i < n; i++) + sum += matchsticks[i]; + if (sum % 4 != 0) + return false; + long long target = sum / 4; + qsort(matchsticks, n, sizeof(int), cmp); + if (matchsticks[0] > target) + return false; + bool *visited = calloc(n, sizeof(bool)); + ans = dfs(matchsticks, visited, 0, n, 0, target, 0); + free(visited); + return ans; +} + +int main() { + int matchsticks1[] = {1, 1, 2, 2, 2}, ms1 = 5; + int matchsticks2[] = {3, 3, 3, 3, 4}, ms2 = 5; + printf("%d\n", makeSquare(matchsticks1, ms1)); // expect: 1 + printf("%d\n", makeSquare(matchsticks2, ms2)); // expect: 0 +} diff --git a/matchsticks_square.cpp b/matchsticks_square.cpp new file mode 100644 index 0000000..f2422b8 --- /dev/null +++ b/matchsticks_square.cpp @@ -0,0 +1,46 @@ +#include "leetcode.h" + +class Solution { +public: + bool makesquare(vector<int> &matchsticks) { + sort(matchsticks.begin(), matchsticks.end(), greater<int>()); + int total = accumulate(matchsticks.begin(), matchsticks.end(), 0); + side = total; + if ((float)total / 4 > side || matchsticks[0] > side) + return false; + return helper(0, side, 0, matchsticks); + } + +private: + int side; + bool helper(int i, int space, int done, vector<int> &matchsticks) { + if (done == 3) + return true; + for (; i < matchsticks.size(); i++) { + int num = matchsticks[i]; + bool ans; + if (num > space) + continue; + matchsticks[i] = side + 1; + if (num == space) + ans = helper(1, side, done + 1, matchsticks); + else + ans = helper(i + 1, space - num, done, matchsticks); + if (ans) + return true; + matchsticks[i] = num; + while (i < matchsticks.size() && matchsticks[i + 1] == num) + i++; + } + return false; + } +}; + +int main() { + Solution obj; + vector<int> matchsticks = {1, 1, 2, 2, 2}; + if (obj.makesquare(matchsticks)) + cout << "true"; + else + cout << "false"; +} diff --git a/matrix_diagonal_sum.c b/matrix_diagonal_sum.c new file mode 100644 index 0000000..d052238 --- /dev/null +++ b/matrix_diagonal_sum.c @@ -0,0 +1,34 @@ +// 1572. Matrix Diagonal Sum +#include <stdio.h> + +/* + * given a square matrix 'mat', return the sum of the matrix + * diagonals. only include the sum of all the elements on the + * primary diagonal and all the elements on the secondary + * diagonal that are not part of the primary + */ + +int diagonalSum(int **mat, int mat_size, int *mat_col_size) { + int i = 0, j = mat_size - 1, sum = 0; + while (i < mat_size) { + sum += mat[i][i]; + i++; + } + i = 0; + while (i < mat_size) { + if (i != j) + sum += mat[i][j]; + i++, j--; + } + return sum; +} + +int main() { + int m1[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, ms1 = 3, mcs1[] = {}; + int m2[][4] = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}}, + ms2 = 4, mcs2[] = {}; + int m3[][1] = {{5}}, ms3 = 1, mcs3[] = {}; + printf("%d\n", diagonalSum(m1, ms1, mcs1)); // expect: 25 + printf("%d\n", diagonalSum(m2, ms2, mcs2)); // expect: 8 + printf("%d\n", diagonalSum(m3, ms3, mcs3)); // expect: 5 +} diff --git a/matrix_diagonal_sum.cpp b/matrix_diagonal_sum.cpp new file mode 100644 index 0000000..d5234b5 --- /dev/null +++ b/matrix_diagonal_sum.cpp @@ -0,0 +1,33 @@ +// 1572. Matrix Diagonal Sum +#include "leetcode.h" + +/* + * given a square matrix 'mat', return the sum of the matrix + * diagonals. only include the sum of all the elements on the + * primary diagonal and all the elements on the secondary + * diagonal that are not part of the primary + */ + +class Solution { +public: + int diagonalSum(vvd(int) & mat) { + int n = mat.size(), ans = 0; + for (int i = 0; i < n; i++) { + if (i != n - i - 1) + ans += mat[i][i] + mat[i][n - i - 1]; + else + ans += mat[i][i]; + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) m1 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; + vvd(int) m2 = {{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}}; + vvd(int) m3 = {{5}}; + printf("%d\n", obj.diagonalSum(m1)); // expect: 25 + printf("%d\n", obj.diagonalSum(m2)); // expect: 8 + printf("%d\n", obj.diagonalSum(m3)); // expect: 5 +} diff --git a/max_69.cpp b/max_69.cpp new file mode 100644 index 0000000..bc8abeb --- /dev/null +++ b/max_69.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + int maximum69Number(int num) { + if (num == 9999) + return num; + string n = to_string(num); + for (auto &i : n) + if (i == '6') { + i = '9'; + break; + } + return stoi(n); + } +}; + +int main() { + Solution obj; + cout << obj.maximum69Number(9669); +} diff --git a/max_69.rs b/max_69.rs new file mode 100644 index 0000000..0bead97 --- /dev/null +++ b/max_69.rs @@ -0,0 +1,11 @@ +struct Solution; + +impl Solution { + pub fn maximum69_number(num: i32) -> i32 { + num.to_string().replacen("6", "9", 1).parse().unwrap() + } +} + +fn main() { + print!("{}", Solution::maximum69_number(9669)); +} diff --git a/max_area_cake.cpp b/max_area_cake.cpp new file mode 100644 index 0000000..f60523e --- /dev/null +++ b/max_area_cake.cpp @@ -0,0 +1,25 @@ +#include "leetcode.h" + +class Solution { +public: + int maxArea(int h, int w, vector<int> &horizontalCuts, + vector<int> &verticalCuts) { + sort(horizontalCuts.begin(), horizontalCuts.end()); + sort(verticalCuts.begin(), verticalCuts.end()); + int maxH = max(horizontalCuts[0], h - horizontalCuts.back()); + int maxV = max(verticalCuts[0], w - verticalCuts.back()); + for (int i = 1; i < horizontalCuts.size(); i++) + maxH = max(maxH, horizontalCuts[i] - horizontalCuts[i - 1]); + for (int i = 1; i < verticalCuts.size(); i++) + maxV = max(maxV, verticalCuts[i] - verticalCuts[i - 1]); + return (int)((long)maxH * maxV % 1000000007); + } +}; + +int main() { + Solution obj; + int h = 5, w = 4; + vector<int> horizontalCuts = {1, 2, 4}; + vector<int> verticalCuts = {1, 3}; + cout << obj.maxArea(h, w, horizontalCuts, verticalCuts); +} diff --git a/max_area_island.cpp b/max_area_island.cpp new file mode 100644 index 0000000..aad8b2d --- /dev/null +++ b/max_area_island.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + int maxAreaOfIsland(vector<vector<int>> &grid) { + int ans = 0; + n = grid.size(), m = grid[0].size(); + for (int i = 0; i < n; i++) + for (int j = 0; j < m; j++) + if (grid[i][j]) + ans = max(ans, helper(i, j, grid)); + return ans; + } + +private: + int n = 0, m = 0; + int helper(int i, int j, vector<vector<int>> &grid) { + if (i < 0 || j < 0 || i >= n || j >= m || !grid[i][j]) + return 0; + grid[i][j] = 0; + return 1 + helper(i - 1, j, grid) + helper(i, j - 1, grid) + + helper(i + 1, j, grid) + helper(i, j + 1, grid); + } +}; diff --git a/max_bags_rocks.cpp b/max_bags_rocks.cpp new file mode 100644 index 0000000..35c66bc --- /dev/null +++ b/max_bags_rocks.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + int maximumBags(vector<int> &capacity, vector<int> &rocks, + int additionalRocks) { + vector<int> count; + int n = rocks.size(), ans; + for (int i = 0; i < n; ++i) + count.push_back(capacity[i] - rocks[i]); + sort(count.begin(), count.end()); + for (ans = 0; ans < n && additionalRocks >= count[ans]; ++ans) + additionalRocks -= count[ans]; + return ans; + } +}; + +int main() { + Solution obj; + vector<int> capacity = {2, 3, 4, 5}, rocks = {1, 2, 4, 4}; + cout << obj.maximumBags(capacity, rocks, 2); +} diff --git a/max_bags_rocks.rs b/max_bags_rocks.rs new file mode 100644 index 0000000..808c393 --- /dev/null +++ b/max_bags_rocks.rs @@ -0,0 +1,20 @@ +struct Solution; + +impl Solution { + pub fn maximum_bags(capacity: Vec<i32>, rocks: Vec<i32>, mut additional_rocks: i32) -> i32 { + let mut bag_space = (0..rocks.len()).map(|i| capacity[i] - rocks[i]) + .filter(|&d| d > 0) + .collect::<Vec<_>>(); + let bag_full = rocks.len() - bag_space.len(); + bag_space.sort_unstable(); + bag_space.into_iter() + .take_while(|&n| { additional_rocks -= n; additional_rocks >= 0 }) + .count() as i32 + bag_full as i32 + } +} + +fn main() { + let capacity = vec![2,3,4,5]; + let rocks = vec![1,2,4,4]; + print!("{}", Solution::maximum_bags(capacity, rocks, 2)); //expect: 3 +} diff --git a/max_consecutive_ones3.cpp b/max_consecutive_ones3.cpp new file mode 100644 index 0000000..cff044f --- /dev/null +++ b/max_consecutive_ones3.cpp @@ -0,0 +1,27 @@ +#include "leetcode.h" + +class Solution { +public: + int longestOnes(vector<int> &nums, int k) { + int start = 0, end, count = 0, ans = 0; + for (int end = 0; end < nums.size(); end++) { + if (!nums[end]) + count++; + if (count == k + 1) { + while (nums[start]) + start++; + start++; + count--; + } + ans = max(ans, end - start + 1); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums = {1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0}; + int k = 2; + cout << obj.longestOnes(nums, k); +} diff --git a/max_depth_binary_tree.c b/max_depth_binary_tree.c new file mode 100644 index 0000000..ba70145 --- /dev/null +++ b/max_depth_binary_tree.c @@ -0,0 +1,22 @@ +/* 104. Maximum Depth of Binary Tree + * given the 'root' of a binary tree, return its maximum depth. a binary tree's + * max depth is the number of nodes along the longest path from the root node + * down to the farthest leaf node. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int maxDepth(struct TreeNode *root) { + if (!root) + return 0; + int max_left = maxDepth(root->left); + int max_rght = maxDepth(root->right); + if (max_left > max_rght) + return max_left + 1; + else + return max_rght + 1; +} diff --git a/max_depth_binary_tree.cpp b/max_depth_binary_tree.cpp new file mode 100644 index 0000000..e5ecc10 --- /dev/null +++ b/max_depth_binary_tree.cpp @@ -0,0 +1,19 @@ +// 104. Maximum Depth of Binary Tree +#include "leetcode.h" + +/* + * given the 'root' of a binary tree, return its maximum depth. a binary tree's + * max depth is the number of nodes along the longest path from the root node + * down to the farthest leaf node. + */ + +class Solution { +public: + int maxDepth(TreeNode *root) { + if (!root) + return 0; + int max_left = maxDepth(root->left); + int max_rght = maxDepth(root->right); + return max(max_left, max_rght) + 1; + } +}; diff --git a/max_diff_node_ancestor.c b/max_diff_node_ancestor.c new file mode 100644 index 0000000..7d2ba9e --- /dev/null +++ b/max_diff_node_ancestor.c @@ -0,0 +1,49 @@ +// 1026. Maximum Difference Between Node and Ancestor +#include "leetcode.h" + +/* + * given the 'root' of a binary tree, find the maximum value 'v' for which there + * exists different nodes 'a' and 'b' where 'v = | a.val - b.val |' and 'a' is + * an ancesotr of 'b'. a node 'a' is an ancesotr of 'b' if either any child if + * 'a' is equal to 'b' or any child 'a' is an ancestor of 'b'. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int helper(struct TreeNode *node, int min_seen, int max_seen) { + int leftdiff, rightdiff; + if (!(node->val < min_seen || node->val > max_seen)) + ; + else { + if (node->val > max_seen) + max_seen = node->val; + else + min_seen = node->val; + } + int diff = max_seen - min_seen; + if (node->left == NULL && node->right == NULL) + return diff; + else if (!(node->left != NULL && node->right != NULL)) { + if (node->left == NULL) { + leftdiff = 0; + rightdiff = helper(node->right, min_seen, max_seen); + return (rightdiff > diff ? rightdiff : diff); + } else { + rightdiff = 0; + leftdiff = helper(node->left, min_seen, max_seen); + return (leftdiff > diff ? leftdiff : diff); + } + } else { + leftdiff = helper(node->left, min_seen, max_seen); + rightdiff = helper(node->right, min_seen, max_seen); + return leftdiff > rightdiff ? leftdiff : rightdiff; + } +} + +int maxAncestorDiff(struct TreeNode *root) { + return !root ? 0 : helper(root, root->val, root->val); +} diff --git a/max_diff_node_ancestor.cpp b/max_diff_node_ancestor.cpp new file mode 100644 index 0000000..ab96947 --- /dev/null +++ b/max_diff_node_ancestor.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + int diff = INT_MIN; + int maxAncestorDiff(TreeNode *root) { + if (!root) + return 0; + int mx = INT_MIN, mn = INT_MAX; + getMax(root, mx, mn); + return diff; + } + +private: + int getMax(TreeNode *root, int mx, int mn) { + mx = max(mx, root->val); + mn = min(mn, root->val); + diff = max(diff, mx - mn); + getMax(root->left, mx, mn); + getMax(root->right, mx, mn); + } +}; diff --git a/max_diff_node_ancestor.py b/max_diff_node_ancestor.py new file mode 100644 index 0000000..e1a0648 --- /dev/null +++ b/max_diff_node_ancestor.py @@ -0,0 +1,48 @@ +# 1026. Maximum Difference Between Node and Ancestor + +""" +given the 'root' of a binary tree, find the maximum value 'v' for which there +exists different nodes 'a' and 'b' where 'v = | a.val - b.val |' and 'a' is +an ancesotr of 'b'. a node 'a' is an ancesotr of 'b' if either any child if +'a' is equal to 'b' or any child 'a' is an ancestor of 'b'. +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def helper(self, root, min_val, max_val): + if not root: + return + self.diff = max( + self.diff, max(abs(min_val - root.val), abs(max_val - root.val)) + ) + min_val = min(min_val, root.val) + max_val = max(max_val, root.val) + self.helper(root.left, min_val, max_val) + self.helper(root.right, min_val, max_val) + + def maxAncestorDiff(self, root): + """ + :type root: TreeNode + :rtype: int + """ + if not root: + return 0 + self.diff = 0 + self.helper(root, root.val, root.val) + return self.diff + + +if __name__ == "__main__": + obj = Solution() + print( + obj.maxAncestorDiff(root=[8, 3, 10, 1, 6, None, 14, None, None, 4, 7, 13]) + ) # expect: 7 + print(obj.maxAncestorDiff(root=[1, None, 2, None, 0, 3])) # expect: 3 diff --git a/max_diff_node_ancestor.rs b/max_diff_node_ancestor.rs new file mode 100644 index 0000000..671bd27 --- /dev/null +++ b/max_diff_node_ancestor.rs @@ -0,0 +1,61 @@ +use std::cmp; +use std::rc::Rc; +use std::cell::RefCell; + +#[derive(Debug, PartialEq, Eq)] +pub struct TreeNode { + pub val: i32, + pub left: Option<Rc<RefCell<TreeNode>>>, + pub right: Option<Rc<RefCell<TreeNode>>> +} + +struct MinMax { + min: i32, + max: i32, + ans: i32 +} + +impl TreeNode { + #[inline] + pub fn new(val: i32) -> Self { + TreeNode { + val, + left: None, + right: None + } + } +} + +impl Solution { + fn minMax(node_ref: Rc<RefCell<TreeNode>>) -> MinMax { + let node = node_ref.borrow(); + let mut a = MinMax { + min: node.val, + max: node.val, + ans: 0 + }; + if node.left.is_none() && node.right.is_none() { + a + } else { + let children = vec![&node.left, &node.right]; + for child_option in children.iter() { + if let Some(child) = child_option { + let c = Self::minMax(Rc::clone(&child)); + a.ans = cmp::max(a.ans, c.ans); + a.ans = cmp::max(a.ans, (node.val - c.min).abs()); + a.ans = cmp::max(a.ans, (node.val - c.max).abs()); + a.min = cmp::min(a.min, c.min); + a.max = cmp::max(a.max, c.max); + } + } + a + } + } + pub fn max_ancestor_diff(root: Option<Rc<RefCell<TreeNode>>>) -> i32 { + if let Some(node_ref) = root { + Self::minMax(Rc::clone(&node_ref)).ans + } else { + panic!("bad input"); + } + } +} diff --git a/max_distance_closest_person.c b/max_distance_closest_person.c new file mode 100644 index 0000000..b0faf1e --- /dev/null +++ b/max_distance_closest_person.c @@ -0,0 +1,42 @@ +// 849. Maximize Distance to Closest Person +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array representing a row of 'seats' where 'seats[i] = 1' represents + * a person sitting in the i'th seat, and 'seats[i] = 0' represents that the + * i'th seat is empty (0-indexed). there is at least one empty seat, and at + * least one person sitting. alex wants to sit in the seat such that the + * distance between him and the closest person to him is maximised. return that + * maximum distance to the closest person. + */ + +int maxDistToClosest(int *seats, int seats_size) { + int n = seats_size, max = 0, cnt = 0, i; + for (i = 0; i < n; i++) { + if (!seats[i]) + cnt++; + else + break; + } + max = cnt; + cnt = 0; + for (int j = i; j < n; j++) { + if (!seats[j]) + cnt++; + else { + max = fmax(max, (cnt + 1) / 2); + cnt = 0; + } + } + max = fmax(max, cnt); + return max; +} + +int main() { + int s1[] = {1, 0, 0, 0, 1, 0, 1}, s2[] = {1, 0, 0, 0}, s3[] = {0, 1}; + printf("%d\n", maxDistToClosest(s1, 7)); // expect: 2 + printf("%d\n", maxDistToClosest(s2, 7)); // expect: 3 + printf("%d\n", maxDistToClosest(s3, 7)); // expect: 1 +} diff --git a/max_distance_closest_person.cpp b/max_distance_closest_person.cpp new file mode 100644 index 0000000..a9203fe --- /dev/null +++ b/max_distance_closest_person.cpp @@ -0,0 +1,39 @@ +// 849. Maximize Distance to Closest Person +#include "leetcode.h" + +/* + * given an array representing a row of 'seats' where 'seats[i] = 1' represents + * a person sitting in the i'th seat, and 'seats[i] = 0' represents that the + * i'th seat is empty (0-indexed). there is at least one empty seat, and at + * least one person sitting. alex wants to sit in the seat such that the + * distance between him and the closest person to him is maximised. return that + * maximum distance to the closest person. + */ + +class Solution { +public: + int maxDistToClosest(vector<int> &seats) { + int n = seats.size(), empty = 0, ans = 0, idx1 = -1, idx2 = -1; + for (int i = 0; i < n; i++) { + if (seats[i] == 1) { + empty = 0; + if (idx1 == -1) + idx1 = i; + idx2 = i; + } else { + empty++; + ans = max(ans, (empty + 1) / 2); + } + } + ans = max({ans, idx1, n - 1 - idx2}); + return ans; + } +}; + +int main() { + Solution obj; + vector<int> s1 = {1, 0, 0, 0, 1, 0, 1}, s2 = {1, 0, 0, 0}, s3 = {0, 1}; + printf("%d\n", obj.maxDistToClosest(s1)); // expect: 2 + printf("%d\n", obj.maxDistToClosest(s2)); // expect: 3 + printf("%d\n", obj.maxDistToClosest(s3)); // expect: 1 +} diff --git a/max_dot_product.c b/max_dot_product.c new file mode 100644 index 0000000..153d104 --- /dev/null +++ b/max_dot_product.c @@ -0,0 +1,36 @@ +// 1458. Max Dot Product of Two Subsequences +#include <stdio.h> +#include <stdlib.h> + +/* + * given two arrays 'nums1, nums2'. return the maximum dot product between + * non-empty subsequences of nums1 and nums2 with the same length. a subsequence + * of an array is a new array which is formed from the original array by + * deleting some (can be none) of the characters without disturbing the relative + * positions of the remaining characters. + */ + +int maxDotProduct(int *nums1, int num1_size, int *nums2, int nums2_size) { + int n = A.size(), m = B.size(); + vector<vector<int>> dp(n, vector<int>(m)); + for (int i = 0; i < n; ++i) { + for (int j = 0; j < m; ++j) { + dp[i][j] = A[i] * B[j]; + if (i && j) + dp[i][j] += max(dp[i - 1][j - 1], 0); + if (i) + dp[i][j] = max(dp[i][j], dp[i - 1][j]); + if (j) + dp[i][j] = max(dp[i][j], dp[i][j - 1]); + } + } + return dp[n - 1][m - 1]; +} +int main() { + int n11[] = {2, 1, -2, 5}, n21[] = {3, 0, -6}; + int n12[] = {3, -2}, n22[] = {2, -6, 7}; + int n13[] = {-1, -1}, n23[] = {1, 1}; + printf("%d\n", maxDotProduct(n11, 4, n21, 3)); // expect: 18 + printf("%d\n", maxDotProduct(n12, 2, n22, 3)); // expect: 21 + printf("%d\n", maxDotProduct(n13, 2, n23, 2)); // expect: -1 +} diff --git a/max_dot_product.py b/max_dot_product.py new file mode 100644 index 0000000..f7e1803 --- /dev/null +++ b/max_dot_product.py @@ -0,0 +1,31 @@ +# 1458. Max Dot Product of Two Subsequences + +""" +given two arrays 'nums1, nums2'. return the maximum dot product between +non-empty subsequences of nums1 and nums2 with the same length. a subsequence +of an array is a new array which is formed from the original array by +deleting some (can be none) of the characters without disturbing the relative +positions of the remaining characters. +""" + +class Solution(object): + def maxDotProduct(self, nums1, nums2): + n, m = len(nums1), len(nums2) + dp = [[0] * (m) for in xrange(n)] + for i in xrange(n): + for j in xrange(m): + dp[i][j] = nums1[i] * nums2[j] + if i and j: + dp[i][j] += max(dp[i - 1][j - 1], 0) + if i: + dp[i][j] = max(dp[i][j], dp[i - 1][j]) + if j: + dp[i][j] = max(dp[i][j], dp[i][j - 1]) + return dp[-1][-1] + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxDotProduct([2,1,-2,5], [3,0,-6])) # expect: 18 + print(obj.maxDotProduct([3,-2],[2,-6,7])) # expect: 21 + print(obj.maxDotProduct([-1,-1],[1,1])) # expect: -1 diff --git a/max_element_decr_rearr.c b/max_element_decr_rearr.c new file mode 100644 index 0000000..9c93905 --- /dev/null +++ b/max_element_decr_rearr.c @@ -0,0 +1,39 @@ +// 1846. Maximum Element After Decreasing and Rearranging +#include "leetcode.h" + +/* + * given an array of positive integers 'arr', perform some operations on 'arr' + * so that it satisfies these conditions: + * - the value of the first element in 'arr' must be 1 + * - the absolute difference between any two adjacent elements must be less than + * or equal to 1. in other words 'abs(arr[i] - arr[i - 1]) <= 1' for each i + * where 1 <= i < arr.length (0-indexed). 'abs(x)' is the absolute value of 'x' + * there are two types operations that you can perform any number of times: + * decrease the value of any element of 'arr' to a smaller positive integer + * rearrange the elements of 'arr' to be in any order + * return the maximum possible value of an element in 'arr' after performing the + * operations to satisfy the conditions. + */ + +int cmp(const void *a, const void *b) { return (*(int *)a - *(int *)b); } + +int maximumElementAfterDecrementingAndRearranging(int *arr, int arr_size) { + qsort(arr, arr_size, sizeof(int), cmp); + int ans = 0, x = 1; + for (int i = 0; i < arr_size; i++) + if (arr[i] >= x) { + ans = (ans < x) ? x : ans; + x++; + } + return ans; +} + +int main() { + int a1[] = {2, 2, 1, 2, 1}, a2[] = {100, 1, 1000}, a3[] = {1, 2, 3, 4, 5}; + printf("%d\n", maximumElementAfterDecrementingAndRearranging( + a1, ARRAY_SIZE(a1))); // expect: 2 + printf("%d\n", maximumElementAfterDecrementingAndRearranging( + a2, ARRAY_SIZE(a2))); // expect: 3 + printf("%d\n", maximumElementAfterDecrementingAndRearranging( + a3, ARRAY_SIZE(a3))); // expect: 5 +} diff --git a/max_element_decr_rearr.py b/max_element_decr_rearr.py new file mode 100644 index 0000000..3f1267d --- /dev/null +++ b/max_element_decr_rearr.py @@ -0,0 +1,35 @@ +# 1846. Maximum Element After Decreasing and Rearranging + +""" +given an array of positive integers 'arr', perform some operations on 'arr' +so that it satisfies these conditions: +- the value of the first element in 'arr' must be 1 +- the absolute difference between any two adjacent elements must be less than +or equal to 1. in other words 'abs(arr[i] - arr[i - 1]) <= 1' for each i +where 1 <= i < arr.length (0-indexed). 'abs(x)' is the absolute value of 'x' +there are two types operations that you can perform any number of times: +decrease the value of any element of 'arr' to a smaller positive integer +rearrange the elements of 'arr' to be in any order +return the maximum possible value of an element in 'arr' after performing the +operations to satisfy the conditions. +""" + + +class Solution(object): + def maximumElementAfterDecrementingAndRearranging(self, arr): + """ + :type arr: List[int] + :rtype: int + """ + arr.sort() + ans = 0 + for i in arr: + ans = min(ans + 1, i) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.maximumElementAfterDecrementingAndRearranging(arr=[2, 2, 1, 2, 1])) + print(obj.maximumElementAfterDecrementingAndRearranging(arr=[100, 1, 1000])) + print(obj.maximumElementAfterDecrementingAndRearranging(arr=[1, 2, 3, 4, 5])) diff --git a/max_equal_freq.c b/max_equal_freq.c new file mode 100644 index 0000000..1d2b7ad --- /dev/null +++ b/max_equal_freq.c @@ -0,0 +1,61 @@ +// 1224. Maximum Equal Frequency +#include "leetcode.h" + +/* + * given an array 'nums' of positive integers, return the longest possible + * length of an array prefix of 'nums' such that it is possible to remove + * exactly one element from this prefix so that ever number has appear in it + * will have the same number occurrences. if after removing one element there + * are no remaining elements, it's still considered that every appear number has + * the same number of occurrences. + */ + +typedef struct { + int key; + int cnt; +} data; + +int maxEqualFreq(int *nums, int numsSize) { + int n = numsSize, m = n, type = 0, ans = 0, max_freq = 1; + data **num_freq = calloc(m, sizeof(data *)); + int *cnt = calloc(n + 1, sizeof(int)); + for (int i = 0; i < n; i++) { + int val = nums[i], curr = val; + while (1) { + if (!num_freq[curr % m]) { + num_freq[curr % m] = malloc(sizeof(data)); + num_freq[curr % m]->key = val; + num_freq[curr % m]->cnt = 1; + cnt[1]++; + type++; + break; + } else if (num_freq[curr % m]->key == val) { + num_freq[curr % m]->cnt++; + cnt[num_freq[curr % m]->cnt]++; + cnt[num_freq[curr % m]->cnt - 1]--; + if (num_freq[curr % m]->cnt > max_freq) + max_freq = num_freq[curr % m]->cnt; + break; + } else + curr++; + } + if (type == i + 1) + ans = fmax(ans, i + 1); + else if (cnt[1] == 1 && max_freq * cnt[max_freq] == i) + ans = fmax(ans, i + 1); + else if ((max_freq - 1) * (cnt[max_freq - 1] + 1) == i) + ans = fmax(ans, i + 1); + } + for (int i = 0; i < m; i++) + if (num_freq[i]) + free(num_freq[i]); + free(num_freq), free(cnt); + return ans; +} + +int main() { + int n1[] = {2, 2, 1, 1, 5, 3, 3, 5}, + n2[] = {1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5}; + printf("%d\n", maxEqualFreq(n1, ARRAY_SIZE(n1))); // expect: 7 + printf("%d\n", maxEqualFreq(n2, ARRAY_SIZE(n2))); // expect: 13 +} diff --git a/max_equal_freq.py b/max_equal_freq.py new file mode 100644 index 0000000..6f81881 --- /dev/null +++ b/max_equal_freq.py @@ -0,0 +1,38 @@ +# 1224. Maximum Equal Frequency +from collections import defaultdict + +""" +given an array 'nums' of positive integers, return the longest possible +length of an array prefix of 'nums' such that it is possible to remove +exactly one element from this prefix so that ever number has appear in it +will have the same number occurrences. if after removing one element there +are no remaining elements, it's still considered that every appear number has +the same number of occurrences. +""" + + +class Solution(object): + def maxEqualFreq(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + cnt, freq, max_freq, ans = defaultdict(int), defaultdict(int), 0, 0 + for i, n in enumerate(nums): + cnt[n] += 1 + freq[cnt[n] - 1] -= 1 + freq[cnt[n]] += 1 + max_freq = max(max_freq, cnt[n]) + if ( + max_freq * freq[max_freq] == i + or (max_freq - 1) * (freq[max_freq - 1] + 1) == i + or max_freq == 1 + ): + ans = i + 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxEqualFreq(nums=[2, 2, 1, 1, 5, 3, 3, 5])) + print(obj.maxEqualFreq(nums=[1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5])) diff --git a/max_erasure_value.cpp b/max_erasure_value.cpp new file mode 100644 index 0000000..dd72746 --- /dev/null +++ b/max_erasure_value.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + int maximumUniqueSubarray(vector<int> &nums) { + int ans = 0; + unordered_set<int> us; + for (int i = 0, j = 0, win = 0; j < nums.size(); j++) { + while (us.find(nums[j]) != us.end()) { + us.erase(nums[i]); + win -= nums[i]; + i++; + } + us.insert(nums[j]); + win += nums[j]; + ans = max(ans, win); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums = {5, 2, 1, 2, 5, 2, 1, 2, 5}; + cout << obj.maximumUniqueSubarray(nums); +} diff --git a/max_ice_cream_bars.c b/max_ice_cream_bars.c new file mode 100644 index 0000000..cb64658 --- /dev/null +++ b/max_ice_cream_bars.c @@ -0,0 +1,37 @@ +// 1833. Maximum Ice Cream Bars +#include <stdio.h> +#include <stdlib.h> + +/* + * it is a sweltering summer day, and a boy wants to buy some ice cream bars. at + * the store, there are 'n' ice cream bars. you are given an array 'costs' of + * length 'n' where 'costs[i]' is the price of the i'th ice cream bar in coins. + * the boy initially has 'coins' coins to spend and he wants to buy as many ice + * cream bars as possible. note, the boy can buy the ice cream bars in any + * order. return the maximum number of ice cream bars the boy can buy with + * 'coins' coins. you must solve the problem by counting sort. + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int maxIceCream(int *costs, int costs_size, int coins) { + int n = costs_size; + qsort(costs, n, sizeof(int), cmp); + int ans = 0, sum = 0; + for (int i = 0; i < n; i++) { + sum += costs[i]; + if (sum <= coins) + ans++; + else + break; + } + return ans; +} + +int main() { + int c1[] = {1, 3, 2, 4, 1}, c2[] = {10, 6, 8, 7, 7, 8}, + c3[] = {1, 6, 3, 1, 2, 5}; + printf("%d\n", maxIceCream(c1, 5, 7)); // expect: 4 + printf("%d\n", maxIceCream(c2, 6, 5)); // expect: 0 + printf("%d\n", maxIceCream(c3, 6, 20)); // expect: 6 +} diff --git a/max_ice_cream_bars.cpp b/max_ice_cream_bars.cpp new file mode 100644 index 0000000..e391f87 --- /dev/null +++ b/max_ice_cream_bars.cpp @@ -0,0 +1,39 @@ +#include "leetcode.h" + +class Solution { +public: + int maxIceCream(vector<int> &costs, int coins) { + int k = costs.size(); + vector<int> dp(k + 1, -1); + sort(costs.begin(), costs.end()); + return dfs(dp, costs, coins, 0, k); + } + +private: + int dfs(vector<int> &dp, vector<int> &nums, int coins, int i, int k) { + if (coins <= 0) + return 0; + if (i == k - 1) { + if (nums[i] <= coins) + return 1; + else + return 0; + } + if (dp[i] != -1) + return dp[i]; + int y = 0, n = 0; + if (nums[i] <= coins) + y = 1 + dfs(dp, nums, coins - nums[i], i + 1, k); + n = dfs(dp, nums, coins, i + 1, k); + return dp[i] = max(y, n); + } +}; + +int main() { + Solution obj; + vector<int> costs1 = {1, 3, 2, 4, 1}, costs2 = {10, 6, 8, 7, 7, 8}, + costs3 = {1, 6, 3, 1, 2, 5}; + cout << obj.maxIceCream(costs1, 7) << endl; // expect: 4 + cout << obj.maxIceCream(costs2, 5) << endl; // expect: 0 + cout << obj.maxIceCream(costs3, 20) << endl; // expect: 6 +} diff --git a/max_ice_cream_bars.rs b/max_ice_cream_bars.rs new file mode 100644 index 0000000..6691a3b --- /dev/null +++ b/max_ice_cream_bars.rs @@ -0,0 +1,27 @@ +struct Solution; + +impl Solution { + pub fn max_ice_cream(costs: Vec<i32>, coins: i32) -> i32 { + let (mut bars, mut coins, mut price, mut count) = + ([0_u32; 100_001], coins, 1, 0); + costs.into_iter().for_each(|c| bars[c as usize] += 1); + while coins >= price && price <= 100_000 { + while bars[price as usize] > 0 && coins >= price { + bars[price as usize] -= 1; + coins -= price; + count += 1; + } + price += 1; + } + count + } +} + +fn main() { + let costs1 = vec![1,3,2,4,1]; + let costs2 = vec![10,6,8,7,7,8]; + let costs3 = vec![1,6,3,1,2,5]; + println!("{}", Solution::max_ice_cream(costs1, 7)); //expect: 4 + println!("{}", Solution::max_ice_cream(costs2, 5)); //expect: 0 + println!("{}", Solution::max_ice_cream(costs3, 20)); //expect: 6 +} diff --git a/max_len_concat_str.c b/max_len_concat_str.c new file mode 100644 index 0000000..ff06957 --- /dev/null +++ b/max_len_concat_str.c @@ -0,0 +1,69 @@ +// 1239. Maximum Length of a Concatenated String with Unique Characters +#include "leetcode.h" + +/* + * given an array of strings 'arr'. a string 's' is formed by the concatenation + * of subsequence of 'arr', that has unique characters. return the maximum + * possible length of 's'. a subsequence is an array that can be derived from + * another array by deleting some or no elements without changing the order of + * the remaining elements. + */ + +typedef unsigned char uint8_t; + +void dfs(uint8_t **data, uint8_t *len, uint8_t *curr, int pos, int n, int *res, + int size) { + if (pos == n) { + *res = fmax(*res, size); + return; + } + dfs(data, len, curr, pos + 1, n, res, size); + bool pass = true; + for (int i = 0; i < 26; i++) { + curr[i] += data[pos][i]; + if (curr[i] > 1) + pass = false; + } + if (pass) + dfs(data, len, curr, pos + 1, n, res, size + len[pos]); + for (int i = 0; i < 26; i++) + curr[i] -= data[pos][i]; +} + +int maxLength(char **arr, int arr_size) { + uint8_t **data = malloc(arr_size * sizeof(uint8_t *)); + uint8_t *len = malloc(arr_size * sizeof(uint8_t)); + uint8_t cnt = 0, ans = 0; + for (uint8_t i = 0; i < arr_size; i++) + data[i] = calloc(26, sizeof(uint8_t)); + data[cnt] = calloc(26, sizeof(uint8_t)); + for (int i = 0; i < arr_size; i++) { + uint8_t l = strlen(arr[i]); + for (int j = 0; j < l; j++) { + data[cnt][arr[i][j] - 'a']++; + if (data[cnt][arr[i][j] - 'a'] > 1) { + memset(data[cnt], 0, 26 * sizeof(uint8_t)); + break; + } + if (j == l - 1) { + ans = fmax(ans, l); + len[cnt] = l; + cnt++; + } + } + } + uint8_t *curr = calloc(26, sizeof(uint8_t)); + if (cnt > 1) + dfs(data, len, curr, 0, cnt, &ans, 0); + free(curr), free(len); + return ans; +} + +int main() { + char a1[3][2] = {"un", "iq", "ue"}; + char a2[4][3] = {"cha", "r", "act", "ers"}; + char a3[1][26] = {"abcdefghijklmnopqrstuvwxyz"}; + printf("%d\n", maxLength(a1, 3)); + printf("%d\n", maxLength(a2, 4)); + printf("%d\n", maxLength(a3, 1)); +} diff --git a/max_len_concat_str.cpp b/max_len_concat_str.cpp new file mode 100644 index 0000000..e360961 --- /dev/null +++ b/max_len_concat_str.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + int maxLength(vector<string> &arr) { + int ans = 0; + vector<bitset<26>> unique; + for (auto s : arr) { + bitset<26> b; + for (char ch : s) + b.set(ch - 'a'); + if (b.count() == s.size()) + unique.push_back(b); + } + vector<bitset<26>> concat = {bitset<26>()}; + for (auto &u : unique) + for (int i = concat.size() - 1; i >= 0; i--) + if ((concat[i] & u).none()) { + concat.push_back(concat[i] | u); + ans = max(ans, (int)(concat[i].count() + u.count())); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<string> arr = {"un", "iq", "ue"}; + cout << obj.maxLength(arr); +} diff --git a/max_len_concat_str.py b/max_len_concat_str.py new file mode 100644 index 0000000..5d8576e --- /dev/null +++ b/max_len_concat_str.py @@ -0,0 +1,34 @@ +# 1239. Maximum Length of a Concatenated String with Unique Characters + +""" +given an array of strings 'arr'. a string 's' is formed by the concatenation +of subsequence of 'arr', that has unique characters. return the maximum +possible length of 's'. a subsequence is an array that can be derived from +another array by deleting some or no elements without changing the order of +the remaining elements. +""" + + +class Solution(object): + def maxLength(self, arr): + """ + :type arr: List[str] + :rtype: int + """ + dp = [set()] + for i in arr: + if len(set(i)) < len(i): + continue + i = set(i) + for c in dp[:]: + if i & c: + continue + dp.append(i | c) + return max(len(i) for i in dp) + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxLength(arr=["un", "iq", "ue"])) + print(obj.maxLength(arr=["cha", "r", "act", "ers"])) + print(obj.maxLength(arr=["abcdefghijklmnopqrstuvwxyz"])) diff --git a/max_len_concat_str.rs b/max_len_concat_str.rs new file mode 100644 index 0000000..8ce0c2b --- /dev/null +++ b/max_len_concat_str.rs @@ -0,0 +1,29 @@ +struct Solution; + +impl Solution { + pub fn max_length(arr: Vec<String>) -> i32 { + let mut ans: u32 = 0; + let mut unique: Vec<u32> = Vec::new(); + for s in arr { + let bin: u32 = s.bytes().map(|c| 1 << (c - b'a')).sum(); + if bin.count_ones() == s.len() as u32 { + unique.push(bin); + } + } + let mut concat: Vec<u32> = vec![0]; + for u in unique { + for i in 0..concat.len() { + if (concat[i] & u).count_ones() == 0 { + concat.push(concat[i] | u); + ans = ans.max(concat[i].count_ones() + u.count_ones()); + } + } + } + ans as i32 + } +} + +fn main() { + let arr = vec!["un".to_string(),"iq".to_string(),"ue".to_string()]; + print!("{}", Solution::max_length(arr)); +} diff --git a/max_len_subarr_pos_product.c b/max_len_subarr_pos_product.c new file mode 100644 index 0000000..9349729 --- /dev/null +++ b/max_len_subarr_pos_product.c @@ -0,0 +1,36 @@ +// 1567. Maximum Length of Subarray With Positive Product +#include "leetcode.h" + +/* + * given an array of integers 'nums', find the maximum length of subarray where + * the product of all its elements is positive. a subarray of anarray is a + * consecutive sequence of zero or more values taken out of that array. return + * the maximum length of a subarray with positive product. + */ + +int getMaxLen(int *nums, int numsSize) { + int pos = 0, neg = 0, ans = 0; + for (int i = 0; i < numsSize; i++) { + if (!nums[i]) + pos = neg = 0; + else if (nums[i]) { + pos++; + if (neg) + neg++; + } else { + int tmp = pos; + pos = neg ? neg + 1 : 0; + neg = tmp + 1; + } + ans = pos > ans ? pos : ans; + } + return ans; +} + +int main() { + int n1[] = {1, -2, -3, 4}, n2[] = {0, 1, -2, -3, -4}, + n3[] = {-1, -2, -3, 0, 1}; + printf("%d\n", getMaxLen(n1, ARRAY_SIZE(n1))); // expect: 4 + printf("%d\n", getMaxLen(n2, ARRAY_SIZE(n2))); // expect: 3 + printf("%d\n", getMaxLen(n3, ARRAY_SIZE(n3))); // expect: 2 +} diff --git a/max_len_subarr_pos_product.py b/max_len_subarr_pos_product.py new file mode 100644 index 0000000..291ad6a --- /dev/null +++ b/max_len_subarr_pos_product.py @@ -0,0 +1,39 @@ +# 1567. Maximum Length of Subarray With Positive Product + +""" +given an array of integers 'nums', find the maximum length of subarray where +the product of all its elements is positive. a subarray of anarray is a +consecutive sequence of zero or more values taken out of that array. return +the maximum length of a subarray with positive product. +""" + + +class Solution(object): + def getMaxLen(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + n, pos, neg = len(nums), 0, 0 + if nums[0] > 0: + pos = 1 + if nums[0] < 0: + neg = 1 + ans = pos + for i in range(1, n): + if nums[i] > 0: + pos += 1 + neg += 1 if neg > 0 else 0 + elif nums[i] < 0: + pos, neg = 1 + neg if neg > 0 else 0, 1 + pos + else: + pos, neg = 0, 0 + ans = max(ans, pos) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.getMaxLen(nums=[1, -2, -3, 4])) + print(obj.getMaxLen(nums=[0, 1, -2, -3, -4])) + print(obj.getMaxLen(nums=[-1, -2, -3, 0, 1])) diff --git a/max_length_pair_chain.c b/max_length_pair_chain.c new file mode 100644 index 0000000..606bf97 --- /dev/null +++ b/max_length_pair_chain.c @@ -0,0 +1,36 @@ +// 646. Maximum Length of Pair Chain +#include <stdio.h> +#include <stdlib.h> + +/* + * given a n array of 'n' pairs, where 'pairs[i]= [lefti, righti]' and 'left[i] + * < right[i]'. a pair 'p2 = [c, d]' follows a pair 'p1 = [a, b]' if 'b < c'. a + * chain of pairs can be formed in this fashion. return the length of the + * longest chain which can be formed. you do not need to use up all the given + * intervals. you can select pairs in any order. + */ + +int cmp(int **a, int **b) { + int *tmpa = *a; + int *tmpb = *b; + if (tmpa[1] == tmpb[1]) + return tmpa[0] - tmpb[0]; + return tmpa[1] - tmpb[1]; +} + +int findLongestChain(int **pairs, int pairs_size, int *pairs_col_size) { + qsort(pairs, pairs_size, sizeof(int *), cmp); + int ans = 1, k = 0; + for (int i = 1; i < pairs_size; i++) + if (pairs[i][0] > pairs[k][1]) { + ans++; + k = i; + } + return ans; +} + +int main() { + int p1[3][2] = {{1, 2}, {2, 3}, {3, 4}}, p2[3][2] = {{1, 2}, {7, 8}, {4, 5}}; + printf("%d\n", findLongestChain(p1, 3, NULL)); // expect: 2 + printf("%d\n", findLongestChain(p2, 3, NULL)); // expect: 3 +} diff --git a/max_length_pair_chain.cpp b/max_length_pair_chain.cpp new file mode 100644 index 0000000..7564ffb --- /dev/null +++ b/max_length_pair_chain.cpp @@ -0,0 +1,33 @@ +// 646. Maximum Length of Pair Chain +#include "leetcode.h" + +/* + * given a n array of 'n' pairs, where 'pairs[i]= [lefti, righti]' and 'left[i] + * < right[i]'. a pair 'p2 = [c, d]' follows a pair 'p1 = [a, b]' if 'b < c'. a + * chain of pairs can be formed in this fashion. return the length of the + * longest chain which can be formed. you do not need to use up all the given + * intervals. you can select pairs in any order. + */ + +class Solution { + static bool cmp(vector<int> &a, vector<int> &b) { return a[1] < b[1]; } + +public: + int findLongestChain(vvd(int) & pairs) { + sort(pairs.begin(), pairs.end(), cmp); + int cnt = 0; + for (int i = 0, j = 0; j < pairs.size(); j++) + if (!j || pairs[i][1] < pairs[j][0]) { + cnt++; + i = j; + } + return cnt; + } +}; + +int main() { + Solution obj; + vvd(int) p1 = {{1, 2}, {2, 3}, {3, 4}}, p2 = {{1, 2}, {7, 8}, {4, 5}}; + printf("%d\n", obj.findLongestChain(p1)); // expect: 2 + printf("%d\n", obj.findLongestChain(p2)); // expect: 3 +} diff --git a/max_length_repeated_subarr.cpp b/max_length_repeated_subarr.cpp new file mode 100644 index 0000000..59ab0bd --- /dev/null +++ b/max_length_repeated_subarr.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + int findLength(vector<int> &nums1, vector<int> &nums2) { + int m = nums1.size(), n = nums2.size(); + vvd(int) dp(m + 1, vector<int>(n + 1)); + int ans = 0; + for (int i = 1; i <= m; ++i) { + for (int j = 1; j <= n; ++j) { + if (nums1[i - 1] == nums2[j - 1]) + dp[i][j] = dp[i - 1][j - 1] + 1; + else + dp[i][j] = 0; + ans = max(ans, dp[i][j]); + } + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums1 = {1, 2, 3, 2, 1}, nums2 = {3, 2, 1, 4, 7}; + cout << obj.findLength(nums1, nums2); +} diff --git a/max_nesting_depth_parentheses.c b/max_nesting_depth_parentheses.c new file mode 100644 index 0000000..49bd8f5 --- /dev/null +++ b/max_nesting_depth_parentheses.c @@ -0,0 +1,21 @@ +// 1614. Maximum Nesting Depth of the Parentheses +#include "leetcode.h" + +int maxDepth(char *s) { + int ans = 0, k = 0, n = strlen(s); + for (int i = 0; i < n; i++) { + if (s[i] == '(') + k++; + if (s[i] == ')') + k--; + if (k > ans) + ans = k; + } + return ans; +} + +int main() { + char *s1 = "(1+(2*3)+((8)/4))+1", *s2 = "(1)+((2))+(((3)))"; + printf("%d\n", maxDepth(s1)); // expect: 3 + printf("%d\n", maxDepth(s2)); // expect: 3 +} diff --git a/max_nesting_depth_parentheses.py b/max_nesting_depth_parentheses.py new file mode 100644 index 0000000..c24f36b --- /dev/null +++ b/max_nesting_depth_parentheses.py @@ -0,0 +1,26 @@ +# 1614. Maximum Nesting Depth of the Parentheses + + +class Solution(object): + def maxDepth(self, s): + """ + :type s: str + :rtype: int + """ + stack = [] + ans = 0 + for c in s: + if c == "(": + stack.append(c) + elif c == ")": + ans = max(ans, len(stack)) + stack.pop() + else: + continue + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxDepth("(1+(2*3)+((8)/4))+1")) + print(obj.maxDepth("(1)+((2))+(((3)))")) diff --git a/max_network_rank.c b/max_network_rank.c new file mode 100644 index 0000000..44c1ed3 --- /dev/null +++ b/max_network_rank.c @@ -0,0 +1,42 @@ +// 1615. Maximal Network Rank +#include <limits.h> +#include <math.h> +#include <stdbool.h> +#include <stdlib.h> + +/* + * there is an infrastructure of 'n' cities with some number of 'roads' + * connecting these cities. each 'roads[i] = [ai, bi]'. indicates that there is + * a bidirectional road between cities 'ai' and 'bi'. the network rank of two + * different cities is defined as the total number of directly conncected roads + * to either city. if a road is directly connected to both cities, it is only + * counted once. the maximal network rank of the infrastructure is the maximum + * network rank of all pairs of different cities. given the integer 'n' and the + * array 'roads', return the maximal network rank of the entire infrastructure. + */ + +int maximalNetworkRank(int n, int **roads, int roads_size, + int *roads_col_size) { + bool **connect = malloc(n * sizeof(bool *)); + for (int i = 0; i < n; i++) + connect[i] = calloc(n, sizeof(bool)); + int *edges = calloc(n, sizeof(int)); + for (int i = 0; i < roads_size; i++) { + int a = roads[i][0]; + int b = roads[i][1]; + connect[a][b] = true; + connect[b][a] = true; + edges[a]++; + edges[b]++; + } + int ans = INT_MIN; + for (int i = 0; i < n; i++) + for (int j = i + 1; j < n; j++) { + int rank = edges[i] + edges[j] - connect[i][j]; + ans = fmax(ans, rank); + } + for (int i = 0; i < n; i++) + free(connect); + free(connect), free(edges); + return ans; +} diff --git a/max_network_rank.cpp b/max_network_rank.cpp new file mode 100644 index 0000000..14a5f8f --- /dev/null +++ b/max_network_rank.cpp @@ -0,0 +1,44 @@ +// 1615. Maximal Network Rank +#include "leetcode.h" + +/* + * there is an infrastructure of 'n' cities with some number of 'roads' + * connecting these cities. each 'roads[i] = [ai, bi]'. indicates that there is + * a bidirectional road between cities 'ai' and 'bi'. the network rank of two + * different cities is defined as the total number of directly conncected roads + * to either city. if a road is directly connected to both cities, it is only + * counted once. the maximal network rank of the infrastructure is the maximum + * network rank of all pairs of different cities. given the integer 'n' and the + * array 'roads', return the maximal network rank of the entire infrastructure. + */ + +class Solution { +public: + int maximalNetworkRank(int n, vvd(int) & roads) { + vector<unordered_set<int>> graph(n); + for (auto r : roads) { + graph[r[0]].insert(r[1]); + graph[r[1]].insert(r[0]); + } + int maximal = 0; + for (int i = 0; i < n; i++) { + for (int j = i + 1; j < n; j++) { + int network_rank = graph[i].size(); + if (graph[j].count(i)) + --network_rank; + maximal = max(maximal, network_rank); + } + } + return maximal; + } +}; + +int main() { + Solution obj; + vvd(int) r1 = {{0, 1}, {0, 3}, {1, 2}, {1, 3}}, + r2 = {{0, 1}, {0, 3}, {1, 2}, {1, 3}, {2, 3}, {2, 4}}, + r3 = {{0, 1}, {1, 2}, {2, 3}, {2, 4}, {5, 6}, {5, 7}}; + printf("%d\n", obj.maximalNetworkRank(4, r1)); // expect: 4 + printf("%d\n", obj.maximalNetworkRank(5, r2)); // expect: 5 + printf("%d\n", obj.maximalNetworkRank(8, r3)); // expect: 5 +} diff --git a/max_num_events_attended2.cpp b/max_num_events_attended2.cpp new file mode 100644 index 0000000..4c54b9d --- /dev/null +++ b/max_num_events_attended2.cpp @@ -0,0 +1,46 @@ +// 1751. Maximum Number of Events That Can Be Attended II +#include "leetcode.h" + +/* + * given an array of 'events' where 'events[i] = [startdayi, enddayi, valuei]'. + * the i'th event starts at 'startdayi' and ends at 'enddayi', and if you attent + * this event, you will receive a value of 'valuei'. you are also given an + * integer 'k' which represents the maximum number of events you can attend. you + * can only attend one event at a time. if you choose to attend an event, you + * must attend the entire event. note that the end day is inclusive: that is, + * you cannot attend two events where one of them starts and the other ends on + * the same day. return the maximum sum of values that you can receive by + * attending events + */ + +class Solution { + vvd(int) dp; + int dfs(vvd(int) & events, int k, int i) { + if (!k || i >= events.size()) + return 0; + if (dp[i][k] != -1) + return dp[i][k]; + auto j = upper_bound(begin(events) + i, end(events), events[i][1], + [](int t, const vector<int> &v) { return v[0] > t; }) - + begin(events); + return dp[i][k] == + max(events[i][2] + dfs(events, k - 1, j), dfs(events, k, i + 1)); + } + +public: + int maxValue(vvd(int) & events, int k) { + dp = vvd(int)(events.size(), vector<int>(k + 1, -1)); + sort(begin(events), end(events)); + return dfs(events, k, 0); + } +}; + +int main() { + Solution obj; + vvd(int) e1 = {{1, 2, 4}, {3, 4, 3}, {2, 3, 1}}, + e2 = {{1, 2, 4}, {3, 4, 3}, {2, 3, 10}}, + e3 = {{1, 1, 1}, {2, 2, 2}, {3, 3, 3}, {4, 4, 4}}; + printf("%d\n", obj.maxValue(e1, 2)); // expect: 7 + printf("%d\n", obj.maxValue(e2, 2)); // expect: 10 + printf("%d\n", obj.maxValue(e3, 3)); // expect: 9 +} diff --git a/max_num_group_entre_comp.c b/max_num_group_entre_comp.c new file mode 100644 index 0000000..48ec41d --- /dev/null +++ b/max_num_group_entre_comp.c @@ -0,0 +1,35 @@ +// 2358. Maximum Number of Groups Entering a Competition +#include "leetcode.h" +/* + * given a positive integer array 'grades' which represents the grades of + * students in a university. you would like to entre all these students into a + * competition in orderd non empty groups such that the ordering meets the + * following requirements. the sum of the grades of students in the i'th group + * is less than the sum of the grades of students in the '(i +1)'th group for + * all groups except last. the total number of students in the i'th group is + * less than the total number of students in the i'th group is less than the + * gtotal numboer of students in the '(i + 1)'th group, for all groups. return + * the maximum numberof groups that can be formed. + */ + +int maximumGroups(int *grades, int gradesSize) { + int left = 1, right = gradesSize / 2 + 1, mid, sum; + while (left < right) { + mid = right - (right - left) / 2; + sum = (1 + mid) * mid / 2; + if (sum == gradesSize) + return mid; + if (sum > gradesSize) + right = mid - 1; + else + left = mid; + ; + } + return left; +} + +int main() { + int g1[] = {10, 6, 12, 7, 3, 5}, g2[] = {8, 8}; + printf("%d\n", maximumGroups(g1, ARRAY_SIZE(g1))); // expect: 3 + printf("%d\n", maximumGroups(g2, ARRAY_SIZE(g2))); // expect: 1 +} diff --git a/max_num_group_entre_comp.py b/max_num_group_entre_comp.py new file mode 100644 index 0000000..b34e855 --- /dev/null +++ b/max_num_group_entre_comp.py @@ -0,0 +1,31 @@ +# 2358. Maximum Number of Groups Entering a Competition +"""iven a positive integer array 'grades' which represents the grades of +students in a university. you would like to entre all these students into a +competition in orderd non empty groups such that the ordering meets the +following requirements. the sum of the grades of students in the i'th group +is less than the sum of the grades of students in the '(i +1)'th group for +all groups except last. the total number of students in the i'th group is +less than the total number of students in the i'th group is less than the +total numboer of students in the '(i + 1)'th group, for all groups. return +the maximum numberof groups that can be formed. + """ + + +class Solution(object): + def maximumGroups(self, grades): + """ + :type grades: List[int] + :rtype: int + """ + n, k = len(grades), 0 + while n >= k + 1: + k += 1 + n -= k + return k + # or return (int)(sqrt(len(grades) * 2 + 0.25) - 0.5) + + +if __name__ == "__main__": + obj = Solution() + print(obj.maximumGroups(grades=[10, 6, 12, 7, 3, 5])) + print(obj.maximumGroups(grades=[8, 8])) diff --git a/max_num_ksum_pair.cpp b/max_num_ksum_pair.cpp new file mode 100644 index 0000000..13c6980 --- /dev/null +++ b/max_num_ksum_pair.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + int maxOperations(vector<int> &nums, int k) { + unordered_map<int, int> freq; + int ans = 0; + for (int i = 0; i < nums.size(); i++) + if (freq[k - nums[i]] > 0) { + ans++; + freq[k - nums[i]]--; + } else + freq[nums[i]]++; + return ans; + } +}; + +int main() { + vector<int> nums = {1, 2, 3, 4}; + Solution obj; + cout << obj.maxOperations(nums, 5); +} diff --git a/max_num_moves_grid.c b/max_num_moves_grid.c new file mode 100644 index 0000000..3b8ddfc --- /dev/null +++ b/max_num_moves_grid.c @@ -0,0 +1,49 @@ +// 2684. Maximum Number of Moves in a Grid +#include "leetcode.h" + +/* + * given a 0-indexed array 'm * n' grid consisting of positive integers. you can + * start at any cell in the first column of the matrix and traverse the grid in + * the following way: from cell '(row, col)', you can move to any of the cells: + * '(row - 1, col + 1), (row, col + 1), and (row + 1, col + 1)'. such that thhe + * value of the cell you are moving to should be strictly bigger than the value + * of the current cell. return the maximum number of moves that you can perform. + */ + +// int dfs(int **dp, int **grid, int row_size, int *col_size, int row, int col, +// int prev, int ith) { +int dfs(int **dp, int r, int c, int grid[r][c], int row_size, int *col_size, + int row, int col, int prev, int ith) { + if (row < 0 || row >= row_size || col < 0 || col > *col_size - 1 || + grid[row][col] <= prev) + return ith; + if (dp[row][col]) + return ith + dp[row][col] + 1; + int tmp = dfs(dp, r, c, grid, row_size, col_size, row - 1, col + 1, + grid[row][col], ith + 1); + tmp = fmax(tmp, dfs(dp, r, c, grid, row_size, col_size, row, col + 1, + grid[row][col], ith + 1)); + tmp = fmax(tmp, dfs(dp, r, c, grid, row_size, col_size, row + 1, col, + grid[row][col], ith + 1)); + dp[row][col] = tmp - ith - 1; + return tmp; +} + +// int maxMoves(int **grid, int grid_size, int *grid_col_size) { +int maxMoves(int r, int c, int grid[r][c], int grid_size, int *grid_col_size) { + int ans = 0; + int **dp = malloc(sizeof(int *) * grid_size); + for (int i = 0; i < grid_size; i++) + dp[i] = calloc(*grid_col_size, sizeof(int)); + for (int i = 0; i < grid_size; i++) + ans = fmax(ans, dfs(dp, r, c, grid, grid_size, grid_col_size, i, 0, 0, -1)); + return ans; +} + +int main() { + int g1[4][4] = {{2, 4, 3, 5}, {5, 4, 9, 3}, {3, 4, 2, 11}, {10, 9, 13, 15}}; + int g2[3][3] = {{3, 2, 4}, {2, 1, 9}, {1, 1, 7}}; + int gcs1[] = {}, gcs2[] = {}; + printf("%d\n", maxMoves(4, 4, g1, 4, gcs1)); // expect: 3 + printf("%d\n", maxMoves(3, 3, g2, 3, gcs2)); // expect: 0 +} diff --git a/max_num_robot_budget.c b/max_num_robot_budget.c new file mode 100644 index 0000000..7b1dbb2 --- /dev/null +++ b/max_num_robot_budget.c @@ -0,0 +1,51 @@ +// 2398. Maximum Number of Robots Within Budget +#include "leetcode.h" + +/* + * you have 'n' robots. you are given two 0 indexed integer arrays 'chargeTimes' + * and 'runningCosts', both of length 'n'. the i'th robot costs 'chargeTimes[i]' + * units to charge and costs 'runningCosts[i]' units to run. you are also given + * an integer 'budget'. the total cost of running 'k' chosen robots is equal to + * 'max(chargeTimes) + k * sum(runningCosts)' where 'max(chargeTimes)' is the + * largest charge cost among the 'k' robots and 'sum(runningCosts)' is the sum + * of running costs among the 'k' robots. return the maximum number of + * consecutive robots you can run such that the total costs does not exceed + * 'budget'. + */ + +int maximumRobots(int *chargeTimes, int chargeTimesSize, int *runningCosts, + int runningCostsSize, long long budget) { + int lut[50001], idx_head = 0, idx_tail = 0, ans = 0, curr_len = 0; + long long curr_cost = 0; + for (int i = 0; i < chargeTimesSize; i++) { + long long curr_sum; + curr_cost += runningCosts[i]; + while (idx_head < idx_tail && lut[idx_head] < i - curr_len) + idx_head++; + while (idx_head < idx_tail && + chargeTimes[lut[idx_tail - 1]] < chargeTimes[i]) + idx_tail--; + lut[idx_tail++] = i; + curr_sum = chargeTimes[lut[idx_head]]; + curr_sum += (long long)(++curr_len * curr_cost); + while (curr_len > 0 && curr_sum > budget) { + curr_cost -= runningCosts[i - (--curr_len)]; + while (idx_head < idx_tail && lut[idx_head] < i - curr_len) + idx_head++; + curr_sum = chargeTimes[lut[idx_head]]; + curr_sum += (long long)(curr_len * curr_cost); + } + if (ans < curr_len) + ans = curr_len; + } + return ans; +} + +int main() { + int ct1[] = {3, 6, 1, 3, 4}, ct2[] = {11, 12, 19}, rc1[] = {2, 1, 3, 4, 5}, + rc2[] = {10, 8, 7}; + printf("%d\n", maximumRobots(ct1, ARRAY_SIZE(ct1), rc1, ARRAY_SIZE(rc1), + 25)); // expect: 3 + printf("%d\n", maximumRobots(ct2, ARRAY_SIZE(ct2), rc2, ARRAY_SIZE(rc2), + 19)); // expect: 0 +} diff --git a/max_num_robot_budget.py b/max_num_robot_budget.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/max_num_robot_budget.py diff --git a/max_num_tasks_assign.cpp b/max_num_tasks_assign.cpp new file mode 100644 index 0000000..370fdda --- /dev/null +++ b/max_num_tasks_assign.cpp @@ -0,0 +1,68 @@ +// 2071. Maximum Number of Tasks You Can Assign +#include "leetcode.h" + +/* + * you have 'n' tasks and 'm' workers. each task has a strength requirement + * stored in a 0-indexed integer array 'tasks', with the i'th task requiring + * 'tasks[i]' strength to complete. the strength of each worker is stored in a + * 0-indexed array 'workers' with the j'th worker having 'workers[j]' strength. + * each worker can only be assigned to a single task and must have a strength + * greather than or equal to the task's strength requirement. additionally, you + * have 'pills' magic pills that will increase a workers strength by 'strength'. + * you can decide which workers receive the pills, however, you may only give + * each worker at most one magical pill. given the 0-indexed integer arrays + * 'tasks' and 'workers' and the integers 'pills' and 'strength', return the + * maximum number of tasks that can be completed. + */ + +class Solution { +public: + int maxTaskAssign(vector<int> &tasks, vector<int> &workers, int pills, + int strength) { + int n = tasks.size(), m = workers.size(); + sort(tasks.begin(), tasks.end()); + sort(workers.begin(), workers.end()); + int lo = 0, hi = min(m, n), ans; + while (lo <= hi) { + int mid = lo + (hi - lo) / 2; + int cnt = 0; + bool flag = true; + multiset<int> st(workers.begin(), workers.end()); + for (int i = mid - 1; i >= 0; i--) { + auto it = prev(st.end()); + if (tasks[i] <= *it) + st.erase(it); + else { + auto it = st.lower_bound(tasks[i] - strength); + if (it != st.end()) { + cnt++; + st.erase(it); + } else { + flag = false; + break; + } + } + if (cnt > pills) { + flag = false; + break; + } + } + if (flag) { + ans = mid; + lo = mid + 1; + } else { + hi = mid - 1; + } + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> t1 = {3, 2, 1}, t2 = {5, 4}, t3 = {10, 15, 30}; + vector<int> w1 = {0, 3, 3}, w2 = {0, 0, 0}, w3 = {0, 10, 10, 10, 10}; + printf("%d\n", obj.maxTaskAssign(t1, w1, 1, 1)); // expect: 3 + printf("%d\n", obj.maxTaskAssign(t2, w2, 1, 5)); // expect: 1 + printf("%d\n", obj.maxTaskAssign(t3, w3, 3, 10)); // expect: 2 +} diff --git a/max_num_vowel_substr.c b/max_num_vowel_substr.c new file mode 100644 index 0000000..3ddd0bc --- /dev/null +++ b/max_num_vowel_substr.c @@ -0,0 +1,39 @@ +// 1456. Maximum Number of Vowels in a Substring of Given Length +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a string 's' and an integer 'k', return the maximum + * number of vowel letters in any substring of 's' with length + * 'k'. vowel letters in english are 'a e i o u' + */ + +int maxVowels(char *s, int k) { + int n = strlen(s), vowel = 0; + for (int i = 0; i < k; i++) + if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u') + vowel++; + if (vowel == k) + return k; + int max = vowel; + for (int i = k; i < n; i++) { + if (s[i] == 'a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'o' || s[i] == 'u') + vowel++; + if (s[i - k] == 'a' || s[i - k] == 'e' || s[i - k] == 'i' || + s[i - k] == 'o' || s[i - k] == 'u') + vowel--; + max = fmax(max, vowel); + if (max == k) + return max; + } + return max; +} + +int main() { + char s1[] = {"abciiidef"}, s2[] = {"aeiou"}, s3[] = {"leetcode"}; + printf("%d\n", maxVowels(s1, 3)); // expect: 3 + printf("%d\n", maxVowels(s2, 2)); // expect: 2 + printf("%d\n", maxVowels(s3, 3)); // expect: 2 +} diff --git a/max_num_vowel_substr.cpp b/max_num_vowel_substr.cpp new file mode 100644 index 0000000..fe24499 --- /dev/null +++ b/max_num_vowel_substr.cpp @@ -0,0 +1,30 @@ +// 1456. Maximum Number of Vowels in a Substring of Given Length +#include "leetcode.h" + +/* + * given a string 's' and an integer 'k', return the maximum + * number of vowel letters in any substring of 's' with length + * 'k'. vowel letters in english are 'a e i o u' + */ + +class Solution { +public: + int maxVowels(string s, int k) { + int count = 0, counting = 0; + unordered_set<char> bag = {'a', 'e', 'i', 'o', 'u'}; + for (int i = 0, local = 0; i < s.size(); i++) { + local += bag.count(s[i]); + if (i - k >= 0) + local -= bag.count(s[i - k]); + count = max(count, local); + } + return count; + } +}; + +int main() { + Solution obj; + cout << obj.maxVowels("abciiidef", 3); // expect: 3 + cout << obj.maxVowels("aeiou", 2); // expect: 2 + cout << obj.maxVowels("leetcode", 3); // expect: 2 +} diff --git a/max_odd_binary_num.c b/max_odd_binary_num.c new file mode 100644 index 0000000..86f6af1 --- /dev/null +++ b/max_odd_binary_num.c @@ -0,0 +1,32 @@ +// 2864. Maximum Odd Binary Number +#include "leetcode.h" + +/* + * given a binary string 's' that contains at least one '1'. you have to + * rearrange the bits in such a way that the resulting binary number is the + * maximum odd binary number that can be created from this combination. return a + * string representing the maximum odd binary number that can be created from + * the given combination. + */ + +char *maximumOddBinaryNumber(char *s) { + int n = strlen(s), one = 0; + for (int i = 0; i < n; ++i) + if (s[i] == '1') + one++; + for (int i = 0; i < n - 1; ++i) { + if (one > 1) { + s[i] = '1'; + --one; + } else + s[i] = '0'; + } + s[n - 1] = '1'; + return s; +} + +int main() { + char *s1 = "010", *s2 = "0101"; + printf("%s\n", maximumOddBinaryNumber(s1)); // expect: 001 + printf("%s\n", maximumOddBinaryNumber(s2)); // expect: 1001 +} diff --git a/max_odd_binary_num.py b/max_odd_binary_num.py new file mode 100644 index 0000000..b8235ef --- /dev/null +++ b/max_odd_binary_num.py @@ -0,0 +1,29 @@ +# 2864. Maximum Odd Binary Number + +""" +given a binary string 's' that contains at least one '1'. you have to +rearrange the bits in such a way that the resulting binary number is the +maximum odd binary number that can be created from this combination. return a +string representing the maximum odd binary number that can be created from +the given combination. +""" + + +class Solution(object): + def maximumOddBinaryNumber(self, s): + """ + :type s: str + :rtype: str + """ + c = sorted(s) + for i in range(len(c) - 1, -1, -1): + if c[i] == "1": + c[i], c[-1] = c[-1], c[i] + break + return "".join(c) + + +if __name__ == "__main__": + obj = Solution() + print(obj.maximumOddBinaryNumber("010")) + print(obj.maximumOddBinaryNumber("0101")) diff --git a/max_performance_team.cpp b/max_performance_team.cpp new file mode 100644 index 0000000..07a6e6e --- /dev/null +++ b/max_performance_team.cpp @@ -0,0 +1,33 @@ +#include "leetcode.h" + +class Solution { +public: + const int mod = (int)1e9 + 7; + int maxPerformance(int n, vector<int> &speed, vector<int> &efficiency, + int k) { + priority_queue<int, vector<int>, greater<int>> pqvg; + vector<pair<int, int>> vp; + for (int i = 0; i < n; i++) + vp.push_back({efficiency[i], speed[i]}); + sort(vp.rbegin(), vp.rend()); + long totSpeed = 0, ans = 0; + for (int i = 0; i < n; i++) { + int currEff = vp[i].first, currSpeed = vp[i].second; + if (pqvg.size() == k) { + totSpeed -= pqvg.top(); + pqvg.pop(); + } + pqvg.push(currSpeed); + totSpeed += currSpeed; + ans = max(ans, totSpeed * currEff); + } + return ans % mod; + } +}; + +int main() { + Solution obj; + int n = 6, k = 2; + vector<int> speed = {2, 10, 3, 1, 5, 8}, efficiency = {5, 4, 3, 9, 7, 2}; + cout << obj.maxPerformance(n, speed, efficiency, k); +} diff --git a/max_points_from_cards.c b/max_points_from_cards.c new file mode 100644 index 0000000..19b711e --- /dev/null +++ b/max_points_from_cards.c @@ -0,0 +1,38 @@ +// 1423. Maximum Points You Can Obtain from Cards +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * there are several cards arranged in a row, and each card has an associated + * number of points. the points are given in the integer array 'card_points'. in + * one step you can take one card from the begining or from the end of the row. + * you have to take exactly 'k' cards. your score is the sum of the points of + * the cards you have taken. given the integer array 'card_points' and the + * integer 'k', return the maximum score you can obtain + */ + +int maxScore(int *card_points, int card_points_size, int k) { + int n = card_points_size; + int *prefix = malloc((k + 1) * sizeof(int)); + int *suffix = malloc((k + 1) * sizeof(int)); + prefix[0] = 0; + suffix[0] = 0; + for (int i = 1; i <= k; i++) { + prefix[i] = prefix[i - 1] + card_points[i - 1]; + prefix[i] = suffix[i - 1] + card_points[n - 1]; + } + int max = INT_MIN; + for (int i = 0; i <= k; i++) + max = fmax(max, prefix[i] + suffix[k - i]); + return max; +} + +int main() { + int cp1[] = {1, 2, 3, 4, 5, 6, 1}, cp2[] = {2, 2, 2}, + cp3[] = {9, 7, 7, 9, 7, 7, 9}; + printf("%d\n", maxScore(cp1, 7, 3)); // expect: 12 + printf("%d\n", maxScore(cp2, 3, 2)); // expect: 4 + printf("%d\n", maxScore(cp3, 7, 7)); // expect: 55 +} diff --git a/max_points_from_cards.cpp b/max_points_from_cards.cpp new file mode 100644 index 0000000..23fc78e --- /dev/null +++ b/max_points_from_cards.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + int maxScore(vector<int> &cardPoints, int k) { + int ans = 0, n = cardPoints.size(); + for (int i = n - k; i < n; i++) + ans += cardPoints[i]; + for (int i = 0, s = ans; i < k; i++) { + s -= cardPoints[n - k + i]; + s += cardPoints[i]; + ans = max(ans, s); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> cardPoints = {1, 2, 3, 4, 5, 6, 1}; + int k = 3; + cout << obj.maxScore(cardPoints, k); +} diff --git a/max_points_line.cpp b/max_points_line.cpp new file mode 100644 index 0000000..5f09af7 --- /dev/null +++ b/max_points_line.cpp @@ -0,0 +1,50 @@ +#include "leetcode.h" + +class Point { // basic coordinate geometry +public: + double x, y; + Point(double x, double y) { + this->x = x; + this->y = y; + } +}; + +class Solution { +public: + int maxPoints(vvd(int) & points) { + int n = points.size(), ans = 0; + if (n <= 2) // 2 or less means points are always collinear + return n; + vector<Point> coordinates; + for (auto &i : points) { + Point k = Point((double)i[0], (double)i[1]); + coordinates.push_back(k); + } + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) { + int cnt = 0; + for (int k = 0; k < n; k++) + if (i != j && j != k && i != k) + if (isCollinear(coordinates[i], coordinates[j], coordinates[k])) + cnt++; + ans = max(cnt + 2, ans); + } + return ans; + } + +private: + bool isCollinear(Point a, Point b, + Point c) { // checks if 3 given points lie on same line + double i = (b.y - a.y) / (b.x - a.x); + double j = (c.y - b.y) / (c.x - b.x); + return i == j; + } +}; + +int main() { + Solution obj; + vvd(int) points1 = {{1, 1}, {2, 2}, {3, 3}}, + points2 = {{1, 1}, {3, 2}, {5, 3}, {4, 1}, {2, 3}, {1, 4}}; + cout << obj.maxPoints(points1) << endl; // expect: 3 + cout << obj.maxPoints(points2) << endl; // expect: 4 +} diff --git a/max_points_line.rs b/max_points_line.rs new file mode 100644 index 0000000..ee9c03d --- /dev/null +++ b/max_points_line.rs @@ -0,0 +1,91 @@ +use std::collections::HashMap; +struct Solution; + +/* +* 'Line' is represented as y = m * x + c +* m & c are rational numbers because of integer coordinates, +* but in general floating point numbers can be insufficient to +* guarantee uniqueness as they are still finite precision. +* so for most real irl cases we use numerator and denominator +* to represent m & c. decimal precision!!! +* if m -> +- infinity then use x-int to identify line +* if m == 0 then use y-int to identify line +*/ +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +enum Line { + Inf(i32), //x-int + MC((i32, i32), (i32, i32)), //numerator, denominator tuples for m & c + Zero(i32) //y-int +} + +impl Solution { + pub fn max_points(points: Vec<Vec<i32>>) -> i32 { + if points.len() == 1 { + return 1; + } + //y - y0 = (y1 - y0) / (x1 - x0) * (x - x0) + //y = dy / dx x + (dx * y0 - dy * x0) / dx + let mut fm: HashMap<Line, i32> = HashMap::new(); + points.iter().enumerate().flat_map(|(i, pt1)| { + points.iter().skip(i + 1).map(move |pt2| { + //swap points arounto make sure dy >= 0 since we are storing + //fraction numerator & denominator separately. + let (x0, y0, x1, y1) = if pt2[1] > pt1[1] || (pt2[1] == pt1[1] && pt2[0] > pt2[1]) { + (pt1[0], pt1[1], pt2[0], pt2[1]) + } else { + (pt2[0], pt2[1], pt1[0], pt1[1]) + }; + let mut dy = y1 - y0; + let mut dx = x1 - x0; + let g = Self::gcd(dy.abs(), dx.abs()); + if g != 0 { + dy /= g; + dx /= g; + } + if dx != 0 && dy != 0 { + /* + * slope is non-zero and finite so consistent line representation + * can be achieved using numerator & denominator representation + * because we have already preprocessed dy & dx for sign consistency + * and removed gcd from dy & dx + */ + Line::MC((dy, dx), (dx * y0 - dy * x0, dx)) + } else if dx == 0 { + //x-int is enough to identify common lines + Line::Inf(x0) + } else { + //y-int is enough to identify common lines + Line::Zero(y0) + } + }) + }).for_each(|k| { + *fm.entry(k).or_insert(0) += 1; + }); + let n = fm.values().max().cloned().unwrap(); + /* + * if 'm' points lie on a line & all points have been processed pairwise + * then n = m * (m - 1) / 2 pairs of points would have matched to same + * line m^2 - m - 2 * n = 0 => m = (1 + sqrt(8 * n + 1)) / 2 + */ + (1 + (8f64 * n as f64 + 1f64).sqrt() as i32) / 2 + } + fn gcd(a: i32, b: i32) -> i32 { + if a == 0 || b == 0 { + return 0; + } + let (mut a, mut b) = (a, b); + while b > 0 { + let tmp = a % b; + a = b; + b = tmp; + } + a + } +} + +fn main() { + let points1 = vec![vec![1,1],vec![2,2],vec![3,3]]; + let points2 = vec![vec![1,1],vec![3,2],vec![5,3],vec![4,1],vec![2,3],vec![1,4]]; + println!("{}", Solution::max_points(points1)); //expect: 3 + println!("{}", Solution::max_points(points2)); //expect: 3 +} diff --git a/max_product_3num.c b/max_product_3num.c new file mode 100644 index 0000000..65f7b19 --- /dev/null +++ b/max_product_3num.c @@ -0,0 +1,42 @@ +// 628. Maximum Product of Three Numbers +#include <limits.h> +#include <math.h> +#include <stdio.h> + +/* + * given an integer array 'nums', find three numbers whose product is maximum + * and return the maximum product + */ + +int maximumProduct(int *nums, int nums_size) { + int min1, min2, max1, max2, max3, num; + min1 = min2 = INT_MAX; + max1 = max2 = max3 = INT_MIN; + for (int i = 0; i < nums_size; i++) { + num = nums[i]; + if (min1 >= num) { + min2 = min1; + min1 = num; + } else if (min2 >= num) { + min2 = num; + } + if (max1 <= num) { + max3 = max2; + max2 = max1; + max1 = num; + } else if (max2 <= num) { + max3 = max2; + max2 = num; + } else if (max3 <= num) { + max3 = num; + } + } + return fmax(min1 * min2 * max1, max1 * max2 * max3); +} + +int main() { + int n1[] = {1, 2, 3}, n2[] = {1, 2, 3, 4}, n3[] = {-1, -2, -3}; + printf("%d\n", maximumProduct(n1, 3)); // expect: 6 + printf("%d\n", maximumProduct(n2, 4)); // expect: 24 + printf("%d\n", maximumProduct(n3, 3)); // expect: -6 +} diff --git a/max_product_3num.cpp b/max_product_3num.cpp new file mode 100644 index 0000000..1886bdb --- /dev/null +++ b/max_product_3num.cpp @@ -0,0 +1,40 @@ +// 628. Maximum Product of Three Numbers +#include "leetcode.h" + +/* + * given an integer array 'nums', find three numbers whose product is maximum + * and return the maximum product + */ + +class Solution { +public: + int maximumProduct(vector<int> &nums) { + int max1 = INT_MIN, max2 = INT_MIN, max3 = INT_MIN; + int min1 = INT_MAX, min2 = INT_MAX, min3 = INT_MAX; + for (int i = 0; i < nums.size(); i++) { + if (nums[i] <= min1) { + min2 = min1; + min1 = nums[i]; + } else if (nums[i] <= min2) + min2 = nums[i]; + if (nums[i] >= max1) { + max3 = max2; + max2 = max1; + max1 = nums[i]; + } else if (nums[i] >= max2) { + max3 = max2; + max2 = nums[i]; + } else if (nums[i] >= max3) + max3 = nums[i]; + } + return max(min1 * min2 * max1, max1 * max2 * max3); + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 2, 3}, n2 = {1, 2, 3, 4}, n3 = {-1, -2, -3}; + printf("%d\n", obj.maximumProduct(n1)); // expect: 6 + printf("%d\n", obj.maximumProduct(n2)); // expect: 24 + printf("%d\n", obj.maximumProduct(n3)); // expect: -6 +} diff --git a/max_product_diff_pair.c b/max_product_diff_pair.c new file mode 100644 index 0000000..889cdbc --- /dev/null +++ b/max_product_diff_pair.c @@ -0,0 +1,36 @@ +// 1913. Maximum Product Difference Between Two Pairs +#include "leetcode.h" + +/* + * the product difference between two pairs '(a, b)' and '(c, d)' is defined as + * '(a * b) - (c * d)'. given an integer array 'nums', choose four distinct + * indices 'w', 'x', 'y' and 'z' such that the product difference between pairs + * '(nums[w], nums[x])' and '(nums[y], nums[y])' is maximised. return the + * maximum such product difference + */ + +int maxProductDifference(int *nums, int nums_size) { + int a, b, c, d; + a = b = 0; + c = d = 10001; + for (int i = 0; i < nums_size; i++) { + int j = nums[i]; + if (j > b) { + a = b; + b = j; + } else if (j > a) + a = j; + if (j < c) { + c = d; + d = j; + } else if (j < c) + c = j; + } + return ((a * b) - (c * d)); +} + +int main() { + int n1[] = {5, 6, 2, 7, 4}, n2[] = {4, 2, 5, 9, 7, 4, 8}; + printf("%d\n", maxProductDifference(n1, ARRAY_SIZE(n1))); // expect: 34 + printf("%d\n", maxProductDifference(n2, ARRAY_SIZE(n2))); // expect: 64 +} diff --git a/max_product_diff_pair.py b/max_product_diff_pair.py new file mode 100644 index 0000000..32a4d49 --- /dev/null +++ b/max_product_diff_pair.py @@ -0,0 +1,27 @@ +# 1913. Maximum Product Difference Between Two Pairs + +""" +the product difference between two pairs '(a, b)' and '(c, d)' is defined as +'(a b) - (c d)'. given an integer array 'nums', choose four distinct +indices 'w', 'x', 'y' and 'z' such that the product difference between pairs +'(nums[w], nums[x])' and '(nums[y], nums[y])' is maximised. return the +maximum such product difference +""" + + +class Solution(object): + def maxProductDifference(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + return ( + sorted(nums)[len(nums) - 2] * sorted(nums)[len(nums) - 1] + - sorted(nums)[0] * sorted(nums)[1] + ) + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxProductDifference(nums=[5, 6, 2, 7, 4])) + print(obj.maxProductDifference(nums=[4, 2, 5, 9, 7, 4, 8])) diff --git a/max_product_split_bt.cpp b/max_product_split_bt.cpp new file mode 100644 index 0000000..f363c0e --- /dev/null +++ b/max_product_split_bt.cpp @@ -0,0 +1,19 @@ +#include "leetcode.h" + +class Solution { +public: + int maxProduct(TreeNode *root) { + tot = solve(root), solve(root); + return ans % (int)(1e9 + 7); + } + +private: + long ans = 0, tot = 0, sub; + int solve(TreeNode *root) { + if (!root) + return 0; + sub = root->val + solve(root->left) + solve(root->right); + ans = max(ans, sub * (tot - sub)); + return sub; + } +}; diff --git a/max_product_split_bt.rs b/max_product_split_bt.rs new file mode 100644 index 0000000..6aec321 --- /dev/null +++ b/max_product_split_bt.rs @@ -0,0 +1,43 @@ +#[derive(Debug, PartialEq, Eq)] +pub struct TreeNode { + pub val: i32, + pub left: Option<Rc<RefCell<TreeNode>>>, + pub right: Option<Rc<RefCell<TreeNode>>>, +} + +impl TreeNode { + #[inline] + pub fn new(val: i32) -> Self { + TreeNode { + val, + left: None, + right: None, + } + } +} + +use std::cell::RefCell; +use std::rc::Rc; +const MOD: i64 = 1_000_000_007; +impl Solution { + pub fn max_product(root: Option<Rc<RefCell<TreeNode>>>) -> i32 { + let mut sums = Vec::new(); + Self::dfs(&root, &mut sums); + ((0..sums.len() - 1) + .map(|i| sums[i] * (sums[sums.len() - 1] - sums[i])) + .max() + .unwrap() + % MOD) as i32 + } + fn dfs(node: &Option<Rc<RefCell<TreeNode>>>, sums: &mut Vec<i64>) -> i64 { + if let Some(n) = node { + let sum = n.borrow().val as i64 + + Self::dfs(&n.borrow().left, sums) + + Self::dfs(&n.borrow().right, sums); + sums.push(sum); + sum + } else { + 0 + } + } +} diff --git a/max_product_two_elem.c b/max_product_two_elem.c new file mode 100644 index 0000000..e52cf63 --- /dev/null +++ b/max_product_two_elem.c @@ -0,0 +1,30 @@ +// 1464. Maximum Product of Two Elements in an Array +#include "leetcode.h" + +/* + * given the array of integers 'nums', you will choose two different indices 'i' + * and 'j' of thatarray. return the maximum value of '(nums[i] - 1) * (nums[j] - + * 1)' + */ + +int maxProduct(int *nums, int nums_size) { + if (nums_size == 2) + return (nums[0] - 1) * (nums[1] - 1); + int max = nums[1] > nums[0] ? nums[1] : nums[0]; + int min = nums[1] > nums[0] ? nums[0] : nums[1]; + for (int i = 2; i < nums_size; i++) { + if (nums[i] > max) { + min = max; + max = nums[i]; + } else if (nums[i] <= max && nums[i] > min) + min = nums[i]; + } + return (max - 1) * (min - 1); +} + +int main() { + int n1[] = {3, 4, 5, 2}, n2[] = {1, 5, 4, 5}, n3[] = {3, 7}; + printf("%d\n", maxProduct(n1, ARRAY_SIZE(n1))); // expect: 12 + printf("%d\n", maxProduct(n2, ARRAY_SIZE(n2))); // expect: 16 + printf("%d\n", maxProduct(n3, ARRAY_SIZE(n3))); // expect: 12 +} diff --git a/max_product_two_elem.py b/max_product_two_elem.py new file mode 100644 index 0000000..68ad11d --- /dev/null +++ b/max_product_two_elem.py @@ -0,0 +1,31 @@ +# 1464. Maximum Product of Two Elements in an Array +import math + +""" +given the array of integers 'nums', you will choose two different indices 'i' +and 'j' of thatarray. return the maximum value of '(nums[i] - 1) (nums[j] - +1)' +""" + + +class Solution(object): + def maxProduct(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + max1 = max2 = -math.inf + for n in nums: + if n > max1: + max2 = max1 + max1 = n + elif n > max2: + max2 = n + return (max1 - 1) * (max2 - 1) + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxProduct([3, 4, 5, 2])) + print(obj.maxProduct([1, 5, 4, 5])) + print(obj.maxProduct([3, 7])) diff --git a/max_product_word_len.cpp b/max_product_word_len.cpp new file mode 100644 index 0000000..c2e518d --- /dev/null +++ b/max_product_word_len.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + int maxProduct(vector<string> &words) { + int n = words.size(), ans = 0; + vector<bitset<26>> chars(n); + for (int i = 0; i < n; i++) { + for (auto &ch : words[i]) + chars[i][ch - 'a'] = 1; + for (int j = 0; j < i; j++) + if (!helper(chars[i], chars[j])) + ans = max(ans, (int)words[i].size() * (int)words[j].size()); + } + return ans; + } + +private: + bool helper(bitset<26> &a, bitset<26> &b) { + for (int i = 0; i < 26; i++) + if (a[i] && b[i]) + return true; + return false; + } +}; + +int main() { + Solution obj; + vector<string> words = {"abcw", "baz", "foo", "bar", "xtfn", "abcdef"}; + cout << obj.maxProduct(words); +} diff --git a/max_profit_job.c b/max_profit_job.c new file mode 100644 index 0000000..666b3db --- /dev/null +++ b/max_profit_job.c @@ -0,0 +1,63 @@ +// 1235. Maximum Profit in Job Scheduling +#include "leetcode.h" + +/* +We have n jobs, where every job is scheduled to be done from startTime[i] to +endTime[i], obtaining a profit of profit[i]. + +You're given the startTime, endTime and profit arrays, return the maximum profit +you can take such that there are no two jobs in the subset with overlapping time +range. + +If you choose a job that ends at time X you will be able to start another job +that starts at time X. +*/ + +struct list { + int start; + int end; + int point; +}; + +int next(int now, int finish_time, struct list *book, int start_time_size) { + for (int i = now + 1; i < start_time_size; i++) { + if (finish_time <= book[i].start) { + return i; + } + } + return start_time_size; +} + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int jobScheduling(int *start_time, int start_time_size, int *end_time, + int end_time_size, int *profit, int profit_size) { + int start[50001]; + start[start_time_size] = 0; + struct list *book = malloc(sizeof(struct list) * start_time_size); + for (int i = 0; i < start_time_size; i++) { + book[i].start = start_time[i]; + book[i].end = end_time[i]; + book[i].point = profit[i]; + } + qsort(book, start_time_size, sizeof(struct list), cmp); + for (int i = start_time_size - 1; i >= 0; i--) + start[i] = + fmax(book[i].point + start[next(i, book[i].end, book, start_time_size)], + start[i + 1]); + free(book); + return start[0]; +} + +int main() { + int st1[] = {1, 2, 3, 3}, et1[] = {3, 4, 5, 6}, p1[] = {50, 10, 40, 70}; + int st2[] = {1, 2, 3, 4, 6}, et2[] = {3, 5, 10, 6, 9}, + p2[] = {20, 20, 100, 70, 60}; + int st3[] = {1, 1, 1}, et3[] = {2, 3, 4}, p3[] = {5, 6, 4}; + printf("%d\n", jobScheduling(st1, ARRAY_SIZE(st1), et1, ARRAY_SIZE(et1), p1, + ARRAY_SIZE(p1))); // expect: 120 + printf("%d\n", jobScheduling(st2, ARRAY_SIZE(st2), et2, ARRAY_SIZE(et2), p2, + ARRAY_SIZE(p2))); // expect: 150 + printf("%d\n", jobScheduling(st3, ARRAY_SIZE(st3), et3, ARRAY_SIZE(et3), p3, + ARRAY_SIZE(p3))); // expect: 6 +} diff --git a/max_profit_job.cpp b/max_profit_job.cpp new file mode 100644 index 0000000..ca702c1 --- /dev/null +++ b/max_profit_job.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" + +class Solution { +public: + int jobScheduling(vector<int> &startTime, vector<int> &endTime, + vector<int> &profit) { + int n = startTime.size(); + vvd(int) jobs; + for (int i = 0; i < n; ++i) + jobs.push_back({endTime[i], startTime[i], profit[i]}); + sort(jobs.begin(), jobs.end()); + map<int, int> dp = {{0, 0}}; + for (auto &j : jobs) { + int curr = prev(dp.upper_bound(j[1]))->second + j[2]; + if (curr > dp.rbegin()->second) + dp[j[0]] = curr; + } + return dp.rbegin()->second; + } +}; + +int main() { + Solution obj; + vector<int> startTime = {1, 2, 3, 3}; + vector<int> endTime = {3, 4, 5, 6}; + vector<int> profit = {50, 10, 40, 70}; + cout << obj.jobScheduling(startTime, endTime, profit); // 120 +} diff --git a/max_profit_job.py b/max_profit_job.py new file mode 100644 index 0000000..db38763 --- /dev/null +++ b/max_profit_job.py @@ -0,0 +1,47 @@ +# 1235. Maximum Profit in Job Scheduling + +""" +We have n jobs, where every job is scheduled to be done from startTime[i] to +endTime[i], obtaining a profit of profit[i]. +You're given the startTime, endTime and profit arrays, return the maximum profit +you can take such that there are no two jobs in the subset with overlapping time +range. +If you choose a job that ends at time X you will be able to start another job +that starts at time X. +""" + + +class Solution(object): + def jobScheduling(self, startTime, endTime, profit): + """ + :type startTime: List[int] + :type endTime: List[int] + :type profit: List[int] + :rtype: int + """ + jobs = sorted(zip(endTime, startTime, profit)) + number_of_jobs = len(profit) + dp = [0] * (number_of_jobs + 1) + for i, (current_end_time, current_start_time, current_profit) in enumerate( + jobs + ): + index = bisect_right(jobs, current_start_time, hi=i, key=lambda x: x[0]) + dp[i + 1] = max(dp[i], dp[index] + current_profit) + return dp[number_of_jobs] + + +if __name__ == "__main__": + obj = Solution() + print( + obj.jobScheduling( + startTime=[1, 2, 3, 3], endTime=[3, 4, 5, 6], profit=[50, 10, 40, 70] + ) + ) + print( + obj.jobScheduling( + startTime=[1, 2, 3, 4, 6], + endTime=[3, 5, 10, 6, 9], + profit=[20, 20, 100, 70, 60], + ) + ) + print(obj.jobScheduling(startTime=[1, 1, 1], endTime=[2, 3, 4], profit=[5, 6, 4])) diff --git a/max_profit_job.rs b/max_profit_job.rs new file mode 100644 index 0000000..fe1fafe --- /dev/null +++ b/max_profit_job.rs @@ -0,0 +1,30 @@ +struct Solution; + +impl Solution { + pub fn job_scheduling(start_time: Vec<i32>, end_time: Vec<i32>, profit: Vec<i32>) -> i32 { + let mut jobs: Vec<usize> = (0..profit.len()).collect(); + jobs.sort_unstable_by_key(|&i| end_time[i]); + let mut dp: Vec<(i32, i32)> = vec![(0, i32::MIN)]; + for &i in jobs.iter() { + let left = match dp.binary_search_by_key(&start_time[i], |&(_, t)| t) { + Ok(j) => j, + Err(j) => j - 1 + }; + if dp[left].0 + profit[i] > dp.last().unwrap().0 { + if end_time[i] == dp.last().unwrap().1 { + dp.last_mut().unwrap().0 = dp[left].0 + profit[i]; + } else { + dp.push((dp[left].0 + profit[i], end_time[i])); + } + } + } + dp.last().unwrap().0 + } +} + +fn main() { + let start_time = vec![1,2,3,3]; + let end_time = vec![3,4,5,6]; + let profit = vec![50,10,40,70]; + print!("{}", Solution::job_scheduling(start_time, end_time, profit)); //120 +} diff --git a/max_repeat_substr.c b/max_repeat_substr.c new file mode 100644 index 0000000..3a4dca5 --- /dev/null +++ b/max_repeat_substr.c @@ -0,0 +1,39 @@ +// 1668. Maximum Repeating Substring +#include "leetcode.h" + +/* + * for a string 'sequence', a string 'word' is 'k'-repeating if 'word' + * concatenated 'k' times is a substring of 'sequence'. the 'word's maximum + * 'k'-repeating value is the highest value 'k' where 'word' is 'k'-repeating in + * 'sequence'. if 'word' is not a substring of 'sequence', 'word's maximum + * 'k'-repeating value is 0. given strings 'sequence' and 'word', return the + * maximum 'k'-repeating value of 'word' in 'sequence'. + */ + +int maxRepeating(char *sequence, char *word) { + int idx = 0, n = strlen(sequence), m = strlen(word), max = 0, cnt = 0; + for (int i = 0; i < n; i++) { + if (strncmp(&sequence[i], word, m)) + continue; + else { + cnt = 1; + for (int k = i + m; i < n; k += m) { + if (strncmp(&sequence[k], word, m)) + break; + else + cnt++; + } + max = fmax(max, cnt); + } + } + return max; +} + +int main() { + char *s1 = "ababc", *w1 = "ab"; + char *s2 = "ababc", *w2 = "ba"; + char *s3 = "ababc", *w3 = "ac"; + printf("%d\n", maxRepeating(s1, w1)); // expect: 2 + printf("%d\n", maxRepeating(s2, w2)); // expect: 1 + printf("%d\n", maxRepeating(s3, w3)); // expect: 0 +} diff --git a/max_repeat_substr.py b/max_repeat_substr.py new file mode 100644 index 0000000..e3d6b9e --- /dev/null +++ b/max_repeat_substr.py @@ -0,0 +1,43 @@ +# 1668. Maximum Repeating Substring + +""" +for a string 'sequence', a string 'word' is 'k'-repeating if 'word' +concatenated 'k' times is a substring of 'sequence'. the 'word's maximum +'k'-repeating value is the highest value 'k' where 'word' is 'k'-repeating in +'sequence'. if 'word' is not a substring of 'sequence', 'word's maximum +'k'-repeating value is 0. given strings 'sequence' and 'word', return the +maximum 'k'-repeating value of 'word' in 'sequence'. +""" + + +class Solution(object): + def maxRepeating(self, sequence, word): + """ + :type sequence: str + :type word: str + :rtype: int + """ + n, m = len(sequence), len(word) + max_repeat = n + failure = [0] * (m * max_repeat + 1) + repeat_words = word * max_repeat + "$" + ans, j = 0, 0 + for i in range(1, len(repeat_words)): + while j > 0 and repeat_words[j] != repeat_words[i]: + j = failure[j - 1] + j += repeat_words[j] == repeat_words[i] + failure[i] = j + j = 0 + for i, c in enumerate(sequence): + while j > 0 and repeat_words[j] != c: + j = failure[j - 1] + j += repeat_words[j] == c + ans = max(ans, j // m) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxRepeating("ababc", "ab")) # expect: 2 + print(obj.maxRepeating("ababc", "ba")) # expect: 1 + print(obj.maxRepeating("ababc", "ac")) # expect: 0 diff --git a/max_running_time_n_computer.c b/max_running_time_n_computer.c new file mode 100644 index 0000000..c60b0ea --- /dev/null +++ b/max_running_time_n_computer.c @@ -0,0 +1,46 @@ +// 2141. Maximum Running Time of N Computers +#include <math.h> +#include <stdbool.h> +#include <stdio.h> + +/* + * you have 'n' computers. you are given the integer 'n' and a 0-indexed integer + * array 'batteries' where the i'th battery can run a computer for + * 'batteries[i]' minutes. you are interested in running all 'n' computers + * simultaneously using the given batteries. initially, you can insert at most + * one battery into each computer. after that and at any integer time moment, + * you can remove a battery from a computer and insert another battery any + * number of times. the inserted battery can be a totally new battery or a + * battery forom another computer. you may assume that the removing and + * inserting process takes no time. note that the batteries canot be recharged. + * return the maximum number of minutes you can run all the 'n' computers + * simultaneously. + */ + +bool check(int n, int *batteries, int batteries_size, long long time) { + long long total = time * n, sum = 0; + for (int i = 0; i < batteries_size; i++) { + sum += fmin(time, batteries[i]); + if (sum >= total) + return true; + } + return false; +} + +long long maxRunTime(int n, int *batteries, int batteries_size) { + long long left = 0, right = 1e14; + while (left < right) { + long long mid = right - (right - left) / 2; + if (check(n, batteries, batteries_size, mid)) + left = mid; + else + right = mid - 1; + } + return left; +} + +int main() { + int b1[] = {3, 3, 3}, b2[] = {1, 1, 1, 1}; + printf("%lld\n", maxRunTime(2, b1, 3)); // expect: 4 + printf("%lld\n", maxRunTime(2, b2, 4)); // expect: 2 +} diff --git a/max_running_time_n_computer.cpp b/max_running_time_n_computer.cpp new file mode 100644 index 0000000..e5a10b5 --- /dev/null +++ b/max_running_time_n_computer.cpp @@ -0,0 +1,35 @@ +// 2141. Maximum Running Time of N Computers +#include "leetcode.h" + +/* + * you have 'n' computers. you are given the integer 'n' and a 0-indexed integer + * array 'batteries' where the i'th battery can run a computer for + * 'batteries[i]' minutes. you are interested in running all 'n' computers + * simultaneously using the given batteries. initially, you can insert at most + * one battery into each computer. after that and at any integer time moment, + * you can remove a battery from a computer and insert another battery any + * number of times. the inserted battery can be a totally new battery or a + * battery forom another computer. you may assume that the removing and + * inserting process takes no time. note that the batteries canot be recharged. + * return the maximum number of minutes you can run all the 'n' computers + * simultaneously. + */ + +class Solution { +public: + long long maxRunTime(int n, vector<int> &batteries) { + sort(batteries.begin(), batteries.end()); + long long sum = accumulate(batteries.begin(), batteries.end(), 0L); + int k = 0, i = batteries.size(); + while (batteries[i - 1 - k] > sum / (n - k)) + sum -= batteries[i - 1 - k++]; + return sum / (n - k); + } +}; + +int main() { + Solution obj; + vector<int> b1 = {3, 3, 3}, b2 = {1, 1, 1, 1}; + printf("%lld\n", obj.maxRunTime(2, b1)); // expect: 4 + printf("%lld\n", obj.maxRunTime(2, b2)); // expect: 2 +} diff --git a/max_score_good_subarr.c b/max_score_good_subarr.c new file mode 100644 index 0000000..aef1662 --- /dev/null +++ b/max_score_good_subarr.c @@ -0,0 +1,41 @@ +// 1793. Maximum Score of a Good Subarray +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array of integers 'nums' (0-indexed) and an integer 'k'. the score + * of a subarray '(i, j)' is defined as 'min(nums[i], nums[i + 1], ..., nums[j]) + * * (j - i + 1)'. a good subarray is a subarray where 'i <= k <= j'. return the + * maximum possible score of a good subarray. + */ + +int maximumScore(int *nums, int nums_size, int k) { + int ans = 0, n = nums_size, left = k - 1, right = k + 1, min_val = nums[k]; + long long sum = nums[k]; + while (left >= 0 || right < n) { + if (left >= 0 && nums[left] >= min_val) { + sum += nums[left]; + left--; + } else if (right < n && nums[right] >= min_val) { + sum += nums[right]; + right++; + } else { + ans = fmax(ans, min_val * (right - left - 1)); + if (left >= 0 && right < n) + min_val = fmax(nums[left], nums[right]); + else if (left >= 0) + min_val = nums[left]; + else + min_val = nums[right]; + } + } + ans = fmax(ans, min_val * (right - left - 1)); + return ans; +} + +int main() { + int n1[] = {1, 4, 3, 7, 4, 5}, n2[] = {5, 5, 4, 5, 4, 1, 1, 1}; + printf("%d\n", maximumScore(n1, 6, 3)); // expect: 15 + printf("%d\n", maximumScore(n1, 8, 0)); // expect: 20 +} diff --git a/max_score_good_subarr.cpp b/max_score_good_subarr.cpp new file mode 100644 index 0000000..3c7bc89 --- /dev/null +++ b/max_score_good_subarr.cpp @@ -0,0 +1,36 @@ +// 1793. Maximum Score of a Good Subarray +#include "leetcode.h" + +/* + * given an array of integers 'nums' (0-indexed) and an integer 'k'. the score + * of a subarray '(i, j)' is defined as 'min(nums[i], nums[i + 1], ..., nums[j]) + * * (j - i + 1)'. a good subarray is a subarray where 'i <= k <= j'. return the + * maximum possible score of a good subarray. + */ + +class Solution { +public: + int maximumScore(vector<int> &nums, int k) { + nums.push_back(0); + stack<int> st; + int n = nums.size(), ans = 0; + for (int i = 0; i < n; i++) { + while (!st.empty() && nums[st.top()] >= nums[i]) { + int height = nums[st.top()]; + st.pop(); + int left = st.empty() ? -1 : st.top(); + if (k < i && k > left) + ans = max(ans, height * (i - left - 1)); + } + st.push(i); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 4, 3, 7, 4, 5}, n2 = {5, 5, 4, 5, 4, 1, 1, 1}; + printf("%d\n", obj.maximumScore(n1, 3)); // expect: 15 + printf("%d\n", obj.maximumScore(n2, 0)); // expect: 20 +} diff --git a/max_score_good_subarr.py b/max_score_good_subarr.py new file mode 100644 index 0000000..138544d --- /dev/null +++ b/max_score_good_subarr.py @@ -0,0 +1,28 @@ +# 1793. Maximum Score of a Good Subarray + +""" +given an array of integers 'nums' (0-indexed) and an integer 'k'. the score +of a subarray '(i, j)' is defined as 'min(nums[i], nums[i + 1], ..., nums[j]) +(j - i + 1)'. a good subarray is a subarray where 'i <= k <= j'. return the +maximum possible score of a good subarray. +""" + + +class Solution(object): + def maximumScore(self, nums, k): + ans = mini = nums[k] + i, j, n = k, k, len(nums) + while i > 0 or j < n - 1: + if (nums[i - 1] if i else 0) < (nums[j + 1] if j < n - 1 else 0): + j += 1 + else: + i -= 1 + mini = min(mini, nums[i], nums[j]) + ans = max(ans, mini * (j - i + 1)) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.maximumScore(nums=[1, 4, 3, 7, 4, 5], k=3)) # expect: 15 + print(obj.maximumScore(nums=[5, 5, 4, 5, 4, 1, 1, 1], k=0)) # expect: 20 diff --git a/max_score_mult_opp.cpp b/max_score_mult_opp.cpp new file mode 100644 index 0000000..7758a29 --- /dev/null +++ b/max_score_mult_opp.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + int maximumScore(vector<int> &nums, vector<int> &multipliers) { + n = nums.size(); + m = multipliers.size(); + memset(memo, -1, sizeof(memo)); + return dp(0, 0, nums, multipliers); + } + +private: + int m, n, memo[1000][1000]; + int dp(int l, int i, vector<int> &nums, vector<int> &multipliers) { + if (i == m) + return 0; + if (memo[l][i] != -1) + return memo[l][i]; + int pickLeft = + dp(l + 1, i + 1, nums, multipliers) + nums[l] * multipliers[i]; + int pickRight = dp(l, i + 1, nums, multipliers) + + nums[n - (i - l) - 1] * multipliers[i]; + return memo[l][i] = max(pickLeft, pickRight); + } +}; + +int main() { + Solution obj; + vector<int> nums = {1, 2, 3}, multipliers = {3, 2, 1}; + cout << obj.maximumScore(nums, multipliers); +} diff --git a/max_score_n_operations.cpp b/max_score_n_operations.cpp new file mode 100644 index 0000000..a2dc2b9 --- /dev/null +++ b/max_score_n_operations.cpp @@ -0,0 +1,59 @@ +// 1799. Maximize Score After N Operations +#include "leetcode.h" + +/* + * given 'nums', an array of positive integers of size '2 * n'. you must perform + * 'n' operations on this array. in the i'th operation (1-index), you will: + * - choose two elements 'x' and 'y' + * - receive a score of 'i * gcd(x, y)' + * - remove 'x' and 'y' from 'nums' + * return the maximum score you can receive after performing 'n' operations. the + * function 'gcd(x, y)' is the greatest common divisor. + */ + +class Solution { +public: + int maxScore(vector<int> nums) { + m = nums.size(); + n = m / 2; + return dp(nums, 1, 0); + } + +private: + int gcd_memo[14][14] = {}; + int memo[1 << 4] = {}; + int m, n; + int dp(vector<int> &nums, int op, int mask) { + if (op > n) + return 0; + if (memo[mask]) + return memo[mask]; + for (int i = 0; i < m; ++i) { + if ((mask >> i) & 0x1) + continue; + for (int j = i + 1; j < m; ++j) { + if ((mask >> j) & 0x1) + continue; + int new_mask = (0x1 << i) | (0x1 << j) | mask; + int score = op * gcd(nums, i, j) + dp(nums, op + 1, new_mask); + memo[mask] = max(memo[mask], score); + } + } + return memo[mask]; + } + int gcd(vector<int> &nums, int i, int j) { + if (gcd_memo[i][j]) + return gcd_memo[i][j]; + return gcd_memo[i][j] = __gcd(nums[i], nums[j]); + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 2}; + vector<int> n2 = {3, 4, 6, 8}; + vector<int> n3 = {1, 2, 3, 4, 5, 6}; + printf("%d\n", obj.maxScore(n1)); // expect: 1 + printf("%d\n", obj.maxScore(n2)); // expect: 11 + printf("%d\n", obj.maxScore(n3)); // expect: 14 +} diff --git a/max_score_node_sequence.cpp b/max_score_node_sequence.cpp new file mode 100644 index 0000000..b4df5d5 --- /dev/null +++ b/max_score_node_sequence.cpp @@ -0,0 +1,43 @@ +#include "leetcode.h" + +class Solution { +public: + int maximumScore(vector<int> &scores, vector<vector<int>> &edges) { + const int n = scores.size(); + vector<vector<int>> adj(n); + for (const vector<int> &edge : edges) { + adj[edge[0]].push_back(edge[1]); + adj[edge[1]].push_back(edge[0]); + } + for (vector<int> &a : adj) { + priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pqpvg; + for (int v : a) { + int score = scores[v]; + if (pqpvg.size() < 3 || pqpvg.top().first < score) { + pqpvg.push({score, v}); + if (pqpvg.size() > 3) + pqpvg.pop(); + } + } + a.resize(pqpvg.size()); + for (int i = a.size() - 1; i >= 0; --i) { + a[i] = pqpvg.top().second; + pqpvg.pop(); + } + } + int ans = -1; + for (const vector<int> &edge : edges) { + int u = edge[0], v = edge[1], base = scores[u] + scores[v]; + for (int x : adj[u]) { + if (x == v) + continue; + for (int y : adj[v]) { + if (y == u || x == y) + continue; + ans = max(ans, base + scores[x] + scores[y]); + } + } + } + return ans; + } +}; diff --git a/max_score_perform_op.c b/max_score_perform_op.c new file mode 100644 index 0000000..745127d --- /dev/null +++ b/max_score_perform_op.c @@ -0,0 +1,39 @@ +// 1770. Maximum Score from Performing Multiplication Operations +#include "leetcode.h" + +/* + * given two 0 indexed integer arrays 'nums' and multipliers of size n and m + * respectively, where n >= m. you begin with a score of 0. you want to perform + * exactly m operations. on the i'th operation, you will choose one integer x + * from either the start or the end of the array 'nums'. add 'multipliers[i] * + * x' to your score. note that 'multipliers[0]' correspons to the first + * operation, 'multipliers[1]' to the second operation and so on. return the + * maximum score after performing m operations. + */ + +int maximumScore(int *nums, int numsSize, int *multipliers, + int multipliersSize) { + int dp_size = fmin(numsSize, multipliersSize); + int *row = &nums[numsSize - dp_size], *col = nums; + int **dp = malloc(dp_size * sizeof(int *)); + for (int i = 0; i < dp_size; i++) { + dp[i] = malloc(dp_size * sizeof(int)); + dp[i][i] = fmax(multipliers[dp_size - 1] * row[i], + multipliers[dp_size - 1] * col[i]); + } + for (int i = 1; i < dp_size; i++) + for (int j = 0; j < dp_size - i; j++) + dp[j][i + j] = + fmax(col[j] * multipliers[dp_size - 1 - i] + dp[j + 1][i + j], + row[i + j] * multipliers[dp_size - 1 - i] + dp[j][i + j - 1]); + return dp[0][dp_size - 1]; +} + +int main() { + int n1[] = {1, 2, 3}, m1[] = {3, 2, 1}, n2[] = {-5, -3, -3, -2, 7, 1}, + m2[] = {-10, -5, 3, 4, 6}; + printf("%d\n", + maximumScore(n1, ARRAY_SIZE(n1), m1, ARRAY_SIZE(m1))); // expect: 14 + printf("%d\n", + maximumScore(n2, ARRAY_SIZE(n2), m2, ARRAY_SIZE(m2))); // expect: 102 +} diff --git a/max_score_perform_op.py b/max_score_perform_op.py new file mode 100644 index 0000000..644c691 --- /dev/null +++ b/max_score_perform_op.py @@ -0,0 +1,37 @@ +# 1770. Maximum Score from Performing Multiplication Operations + +""" +given two 0 indexed integer arrays 'nums' and multipliers of size n and m +respectively, where n >= m. you begin with a score of 0. you want to perform +exactly m operations. on the i'th operation, you will choose one integer x +from either the start or the end of the array 'nums'. add 'multipliers[i] +x' to your score. note that 'multipliers[0]' correspons to the first +operation, 'multipliers[1]' to the second operation and so on. return the +maximum score after performing m operations. +""" + + +class Solution(object): + def maximumScore(self, nums, multipliers): + """ + :type nums: List[int] + :type multipliers: List[int] + :rtype: int + """ + n, m = len(nums), len(multipliers) + dp = [[0] * (m + 1) for _ in range(m + 1)] + for l in range(m - 1, -1, -1): + for i in range(m - 1, -1, -1): + r = n - (i - l) - 1 + if r < 0 or r >= n: + break + leftPick = dp[l + 1][i + 1] + nums[l] * multipliers[i] + rightPick = dp[l][i + 1] + nums[r] * multipliers[i] + dp[l][i] = max(leftPick, rightPick) + return dp[0][0] + + +if __name__ == "__main__": + obj = Solution() + print(obj.maximumScore(nums=[1, 2, 3], multipliers=[3, 2, 1])) + print(obj.maximumScore(nums=[-5, -3, -3, -2, 7, 1], multipliers=[-10, -5, 3, 4, 6])) diff --git a/max_score_split_str.c b/max_score_split_str.c new file mode 100644 index 0000000..f636fce --- /dev/null +++ b/max_score_split_str.c @@ -0,0 +1,31 @@ +// 1422. Maximum Score After Splitting a String +#include "leetcode.h" + +/* + * given a string 's' of zeros and ones, return the maximum score after + * splitting the string into two non-empty substrings (ie. left and right). the + * score after splitting a string is the number of zeros in the left substring + * plus the number of ones in the right substring. + */ + +int maxScore(char *s) { + int n = strlen(s), ans = 0; + int *suffix_one = malloc(n * sizeof(int)); + int *prefix_zero = malloc(n * sizeof(int)); + suffix_one[n - 1] = (s[n - 1] == '1'); + for (int i = n - 2; i >= 0; i--) + suffix_one[i] = suffix_one[i + 1] + (s[i] == '1'); + prefix_zero[0] = (s[0] == '0'); + for (int i = 1; i < n; i++) + prefix_zero[i] = prefix_zero[i - 1] + (s[i] == '0'); + for (int i = 1; i < n; i++) + ans = fmax(ans, suffix_one[i] + prefix_zero[i - 1]); + return ans; +} + +int main() { + char *s1 = "011101", *s2 = "00111", *s3 = "1111"; + printf("%d\n", maxScore(s1)); // expect: 5 + printf("%d\n", maxScore(s2)); // expect: 5 + printf("%d\n", maxScore(s3)); // expect: 3 +} diff --git a/max_score_split_str.py b/max_score_split_str.py new file mode 100644 index 0000000..5152d8a --- /dev/null +++ b/max_score_split_str.py @@ -0,0 +1,31 @@ +# 1422. Maximum Score After Splitting a String + +""" +given a string 's' of zeros and ones, return the maximum score after +splitting the string into two non-empty substrings (ie. left and right). the +score after splitting a string is the number of zeros in the left substring +plus the number of ones in the right substring. +""" + + +class Solution(object): + def maxScore(self, s): + """ + :type s: str + :rtype: int + """ + max_score = prefix_zero = 0 + suffix_one = s.count("1") + for i in range(len(s) - 1): + prefix_zero += s[i] == "0" + suffix_one -= s[i] == "1" + max_score = max(max_score, prefix_zero + suffix_one) + + return max_score + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxScore("011101")) + print(obj.maxScore("00111")) + print(obj.maxScore("1111")) diff --git a/max_score_word_letters.c b/max_score_word_letters.c new file mode 100644 index 0000000..d7945b2 --- /dev/null +++ b/max_score_word_letters.c @@ -0,0 +1,98 @@ +// 1255. Maximum Score Words Formed by Letters +#include "leetcode.h" + +/* + * given a list of 'words' list of single 'letters' (potentially repeating), and + * 'score' of every character. return the maximum score of any valid set of + * words formed by using the given letters ('words[i]' cannot be used two or + * more times). it is not necessary to use all characters in 'letters' and each + * letter can only be used once. score of letters a through z is given by + * 'score[i]' respectively. + */ + +struct pair { + bool valid; + int len; + int score; +}; + +int process(char *str, int *hash, struct pair *p, int idx, bool *no_add) { + if (!(*no_add)) { + for (int i = 0; i < p[idx].len; i++) + hash[str[i] - 'a']++; + } else { + for (int i = 0; i < p[idx].len; i++) { + if (!hash[str[i] - 'a']) { + for (int j = 0; j < i; j++) + hash[str[j] - 'a']++; + return 0; + } + hash[str[i] - 'a']--; + } + *no_add = false; + } + return p[idx].score; +} + +void dfs(char **words, int wordsSize, int *hash, struct pair *p, int *cnt, + int *res, int idx) { + if (idx == wordsSize) { + *res = fmax(*cnt, *res); + return; + } + for (int i = idx; i < wordsSize; i++) { + bool no_add = true; + if (p[i].valid) + *cnt += process(words[i], hash, p, i, &no_add); + dfs(words, wordsSize, hash, p, cnt, res, i + 1); + if (!no_add) + *cnt -= process(words[i], hash, p, i, &no_add); + } +} + +int maxScoreWords(char **words, int wordsSize, char *letters, int lettersSize, + int *score, int scoreSize) { + int hash[26] = {0}, cnt = 0, ans = 0; + for (int i = 0; i < lettersSize; i++) + hash[letters[i] - 'a']++; + struct pair *p = (struct pair *)calloc(wordsSize, sizeof(struct pair)); + for (int i = 0; i < wordsSize; i++) { + int n = strlen(words[i]), res = 1, tmp = 0; + p[i].len = n; + for (int j = 0; j < n; j++) { + tmp += score[words[i][j] - 'a']; + if (!hash[words[i][j] - 'a']) { + res = 0; + break; + } + } + p[i].valid = res; + p[i].score = !p[i].valid ? 0 : tmp; + } + dfs(words, wordsSize, hash, p, &cnt, &ans, 0); + free(p); + return ans; +} + +int main() { + char *w1[] = {"dog", "cat", "dad", "good"}, + *w2[] = {"xxxz", "ax", "bx", "cx"}, *w3[] = {"leetcode"}, + *l1[] = {"a", "a", "c", "d", "d", "d", "g", "o", "o"}, + *l2[] = {"z", "a", "b", "c", "x", "x", "x"}, + *l3[] = {"l", "e", "t", "c", "o", "d"}; + int s1[] = {1, 0, 9, 5, 0, 0, 3, 0, 0, 0, 0, 0, 0, + 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + s2[] = {4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 10}, + s3[] = {0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}; + printf("%d\n", + maxScoreWords((char **)w1, ARRAY_SIZE(w1), (char *)l1, ARRAY_SIZE(l1), + s1, ARRAY_SIZE(s1))); // expect: 23 + printf("%d\n", + maxScoreWords((char **)w2, ARRAY_SIZE(w2), (char *)l2, ARRAY_SIZE(l2), + s2, ARRAY_SIZE(s2))); // expect: 27 + printf("%d\n", + maxScoreWords((char **)w3, ARRAY_SIZE(w3), (char *)l3, ARRAY_SIZE(l3), + s3, ARRAY_SIZE(s3))); // expect: 0 +} diff --git a/max_score_word_letters.py b/max_score_word_letters.py new file mode 100644 index 0000000..cb9deee --- /dev/null +++ b/max_score_word_letters.py @@ -0,0 +1,147 @@ +# 1255. Maximum Score Words Formed by Letters + +""" +given a list of 'words' list of single 'letters' (potentially repeating), and +'score' of every character. return the maximum score of any valid set of +words formed by using the given letters ('words[i]' cannot be used two or +more times). it is not necessary to use all characters in 'letters' and each +letter can only be used once. score of letters a through z is given by +'score[i]' respectively. +""" + + +class Solution(object): + def maxScoreWords(self, words, letters, score): + """ + :type words: List[str] + :type letters: List[str] + :type score: List[int] + :rtype: int + """ + cnt = [0] * 26 + letters_cnt = [0] * 26 + for c in letters: + cnt[ord(c) - ord("a")] += 1 + self.ans = 0 + self.backtracking(words, score, cnt, letters_cnt, 0, 0) + return self.ans + + def backtracking(self, words, score, cnt, letters_cnt, pos, tmp): + for i in range(26): + if letters_cnt[i] > cnt[i]: + return + self.ans = max(self.ans, tmp) + for i in range(pos, len(words)): + for c in words[i]: + letters_cnt[ord(c) - ord("a")] += 1 + tmp += score[ord(c) - ord("a")] + self.backtracking(words, score, cnt, letters_cnt, i + 1, tmp) + for c in words[i]: + letters_cnt[ord(c) - ord("a")] -= 1 + tmp -= score[ord(c) - ord("a")] + + +if __name__ == "__main__": + obj = Solution() + print( + obj.maxScoreWords( + words=["dog", "cat", "dad", "good"], + letters=["a", "a", "c", "d", "d", "d", "g", "o", "o"], + score=[ + 1, + 0, + 9, + 5, + 0, + 0, + 3, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ], + ) + ) + print( + obj.maxScoreWords( + words=["xxxz", "ax", "bx", "cx"], + letters=["z", "a", "b", "c", "x", "x", "x"], + score=[ + 4, + 4, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 5, + 0, + 10, + ], + ) + ) + print( + obj.maxScoreWords( + words=["leetcode"], + letters=["l", "e", "t", "c", "o", "d"], + score=[ + 0, + 0, + 1, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + ], + ) + ) diff --git a/max_subarray.cpp b/max_subarray.cpp new file mode 100644 index 0000000..7356925 --- /dev/null +++ b/max_subarray.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class Solution { +public: + int maxSubArray(vector<int> &nums) { + return helper(nums, 0, nums.size() - 1); + } + +private: + int helper(vector<int> &nums, int l, int r) { + if (l > r) + return INT_MIN; + int m = l + (r - l) / 2, mL = 0, mR = 0; + int lMax = helper(nums, l, m - 1); + int rMax = helper(nums, m + 1, r); + for (int i = m - 1, sum = 0; i >= l; i--) { + sum += nums[i]; + mL = max(sum, mL); + } + for (int i = m + 1, sum = 0; i <= r; i++) { + sum += nums[i]; + mR = max(sum, mR); + } + return max(max(lMax, rMax), mL + mR + nums[m]); + } +}; + +int main() { + vector<int> nums = {-2, 1, -3, 4, -1, 2, 1, -5, 4}; + Solution obj; + cout << obj.maxSubArray(nums); +} diff --git a/max_subseq_score.c b/max_subseq_score.c new file mode 100644 index 0000000..deb41c1 --- /dev/null +++ b/max_subseq_score.c @@ -0,0 +1,99 @@ +// 2542. Maximum Subsequence Score +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given two 0-indexed integer arrays 'num1' and 'nums2' of equal length 'n' and + * a positive integer 'k'. you must choose a subsequence of indices from 'nums1' + * of length 'k'. for chosen indices 'i0, i1, ..., ik-1', your score is defined + * as + * - the sum of the selected elements from 'nums1' multiplied with the minimum + * of the selected elements from 'nums2' + * - it can defined simply as '(num1[i0] + nums1[i1] + ... + nums1[ik - 1]) * + * min(nums2[i0], nums2[i1], ..., nums2[ik - 1])' return the maximum possible + * score. a subseqnce of indices of an array is a set that can be derived from + * the set '{0, 1, ..., n - 1}' by deleting no elements + */ + +int cmp(const void *a, const void *b) { + int *ptr_a = *(int **)a; + int *ptr_b = *(int **)b; + if (ptr_a[1] == ptr_b[1]) + return ptr_a[0] - ptr_b[0]; + return ptr_a[1] - ptr_b[1]; +} + +int cmp1(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +void insert(int *heap, int k, int val, long long *sum) { + if (val <= heap[0]) + return; + int f = 0; + *sum = *sum + val - heap[0]; + heap[0] = val; + while (1) { + int child1 = 2 * f + 1; + int child2 = 2 * f + 2; + if (child2 < k) { + if (heap[child1] <= heap[child2]) { + if (heap[child1] < heap[f]) { + int tmp = heap[child1]; + heap[child1] = heap[f]; + heap[f] = tmp; + f = child1; + } else + break; + } else { + if (heap[child2] < heap[f]) { + int tmp = heap[child2]; + heap[child2] = heap[f]; + heap[f] = tmp; + f = child2; + } else + break; + } + } else if (child1 < k) { + if (heap[child1] < heap[f]) { + int tmp = heap[child1]; + heap[child1] = heap[f]; + heap[f] = tmp; + f = child1; + } else + break; + } else + break; + } +} + +long long maxScore(int *nums1, int nums1_size, int *nums2, int nums2_size, + int k) { + long long ans = 0, sum = 0; + int n = nums1_size; + int **tmp = malloc(n * sizeof(int *)); + int *heap = malloc(2 * k * sizeof(int)); + for (int i = 0; i < n; i++) { + tmp[i] = malloc(2 * sizeof(int)); + tmp[i][0] = nums1[i]; + tmp[i][1] = nums2[i]; + } + qsort(tmp, n, sizeof(int *), cmp); + for (int i = 0; i < k; i++) { + heap[i] = tmp[n - 1 - i][0]; + sum += tmp[n - 1 - i][0]; + } + ans = sum * (long long)tmp[n - k][1]; + qsort(heap, k, sizeof(int), cmp1); + for (int i = n - k - 1; i >= 0; i--) { + insert(heap, k, tmp[i][0], &sum); + ans = fmax(ans, sum * tmp[i][1]); + } + return ans; +} + +int main() { + int n11[] = {1, 3, 3, 2}, n21[] = {2, 1, 3, 4}; + int n12[] = {4, 2, 3, 1, 1}, n22[] = {7, 5, 10, 9, 6}; + printf("%lld\n", maxScore(n11, 4, n21, 4, 3)); // expect: 12 + printf("%lld\n", maxScore(n12, 5, n22, 5, 1)); // expect: 30 +} diff --git a/max_subseq_score.cpp b/max_subseq_score.cpp new file mode 100644 index 0000000..a739d77 --- /dev/null +++ b/max_subseq_score.cpp @@ -0,0 +1,47 @@ +// 2542. Maximum Subsequence Score +#include "leetcode.h" + +/* + * given two 0-indexed integer arrays 'num1' and 'nums2' of equal length 'n' and + * a positive integer 'k'. you must choose a subsequence of indices from 'nums1' + * of length 'k'. for chosen indices 'i0, i1, ..., ik-1', your score is defined + * as + * - the sum of the selected elements from 'nums1' multiplied with the minimum + * of the selected elements from 'nums2' + * - it can defined simply as '(num1[i0] + nums1[i1] + ... + nums1[ik - 1]) * + * min(nums2[i0], nums2[i1], ..., nums2[ik - 1])' return the maximum possible + * score. a subseqnce of indices of an array is a set that can be derived from + * the set '{0, 1, ..., n - 1}' by deleting no elements + */ + +class Solution { +public: + long long maxScore(vector<int> &nums1, vector<int> &nums2, int k) { + int n = nums1.size(); + vector<pair<int, int>> ess(n); + for (int i = 0; i < n; ++i) + ess[i] = {nums2[i], nums1[i]}; + sort(rbegin(ess), rend(ess)); + long long sum_s = 0, ans = 0; + priority_queue<int, vector<int>, greater<int>> pq; + for (auto &[e, s] : ess) { + pq.emplace(s); + sum_s += s; + if (pq.size() > k) { + sum_s -= pq.top(); + pq.pop(); + } + if (pq.size() == k) + ans = max(ans, sum_s * e); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n11 = {1, 3, 3, 2}, n21 = {2, 1, 3, 4}; + vector<int> n12 = {4, 2, 3, 1, 1}, n22 = {7, 5, 10, 9, 6}; + printf("%lld\n", obj.maxScore(n11, n21, 3)); // expect: 12 + printf("%lld\n", obj.maxScore(n12, n22, 1)); // expect: 30 +} diff --git a/max_sum_binary_tree.c b/max_sum_binary_tree.c new file mode 100644 index 0000000..0a43dfb --- /dev/null +++ b/max_sum_binary_tree.c @@ -0,0 +1,64 @@ +// 1161. Maximum Level Sum of a Binary Tree +#include <limits.h> +#include <stdlib.h> + +/* + * given the 'root' of a binary tree, the level of its root is 1, the level of + * its children is 2, and so on. return the smallest level 'x' such that the sum + * of all the values of nodes at level 'x' is maximal. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int maxLevelSum(struct TreeNode *root) { + struct TreeNode **even = malloc(5000 * sizeof(struct TreeNode *)); + struct TreeNode **odd = malloc(5000 * sizeof(struct TreeNode *)); + int even_idx = 0, odd_idx = 0; + even[0] = root, even_idx = 1; + int max_sum = INT_MIN, max_id = -1, level = 1; + while (even_idx || odd_idx) { + int sum = 0; + if (even_idx) { + for (int i = 0; i < even_idx; i++) { + sum += even[i]->val; + if (even[i]->left) { + odd[odd_idx] = even[i]->left; + odd_idx++; + } + if (even[i]->right) { + odd[odd_idx] = even[i]->right; + odd_idx++; + } + } + if (sum > max_sum) { + max_sum = sum; + max_id = level; + } + even_idx = 0; + level++; + } else { + for (int i = 0; i < odd_idx; i++) { + sum += odd[i]->val; + if (odd[i]->left) { + even[even_idx] = odd[i]->left; + even_idx++; + } + if (odd[i]->right) { + even[even_idx] = odd[i]->right; + even_idx++; + } + } + if (sum > max_sum) { + max_sum = sum; + max_id = level; + } + odd_idx = 0; + level++; + } + } + return max_id; +} diff --git a/max_sum_binary_tree.cpp b/max_sum_binary_tree.cpp new file mode 100644 index 0000000..64d1d20 --- /dev/null +++ b/max_sum_binary_tree.cpp @@ -0,0 +1,26 @@ +// 1161. Maximum Level Sum of a Binary Tree +#include "leetcode.h" + +/* + * given the 'root' of a binary tree, the level of its root is 1, the level of + * its children is 2, and so on. return the smallest level 'x' such that the sum + * of all the values of nodes at level 'x' is maximal. + */ + +class Solution { + vector<int> sums; + void dfs(TreeNode *root, size_t level) { + if (root) { + sums.resize(max(sums.size(), level)); + sums[level - 1] += root->val; + dfs(root->left, level + 1); + dfs(root->right, level + 1); + } + } + +public: + int maxLevelSum(TreeNode *root) { + dfs(root, 1); + return distance(begin(sums), max_element(begin(sums), end(sums))) + 1; + } +}; diff --git a/max_sum_circular_subarr.c b/max_sum_circular_subarr.c new file mode 100644 index 0000000..85db07c --- /dev/null +++ b/max_sum_circular_subarr.c @@ -0,0 +1,46 @@ +// 918. Maximum Sum Circular Subarray +#include <stdio.h> +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +/* + * given: circular int array 'nums' of length 'n', return the max possible + * sum of non-empty subarray of 'nums' + * + * a circular array means the end of the array connects to the beginning. + * formally, the previous element of 'nums[i]' is 'nums[(i -/+ 1) % n]' + * + * a subarray may only include each element of the fixed buffer 'nums' at + * most once. formally, for a subarray 'nums[i], nums[i + 1], ..., nums[j]' + * there does not exist i <= k1, k2 <= j with k1 % n == k2 % n + */ + +int helper(int *a, int n) { + // kadane's dp algorithm + // [https://medium.com/@rsinghal757/kadanes-algorithm-dynamic-programming-how-and-why-does-it-work-3fd8849ed73d] + int currMax, sum; + sum = currMax = a[0]; + for (int i = 1; i < n; i++) { + currMax = MAX(a[i], currMax + a[i]); + sum = MAX(currMax, sum); + } + return sum; +} + +int maxSubarraySumCircular(int *nums, int numsSize) { + int k1, k2, total = 0; + k1 = helper(nums, numsSize); + for (int i = 0; i < numsSize; i++) { + total += nums[i]; + nums[i] *= -1; + } + k2 = helper(nums, numsSize); + int ans = total + k2; + return (ans > k1 && ans != 0) ? ans : k1; +} + +int main() { + int nums1[] = {1, -2, 3, -2}, nums2[] = {5, -3, 5}, nums3[] = {-3, -2, -3}; + printf("%d\n", maxSubarraySumCircular(nums1, 4)); // expect: 3 + printf("%d\n", maxSubarraySumCircular(nums2, 3)); // expect: 3 + printf("%d\n", maxSubarraySumCircular(nums3, 3)); // expect: 3 +} diff --git a/max_sum_circular_subarr.cpp b/max_sum_circular_subarr.cpp new file mode 100644 index 0000000..a86eafa --- /dev/null +++ b/max_sum_circular_subarr.cpp @@ -0,0 +1,49 @@ +// 918. Maximum Sum Circular Subarray +#include "leetcode.h" + +/* + * given: circular int array 'nums' of length 'n', return the max possible + * sum of non-empty subarray of 'nums' + * + * a circular array means the end of the array connects to the beginning. + * formally, the previous element of 'nums[i]' is 'nums[(i -/+ 1) % n]' + * + * a subarray may only include each element of the fixed buffer 'nums' at + * most once. formally, for a subarray 'nums[i], nums[i + 1], ..., nums[j]' + * there does not exist i <= k1, k2 <= j with k1 % n == k2 % n + */ + +class Solution { +public: + int maxSubarraySumCircular(vector<int> &nums) { + int sum = 0; + for (int i : nums) + sum += i; + int s1 = helper(nums.begin(), nums.end()); + for (int &i : nums) + i *= -1; + int s2 = sum + helper(nums.begin(), nums.end() - 1); + int s3 = sum + helper(nums.begin() + 1, nums.end()); + return max(s1, max(s2, s3)); + } + +private: + int helper(vector<int>::iterator p, vector<int>::iterator q) { + int res = INT_MIN, n = 0; + for (auto i = p; i != q; i++) { + n += *i; + res = max(res, n); + if (n < 0) + n = 0; + } + return res; + } +}; + +int main() { + Solution obj; + vector<int> nums1 = {-2}, nums2 = {5, -3, 5}, nums3 = {-3, -2, -3}; + cout << obj.maxSubarraySumCircular(nums1) << endl; // expect: 3 + cout << obj.maxSubarraySumCircular(nums2) << endl; // expect: 10 + cout << obj.maxSubarraySumCircular(nums3) << endl; // expect: -2 +} diff --git a/max_sum_rectangle.cpp b/max_sum_rectangle.cpp new file mode 100644 index 0000000..9b252e1 --- /dev/null +++ b/max_sum_rectangle.cpp @@ -0,0 +1,33 @@ +#include "leetcode.h" + +class Solution { +public: + int maxSumSubmatrix(vector<vector<int>> &matrix, int k) { + int ans = INT_MIN, rows = matrix.size(), cols = matrix[0].size(); + for (int l = 0; l < cols; ++l) { + vector<int> sums(rows); + for (int r = l; r < cols; ++r) { + int pMin = 0, pMax = INT_MIN; + for (int i = 0; i < rows; ++i) { + sums[i] += matrix[i][r]; + pMin = max(pMin + sums[i], sums[i]); + pMax = max(pMax, pMin); + } + if (pMax <= k) { + ans = max(ans, pMax); + continue; + } + set<int> s = {0}; + int runSum = 0; + for (int sum : sums) { + runSum += sum; + auto it = s.lower_bound(runSum - k); + if (it != end(s)) + ans = max(ans, runSum - *it); + s.insert(runSum); + } + } + } + return ans; + } +}; diff --git a/max_total_importance_road.c b/max_total_importance_road.c new file mode 100644 index 0000000..145c3e2 --- /dev/null +++ b/max_total_importance_road.c @@ -0,0 +1,29 @@ +// 2285. Maximum Total Importance of Roads +#include <stdio.h> +#include <stdlib.h> + +int cmp(const void *a, const void *b) { return (*(int *)a - *(int *)b); } + +long long maximumImportance(int n, int **roads, int roadsSize, + int *roadsColSize) { + long long ans = 0, *timeShown = calloc(n, sizeof(long long)); + for (int i = 0; i < roadsSize; i++) + for (int j = 0; j < 2; j++) + timeShown[roads[i][j]]++; + qsort(timeShown, n, sizeof(long long), cmp); + for (int i = n - 1; i >= 0; i--) + ans += timeShown[i] * (i + 1); + free(timeShown); + return ans; +} + +int main() { + int roads1[][2] = {{0, 1}, {1, 2}, {2, 3}, {0, 2}, {1, 3}, {2, 4}}, + roadsColSize1[] = {6}; + int roads2[][2] = {{0, 3}, {2, 4}, {1, 3}}, roadsColSize2[] = {3}; + printf("%llu\n", maximumImportance(5, roads1, 6, roadsColSize1)); // expect: + // 43 + printf("%llu\n", maximumImportance(5, roads1, 3, roadsColSize1)); // expect: + // 20 + return 0; +} diff --git a/max_tranfer_requests.c b/max_tranfer_requests.c new file mode 100644 index 0000000..3860d06 --- /dev/null +++ b/max_tranfer_requests.c @@ -0,0 +1,42 @@ +// 1601. Maximum Number of Achievable Trtmpfer Requests +#include <limits.h> +#include <math.h> +#include <stdlib.h> + +/* + * we have 'n' buildings numbered from 0 to 'n - 1'. each building has a number + * of employees. it's trtmpfer season and some employees want to change the + * building they reside in. you are an an array 'requests' where 'requests[i] = + * [fromi, toi]' represents an employee's request to trtmpfer from building + * 'fromi' to building 'toi'. all buildings are full. so a list of requests is + * achievable only if for each building, the net change in emplyee trtmpfers is + * zero. this metmp the number of emplyees leaving is equal to the number of + * employees moving in. return the maximum number of achievable requests + */ + +int tmp; + +int dfs(int idx, int **requests, int *building, int n) { + if (idx == tmp) { + for (int i = 0; i < n; i++) + if (building[i]) + return INT_MIN; + return 0; + } + int val1 = dfs(idx + 1, requests, building, n); + building[requests[idx][0]]--; + building[requests[idx][1]]++; + int val2 = dfs(idx + 1, requests, building, n) + 1; + building[requests[idx][0]]++; + building[requests[idx][1]]--; + return fmax(val1, val2); +} + +int maximumRequests(int n, int **requests, int requests_size, + int *requests_col_size) { + int *building = (int *)calloc(n + 1, sizeof(int)); + tmp = requests_size; + int ans = dfs(0, requests, building, n); + free(building); + return ans; +} diff --git a/max_tranfer_requests.cpp b/max_tranfer_requests.cpp new file mode 100644 index 0000000..c23f66b --- /dev/null +++ b/max_tranfer_requests.cpp @@ -0,0 +1,46 @@ +// 1601. Maximum Number of Achievable Transfer Requests +#include "leetcode.h" + +/* + * we have 'n' buildings numbered from 0 to 'n - 1'. each building has a number + * of employees. it's transfer season and some employees want to change the + * building they reside in. you are an an array 'requests' where 'requests[i] = + * [fromi, toi]' represents an employee's request to transfer from building + * 'fromi' to building 'toi'. all buildings are full. so a list of requests is + * achievable only if for each building, the net change in emplyee transfers is + * zero. this means the number of emplyees leaving is equal to the number of + * employees moving in. return the maximum number of achievable requests + */ + +class Solution { +public: + int maximumRequests(int n, vvd(int) & requests) { + int ans = 0, k = requests.size(), r = 1 << k, x; + for (int i = 1; i < r; i++) { + int *a = (int *)calloc(n, sizeof(int)); + int curr = 0; + for (int j = 0; j < k; j++) { + if (int(i >> j) & 1) { + a[requests[j][0]]++; + a[requests[j][1]]--; + curr++; + } + } + for (x = 0; x < n; x++) + if (a[x]) + break; + if (x == n) + ans = max(ans, curr); + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) r1 = {{0, 1}, {1, 0}, {0, 1}, {1, 2}, {2, 0}, {3, 4}}; + vvd(int) r2 = {{0, 0}, {1, 2}, {2, 1}}, r3 = {{0, 3}, {3, 1}, {1, 2}, {2, 0}}; + printf("%d\n", obj.maximumRequests(5, r1)); // expect: 5 + printf("%d\n", obj.maximumRequests(3, r2)); // expect: 3 + printf("%d\n", obj.maximumRequests(4, r3)); // expect: 4 +} diff --git a/max_twin_sum_list.c b/max_twin_sum_list.c new file mode 100644 index 0000000..c63f245 --- /dev/null +++ b/max_twin_sum_list.c @@ -0,0 +1,32 @@ +// 2130. Maximum Twin Sum of a Linked List +#include <stdlib.h> + +/* + * in a linked-list of size 'n', where 'n' is even, the i'th node (0-indexed) of + * the linked list is known as the twin of the 'n - 1 - i' node, if 0 <= i <= (n + * / 2) - 1. for example, if 'n = 4', then node 0 is the twin of node 3, and + * node 1 is the twin node of node 2. these are the only nodes with twins for 'n + * = 4'. the twin sum is defined as the sum of a node and its twin. given the + * 'head' of a linked list with even length, return the maximum twin sum of the + * linked list. + * + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +int pairSum(struct ListNode *head) { + int arr[100001], i = 0, j; + while (head) { + arr[i++] = head->val; + head = head->next; + } + i--; + int max = -1; + for (int j = 0; j <= i / 2; j++) + if (arr[j] + arr[i - j] > max) + max = arr[j] + arr[i - j]; + return max; +} diff --git a/max_twin_sum_list.cpp b/max_twin_sum_list.cpp new file mode 100644 index 0000000..dd635e1 --- /dev/null +++ b/max_twin_sum_list.cpp @@ -0,0 +1,41 @@ +// 2130. Maximum Twin Sum of a Linked List +#include "leetcode.h" + +/* + * in a linked-list of size 'n', where 'n' is even, the i'th node (0-indexed) of + * the linked list is known as the twin of the 'n - 1 - i' node, if 0 <= i <= (n + * / 2) - 1. for example, if 'n = 4', then node 0 is the twin of node 3, and + * node 1 is the twin node of node 2. these are the only nodes with twins for 'n + * = 4'. the twin sum is defined as the sum of a node and its twin. given the + * 'head' of a linked list with even length, return the maximum twin sum of the + * linked list. + * + */ + +class Solution { +public: + int pairSum(ListNode *head) { + int ans = 0; + auto slow = head, fast = head; + while (fast != nullptr && fast->next != nullptr) { + fast = fast->next->next; + slow = slow->next; + } + slow = reverseList(slow); + while (slow != nullptr) { + ans = max(ans, slow->val + head->val); + slow = slow->next; + head = head->next; + } + return ans; + } + +private: + ListNode *reverseList(ListNode *curr, ListNode *prev = nullptr) { + while (curr != nullptr) { + swap(curr->next, prev); + swap(prev != nullptr ? prev->next : prev, curr); + } + return prev; + } +}; diff --git a/max_units_truck.cpp b/max_units_truck.cpp new file mode 100644 index 0000000..f95e777 --- /dev/null +++ b/max_units_truck.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + int maximumUnits(vector<vector<int>> &boxTypes, int truckSize) { + sort(boxTypes.begin(), boxTypes.end(), cmp); + int ans = 0; + for (auto box : boxTypes) { + int n = min(box[0], truckSize); + ans += (n * box[1]); + truckSize -= n; + if (!truckSize) + break; + } + return ans; + } + +private: + static bool cmp(vector<int> &a, vector<int> &b) { return a[1] > b[1]; } +}; diff --git a/max_val_k_coin_pile.cpp b/max_val_k_coin_pile.cpp new file mode 100644 index 0000000..6df457a --- /dev/null +++ b/max_val_k_coin_pile.cpp @@ -0,0 +1,42 @@ +// 2218. Maximum Value of K Coins From Piles +#include "leetcode.h" + +/* + * there are 'n' piles of coins on a table. each pile consists of a positive + * number of coins of assorted denominations. in one move you can choose any + * coin on top of a pile remove it and add it to your wallet. given a list of + * 'piles' where 'piles[i]' is a list of integers denoting the composition of + * the i'th pile from top to bottom, and a positive integer 'k', return the + * maximum total values of coins you can have in your wallet if you choose + * exactly 'k' coins optimally. + */ + +class Solution { +public: + int maxValueOfCoins(vvd(int) & piles, int k) { + int n = piles.size(), m[1001][2001] = {}; + memset(m, -1, sizeof(m)); + function<int(int, int)> dp = [&](int i, int j) { + if (m[i][j] != -1) + return m[i][j]; + if (i == n) + return 0; + int ans = dp(i + 1, j), sum = 0; + for (int k = 1; k <= j && k <= piles[i].size(); ++k) { + sum += piles[i][k - 1]; + ans = max(ans, dp(i + 1, j - k) + sum); + } + return m[i][j] = ans; + }; + return dp(0, k); + } +}; + +int main() { + Solution obj; + vvd(int) + p1 = {{1, 100, 3}, {7, 8, 9}}, + p2 = {{100}, {100}, {100}, {100}, {100}, {100}, {1, 1, 1, 1, 1, 1, 700}}; + printf("%d\n", obj.maxValueOfCoins(p1, 2)); // expect: 101 + printf("%d\n", obj.maxValueOfCoins(p2, 7)); // expect: 706 +} diff --git a/max_value_give_idx.c b/max_value_give_idx.c new file mode 100644 index 0000000..da181b9 --- /dev/null +++ b/max_value_give_idx.c @@ -0,0 +1,51 @@ +// 1802. Maximum Value at a Given Index in a Bounded Array +#include <stdio.h> + +/* + * given three positive integers: 'n, index, and max_sum'. you want to construct + * an array 'nums' (0-indexed) that satisfies the following conditions: + * - nums.length == n + * - nums[i] is a positive integer where 0 <= i < n + * - abs(nums[i] - nums[i + 1]) <= 1 where 0 <= i < n - 1 + * - the sum of all the elements of 'nums' does not exceed 'max_sum' + * - nums[index] is maximised + * return 'nums[index]' of the constructed array. note that 'abs(x)' equals 'x' + * if 'x >= 0' and '-x' otherwise + */ + +int maxValue(int n, int index, int max_sum) { + long long sum; + int cnl = index, cnr = n - cnl - 1; + int left = 1, right = max_sum, mid; + while (left < right) { + sum = 0; + mid = right - (right - left) / 2; + if (cnl) { + if (mid > cnl) + sum += ((long long)((mid - 1) + (mid - cnl)) * cnl / 2); + else { + sum += ((long long)((mid - 1) + 1) * (mid - 1) / 2); + sum += (cnl - (mid - 1)); + } + } + if (cnr) { + if (mid > cnr) + sum += ((long long)((mid - 1) + (mid - cnr)) * cnr / 2); + else { + sum += ((long long)((mid - 1) + 1) * (mid - 1) / 2); + sum += (cnr - (mid - 1)); + } + } + sum += mid; + if (sum <= max_sum) + left = mid; + else + right = mid - 1; + } + return left; +} + +int main() { + printf("%d\n", maxValue(4, 2, 6)); // expect: 2 + printf("%d\n", maxValue(6, 1, 10)); // expect: 3 +} diff --git a/max_value_give_idx.cpp b/max_value_give_idx.cpp new file mode 100644 index 0000000..ee6c25f --- /dev/null +++ b/max_value_give_idx.cpp @@ -0,0 +1,43 @@ +// 1802. Maximum Value at a Given Index in a Bounded Array +#include "leetcode.h" + +/* + * given three positive integers: 'n, index, and max_sum'. you want to construct + * an array 'nums' (0-indexed) that satisfies the following conditions: + * - nums.length == n + * - nums[i] is a positive integer where 0 <= i < n + * - abs(nums[i] - nums[i + 1]) <= 1 where 0 <= i < n - 1 + * - the sum of all the elements of 'nums' does not exceed 'max_sum' + * - nums[index] is maximised + * return 'nums[index]' of the constructed array. note that 'abs(x)' equals 'x' + * if 'x >= 0' and '-x' otherwise + */ + +class Solution { + bool check(int n, int i, int max_sum, int m) { + for (int d = 1; max_sum >= 0 && d < m && i + d < n; ++d) + max_sum -= m - d; + for (int d = 1; max_sum >= 0 && d < m && i - d >= 0; ++d) + max_sum -= m - d; + return max_sum >= 0; + } + +public: + int maxValue(int n, int index, int max_sum) { + int left = 0, right = max_sum; + while (left < right) { + int mid = (left + right + 1) / 2; + if (check(n, index, max_sum - n - mid, mid)) + left = mid; + else + right = mid - 1; + } + return left + 1; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.maxValue(4, 2, 6)); // expect: 2 + printf("%d\n", obj.maxValue(6, 1, 10)); // expect: 3 +} diff --git a/max_width_binary_tree.c b/max_width_binary_tree.c new file mode 100644 index 0000000..0853205 --- /dev/null +++ b/max_width_binary_tree.c @@ -0,0 +1,104 @@ +// 662. Maximum Width of Binary Tree +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given 'root' of binary tree, return the maximum width of the + * given tree. the maximum width of a tree is the maximum width + * among all levels. the width of one level is defined as the + * length between the end-nodes (the leftmost and rightmost non + * null nodes), where the null nodes between the end-nodes that + * would be present in a complete binary tree extending down to + * that level are also counted into the length calculation. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +typedef enum { + QUEUELINK_OK, + QUEUELINK_EMPTY, + QUEUELINK_FULL, + QUEUELINK_ERROR = 0xFF +} queue_link; + +#define QUEUELINK_DEFINE(type) \ + typedef struct _queuelink_node_##type##_t { \ + struct _queuelink_node_##type##_t *next; \ + type value; \ + } queuelink_node_##type##_t; \ + typedef struct _queuelink_struct##type##_t { \ + queuelink_node_##type##_t *head; \ + queuelink_node_##type##_t *tail; \ + int count; \ + } queuelink_##type##_t; \ + queuelink_er_em offer_queuelink_##type(queuelink_##type##_t *queuelink, \ + type *tdata) { \ + if (tdata == NULL) \ + return QUEUELINK_ERROR; \ + queuelink_node_##type##_t *node = (queuelink_node_##type##_t *)malloc( \ + sizeof(queuelink_node_##type##_t)); \ + node->next = NULL; \ + memcpy(&node->value, tdata, sizeof(type)); \ + if (queuelink->head == NULL) { \ + queuelink->head = node; \ + queuelink->tail = node; \ + } else { \ + queuelink->tail->next = node; \ + queuelink->tail = node; \ + } \ + queuelink->count++; \ + return QUEUELINK_OK; \ + } \ + queuelink_er_em poll_queuelink_##type(queuelink_##type##_t *queuelink, \ + type *rdata) { \ + if (queuelink->head == NULL) \ + return QUEUELINK_EMPTY; \ + memcpy(rdata, &queuelink->head->value, sizeof(type)); \ + queuelink_node_##type##_t *tmp = queuelink->head; \ + queuelink->head = queuelink->head->next; \ + free(tmp); \ + queuelink->count--; \ + return QUEUELINK_OK; \ + } \ + inline int get_queuelink_size_##type(queuelink_##type##_t *queuelink_) { \ + return queuelink_->count; \ + } + +typedef struct TreeNode node_data; +QUEUELINK_DEFINE(node_data); + +int widthOfBinaryTree(struct TreeNode *root) { + queuelink_node_data_t q = {.head = NULL, .tail = NULL, .count = 0}; + offer_queuelink_node_data(&q, root); + long left = 0, right = 0; + node_data tmp; + int ans = 0; + while (1) { + int counts = get_queuelink_size_node_data(&q); + if (!counts) + break; + for (int i = 0; i < counts; i++) { + poll_queuelink_node_data(&q, &tmp); + if (!i) + left = tmp.val; + right = tmp.val; + if (tmp.left != NULL) { + tmp.left->val = tmp.val * 2L; + offer_queuelink_node_data(&q, tmp.left); + } + if (tmp.right != NULL) { + tmp.right->val = tmp.val * 2L + 1; + offer_queuelink_node_data(&q, tmp.right); + } + int tmp_ans = right - left + 1; + if (ans < tmp_ans) + ans = tmp_ans; + } + } + return ans; +} diff --git a/max_width_binary_tree.cpp b/max_width_binary_tree.cpp new file mode 100644 index 0000000..3f69177 --- /dev/null +++ b/max_width_binary_tree.cpp @@ -0,0 +1,40 @@ +// 662. Maximum Width of Binary Tree +#include "leetcode.h" + +/* + * given 'root' of binary tree, return the maximum width of the + * given tree. the maximum width of a tree is the maximum width + * among all levels. the width of one level is defined as the + * length between the end-nodes (the leftmost and rightmost non + * null nodes), where the null nodes between the end-nodes that + * would be present in a complete binary tree extending down to + * that level are also counted into the length calculation. + */ + +class Solution { +public: + int widthOfBinaryTree(TreeNode *root) { + if (root == NULL) + return 0; + int max_width = 1; + queue<pair<TreeNode *, int>> qp; + qp.push({root, 0}); + while (!qp.empty()) { + int level_size = qp.size(); + int start_idx = qp.front().second; + int end_idx = qp.back().second; + max_width = max(max_width, end_idx - start_idx + 1); + for (int i = 0; i < level_size; ++i) { + auto node_idx_pair = qp.front(); + TreeNode *node = node_idx_pair.first; + int node_idx = node_idx_pair.second - start_idx; + qp.pop(); + if (node->left != nullptr) + qp.push({node->left, 2LL * node_idx + 1}); + if (node->right != nullptr) + qp.push({node->right, 2LL * node_idx + 2}); + } + } + return max_width; + } +}; diff --git a/max_xor_after_op.c b/max_xor_after_op.c new file mode 100644 index 0000000..8b7a46a --- /dev/null +++ b/max_xor_after_op.c @@ -0,0 +1,26 @@ +// 2317. Maximum XOR After Operations +#include "leetcode.h" + +/* + * given a 0-indexed integer array 'nums'. in one operations, select any + * non-negative integer 'x' and an index 'i' then update 'nums[i]' to be equal + * to 'nums[i] & (nums[i] ^ x)'. return the maximum possible bitwsie xor of all + * elements after applying the operation any number of times. + */ + +int maximumXOR(int *nums, int numsSize) { + int ans = 0; + for (int i = 0; i < numsSize; i++) + // 0 | 3 = 3 + // 3 | 2 = 3 + // 3 | 4 = 7 + // 7 | 6 = 7 + ans |= nums[i]; + return ans; +} + +int main() { + int n1[] = {3, 2, 4, 6}, n2[] = {1, 2, 3, 9, 2}; + printf("%d\n", maximumXOR(n1, ARRAY_SIZE(n1))); // expect: 7 + printf("%d\n", maximumXOR(n2, ARRAY_SIZE(n2))); // expect: 11 +} diff --git a/max_xor_after_op.py b/max_xor_after_op.py new file mode 100644 index 0000000..416bbaa --- /dev/null +++ b/max_xor_after_op.py @@ -0,0 +1,25 @@ +# 2317. Maximum XOR After Operations + +""" +given a 0-indexed integer array 'nums'. in one operations, select any +non-negative integer 'x' and an index 'i' then update 'nums[i]' to be equal +to 'nums[i] & (nums[i] ^ x)'. return the maximum possible bitwsie xor of all +elements after applying the operation any number of times. +""" + +class Solution(object): + def maximumXOR(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + ans = 0 + for i in range(len(nums)): + ans |= nums[i] + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.maximumXOR([3,2,4,6])) # expect: 7 + print(obj.maximumXOR([1,2,3,9,2])) # expect: 11 diff --git a/maximal_rectangle.c b/maximal_rectangle.c new file mode 100644 index 0000000..a1b4b27 --- /dev/null +++ b/maximal_rectangle.c @@ -0,0 +1,62 @@ +// 85. Maximal Rectangle +#include "leetcode.h" + +/* + * given a 'rows * cols' binary 'matrix' filled with 0's and 1's, find the + * largest rectangle containing only 1's and return its area. + */ + +int max_area(int *heights, int heights_size) { + int *stack = (int *)malloc(heights_size * sizeof(int)); + int depth = 0, width = 0, res = 0, i = 0, tmp = 0; + if (!heights || !heights_size) + return 0; + while (i < heights_size) { + if (!depth || heights[i] >= heights[stack[depth - 1]]) { + stack[depth] = i; + depth++, i++; + } else { + while (depth && heights[stack[depth - 1]] > heights[i]) { + width = depth > 1 ? i - stack[depth - 2] - 1 : i; + tmp = heights[stack[depth - 1]] * width; + if (res < tmp) + res = tmp; + depth--; + } + } + } + while (depth) { + width = depth > 1 ? i - stack[depth - 2] - 1 : i; + tmp = heights[stack[depth - 1]] * width; + if (res < tmp) + res = tmp; + depth--; + } + free(stack); + return res; +} + +int maximalRectangle(char **matrix, int matrix_size, int *matrix_col_size) { + int *heights = (int *)calloc(*matrix_col_size, sizeof(int)); + int ans = 0; + if (!matrix || !matrix_size) + return 0; + for (int i = 0; i < matrix_size; i++) { + for (int j = 0; j < *matrix_col_size; j++) + heights[j] = matrix[i][j] == '0' ? 0 : heights[j] + 1; + int tmp = max_area(heights, *matrix_col_size); + if (ans < tmp) + ans = tmp; + } + free(heights); + return ans; +} + +int main() { + char *matrix[4][5] = {{"1", "0", "1", "0", "0"}, + {"1", "0", "1", "1", "1"}, + {"1", "1", "1", "1", "1"}, + {"1", "0", "0", "1", "0"}}; + int matrix_col_size = 5; + printf("%d\n", maximalRectangle((char **)matrix, 4, &matrix_col_size)); +} diff --git a/maximal_rectangle.py b/maximal_rectangle.py new file mode 100644 index 0000000..5e18d0c --- /dev/null +++ b/maximal_rectangle.py @@ -0,0 +1,44 @@ +# 85. Maximal Rectangle + +""" +given a 'rows * cols' binary 'matrix' filled with 0's and 1's, find the +largest rectangle containing only 1's and return its area. +""" + + +class Solution(object): + def maximalRectangle(self, matrix): + """ + :type matrix: List[List[str]] + :rtype: int + """ + if not matrix or not matrix[0]: + return 0 + n = len(matrix[0]) + height = [0] * (n + 1) + ans = 0 + for row in matrix: + for i in range(n): + height[i] = height[i] + 1 if row[i] == "1" else 0 + stack = [-1] + for i in range(n + 1): + while height[i] < height[stack[-1]]: + h = height[stack.pop()] + w = i - 1 - stack[-1] + ans = max(ans, h * w) + stack.append(i) + return ans + + +if __name__ == "__main__": + obj = Solution() + print( + obj.maximalRectangle( + matrix=[ + ["1", "0", "1", "0", "0"], + ["1", "0", "1", "1", "1"], + ["1", "1", "1", "1", "1"], + ["1", "0", "0", "1", "0"], + ] + ) + ) diff --git a/maximise_confusion_exam.c b/maximise_confusion_exam.c new file mode 100644 index 0000000..10ff638 --- /dev/null +++ b/maximise_confusion_exam.c @@ -0,0 +1,45 @@ +// 2024. Maximize the Confusion of an Exam +#include <math.h> +#include <stdio.h> +#include <string.h> + +/* + * a teacher is writing a test with 'n' true/false questions. with 'T' denoting + * true, and 'F' denoting false. he wants to confuse the students by maximising + * the number of consecutive questions with the same answer (multiple trues or + * multiple falses in a row) you are given a string 'answer_key', where + * 'answer_key[i]' is the original answer to the i'th question. in addition, you + * are given an integer 'k', the following operation: + * - change the answer key for any question to 'T' or 'F' + * return the maximum number of consecutive 'T's or 'F's in the answer key after + * performing the operation at most 'k' times + */ + +int maxConsecutiveAnswers(char *answer_key, int k) { + int n = strlen(answer_key), left = 0, right = 0, t = 0, f = 0, ans = 0; + while (right < n) { + if (answer_key[right] == 'T') { + t++; + ans = fmax(ans, t); + } else { + f++; + ans = fmax(ans, f); + } + right++; + if ((right - left) > ans + k) { + if (answer_key[left] == 'T') + t--; + else + f--; + left++; + } + } + return right - left; +} + +int main() { + char ak1[] = {"TTFF"}, ak2[] = {"TFFT"}, ak3[] = {"TTFTTFTT"}; + printf("%d\n", maxConsecutiveAnswers(ak1, 2)); // expect: 4 + printf("%d\n", maxConsecutiveAnswers(ak2, 1)); // expect: 3 + printf("%d\n", maxConsecutiveAnswers(ak3, 1)); // expect: 5 +} diff --git a/maximise_confusion_exam.cpp b/maximise_confusion_exam.cpp new file mode 100644 index 0000000..0de5eaf --- /dev/null +++ b/maximise_confusion_exam.cpp @@ -0,0 +1,41 @@ +// 2024. Maximize the Confusion of an Exam +#include "leetcode.h" + +/* + * a teacher is writing a test with 'n' true/false questions. with 'T' denoting + * true, and 'F' denoting false. he wants to confuse the students by maximising + * the number of consecutive questions with the same answer (multiple trues or + * multiple falses in a row) you are given a string 'answer_key', where + * 'answer_key[i]' is the original answer to the i'th question. in addition, you + * are given an integer 'k', the following operation: + * - change the answer key for any question to 'T' or 'F' + * return the maximum number of consecutive 'T's or 'F's in the answer key after + * performing the operation at most 'k' times + */ + +class Solution { +public: + int maxConsecutiveAnswers(string answer_key, int k) { + int n = answer_key.size(), start = 0, end = 0, t = 0, f = 0, ans = 0; + while (end < n) { + t += (answer_key[end] == 'T'); + f += (answer_key[end] == 'F'); + while (t > k && f > k) { + if (answer_key[start] == 'T') + t--; + else + f--; + } + ans = max(ans, end - start + 1); + end++; + } + return ans; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.maxConsecutiveAnswers("TTFF", 2)); // expect: 4 + printf("%d\n", obj.maxConsecutiveAnswers("TFFT", 1)); // expect: 3 + printf("%d\n", obj.maxConsecutiveAnswers("TTFTTFTT", 1)); // expect: 5 +} diff --git a/maximise_happiness_children.c b/maximise_happiness_children.c new file mode 100644 index 0000000..4199189 --- /dev/null +++ b/maximise_happiness_children.c @@ -0,0 +1,32 @@ +// 3075. Maximize Happiness of Selected Children +#include "leetcode.h" + +/* + * given an array 'happiness' of length 'n' and a positive integer 'k'. there + * are 'n' children standing in a queue where the i'th child has happiness value + * 'happiness[i]'. you want to select 'k' children from these 'n' children in + * 'k' turns. in each turn you select a child the happiness value of all the + * children that have not been selected till now decreases by one. note that the + * happiness value cannot become negative and decremented only if it is + * positive. return the maximum sum of the happiness values of the selected + * children you can achieve by selecting 'k' children. + */ + +int cmp(const void *a, const void *b) { return *(int *)b - *(int *)a; } + +long long maximumHappinessSum(int *happiness, int happinessSize, int k) { + long long ans = 0, sub = 0; + qsort(happiness, happinessSize, sizeof(int), cmp); + for (int i = 0; i < happinessSize && k; i++, k--) { + ans += happiness[i] - sub < 0 ? 0 : happiness[i] - sub; + sub++; + } + return ans; +} + +int main() { + int h1[] = {1, 2, 3}, h2[] = {1, 1, 1, 1}, h3[] = {2, 3, 4, 5}; + printf("%lld\n", maximumHappinessSum(h1, ARRAY_SIZE(h1), 2)); // expect: 4 + printf("%lld\n", maximumHappinessSum(h2, ARRAY_SIZE(h2), 2)); // expect: 1 + printf("%lld\n", maximumHappinessSum(h3, ARRAY_SIZE(h3), 1)); // expect: 5 +} diff --git a/maximise_happiness_children.py b/maximise_happiness_children.py new file mode 100644 index 0000000..6b2c5fe --- /dev/null +++ b/maximise_happiness_children.py @@ -0,0 +1,36 @@ +# 3075. Maximize Happiness of Selected Children + +""" +given an array 'happiness' of length 'n' and a positive integer 'k'. there +are 'n' children standing in a queue where the i'th child has happiness value +'happiness[i]'. you want to select 'k' children from these 'n' children in +'k' turns. in each turn you select a child the happiness value of all the +children that have not been selected till now decreases by one. note that the +happiness value cannot become negative and decremented only if it is +positive. return the maximum sum of the happiness values of the selected +children you can achieve by selecting 'k' children. +""" + + +class Solution(object): + def maximumHappinessSum(self, happiness, k): + """ + :type happiness: List[int] + :type k: int + :rtype: int + """ + happiness.sort(reverse=True) + i, ans = 0, 0 + while k: + happiness[i] = max(happiness[i] - i, 0) + ans += happiness[i] + i += 1 + k -= 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.maximumHappinessSum(happiness=[1, 2, 3], k=2)) + print(obj.maximumHappinessSum(happiness=[1, 1, 1, 1], k=2)) + print(obj.maximumHappinessSum(happiness=[2, 3, 4, 5], k=1)) diff --git a/maximise_num_div.c b/maximise_num_div.c new file mode 100644 index 0000000..66ecab3 --- /dev/null +++ b/maximise_num_div.c @@ -0,0 +1,38 @@ +// 1808. Maximize Number of Nice Divisors +#include <stdio.h> + +/* + * you are given a positive integer 'prime_factors'. you are asked to construct + * a positive integer 'n' that satisfies the following conditions. + * - the number of prime factors of 'n' (not necessarily distinct) is at most + * 'prime_factors' + * - the number of nice divisors of 'n' is maximised. note that a divisor of 'n' + * nice if it is divisible by every prime factor of 'n'. for example if 'n = + * 12', then its prime factors are '[2,2,3]', then '6' and '12' are nice + * divisors, while '3' and '4' are not. return the number of nice divisors of + * 'n'. since that number can be too large, return it modulo 10e9+7. note that a + * prime number is a natural number greater than 1 that is not a product of two + * smaller natural numbers. the prime factors of a number 'n' is a list of prime + * numbers such that their product equals 'n' + */ + +long modpow(long base, int exp, int mod) { + long res = 1; + for (; exp; exp >>= 1) { + res *= (exp & 1 ? base : 1) % mod; + base *= (base % mod); + } + return res; +} + +int maxNiceDivisors(int prime_factors) { + int st[6] = {1, 2, 3, 4, 5, 6}, mod = 1e9 + 7; + return prime_factors < 6 ? st[prime_factors] + : st[3 + prime_factors % 3] * + modpow(3, prime_factors / 3 - 1, mod) % mod; +} + +int main() { + printf("%d\n", maxNiceDivisors(5)); // expect: 6 + printf("%d\n", maxNiceDivisors(8)); // expect: 18 +} diff --git a/maximise_num_div.py b/maximise_num_div.py new file mode 100644 index 0000000..225ac83 --- /dev/null +++ b/maximise_num_div.py @@ -0,0 +1,34 @@ +# 1808. Maximize Number of Nice Divisors + +""" +you are given a positive integer 'prime_factors'. you are asked to construct +a positive integer 'n' that satisfies the following conditions. +- the number of prime factors of 'n' (not necessarily distinct) is at most +'prime_factors' +- the number of nice divisors of 'n' is maximised. note that a divisor of 'n' +nice if it is divisible by every prime factor of 'n'. for example if 'n = +12', then its prime factors are '[2,2,3]', then '6' and '12' are nice +divisors, while '3' and '4' are not. return the number of nice divisors of +'n'. since that number can be too large, return it modulo 10e9+7. note that a +prime number is a natural number greater than 1 that is not a product of two +smaller natural numbers. the prime factors of a number 'n' is a list of prime +numbers such that their product equals 'n' +""" + + +class Solution(object): + def maxNiceDivisors(self, n): + m = 10*9 + 7 + if n <= 3: + return n + if n % 3 == 0: + return pow(3, n // 3, m) + if n % 3 == 1: + return (pow(3, (n - 4) // 3, m) * 4) % m + return (2 * pow(3, n // 3)) % m + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxNiceDivisors(5)) # expect: 6 + print(obj.maxNiceDivisors(8)) # expect: 18 diff --git a/mean_arr_remove_element.c b/mean_arr_remove_element.c new file mode 100644 index 0000000..7976389 --- /dev/null +++ b/mean_arr_remove_element.c @@ -0,0 +1,32 @@ +// 1619. Mean of Array After Removing Some Elements +#include "leetcode.h" + +/* + * givn an integer array 'arr', return the mean of the remaining integers after + * removing the smallest 5% and the largest 5% of the elements. answers within + * 10^-5 of the actual answer will be considered accepted. + */ + +int cmp(const void *a, const void *b) { return (*(int *)a - *(int *)b); } + +double trimMean(int *arr, int arrSize) { + double ans = 0; + int perc = (arrSize * 5) / 500, k = 0; + qsort(arr, arrSize, sizeof(int), cmp); + for (int i = perc; i < arrSize - perc; i++) { + ans += arr[i]; + k++; + } + ans /= k; + return ans; +} + +int main() { + int a1[] = {1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3}, + a2[] = {6, 2, 7, 5, 1, 2, 0, 3, 10, 2, 5, 0, 5, 5, 0, 8, 7, 6, 8, 0}, + a3[] = {6, 0, 7, 0, 7, 5, 7, 8, 3, 4, 0, 7, 8, 1, 6, 8, 1, 1, 2, 4, + 8, 1, 9, 5, 4, 3, 8, 5, 10, 8, 6, 6, 1, 0, 6, 10, 8, 2, 3, 4}; + printf("%f\n", trimMean(a1, ARRAY_SIZE(a1))); // expect: 2.0000 + printf("%f\n", trimMean(a2, ARRAY_SIZE(a2))); // expect: 4.0000 + printf("%f\n", trimMean(a3, ARRAY_SIZE(a3))); // expect: 4.7778 +} diff --git a/mean_arr_remove_element.py b/mean_arr_remove_element.py new file mode 100644 index 0000000..40b77a0 --- /dev/null +++ b/mean_arr_remove_element.py @@ -0,0 +1,75 @@ +# 1619. Mean of Array After Removing Some Elements +import statistics + +""" +givn an integer array 'arr', return the mean of the remaining integers after +removing the smallest 5% and the largest 5% of the elements. answers within +10^-5 of the actual answer will be considered accepted. +""" + + +class Solution(object): + def trimMean(self, arr): + """ + :type arr: List[int] + :rtype: float + """ + arr.sort() + n = int(0.05 * len(arr)) + return statistics.mean(arr[n : len(arr) - n]) + + +if __name__ == "__main__": + obj = Solution() + print( + obj.trimMean(arr=[1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3]) + ) + print( + obj.trimMean( + arr=[ + 6, + 0, + 7, + 0, + 7, + 5, + 7, + 8, + 3, + 4, + 0, + 7, + 8, + 1, + 6, + 8, + 1, + 1, + 2, + 4, + 8, + 1, + 9, + 5, + 4, + 3, + 8, + 5, + 10, + 8, + 6, + 6, + 1, + 0, + 6, + 10, + 8, + 2, + 3, + 4, + ] + ) + ) + print( + obj.trimMean(arr=[6, 2, 7, 5, 1, 2, 0, 3, 10, 2, 5, 0, 5, 5, 0, 8, 7, 6, 8, 0]) + ) diff --git a/median_two_sorted_arr.c b/median_two_sorted_arr.c new file mode 100644 index 0000000..30dd2bc --- /dev/null +++ b/median_two_sorted_arr.c @@ -0,0 +1,42 @@ +// 4. Median of Two Sorted Arrays +#include <stdio.h> +#include <stdlib.h> + +/* + * given two sorted arrays 'nums1' and 'nums2' of size 'm' and 'n', respectively + * return the median of the two sorted arrays. the overall run time complexity + * should be 'O(log(m + n))' + */ + +double findMedianSortedArrays(int *nums1, int nums1_size, int *nums2, + int nums2_size) { + int n = nums1_size + nums2_size, i, j, k, a; + float f, nums3[n]; + i = j = k = 0; + while (i < nums1_size && j < nums2_size) { + if (nums1[i] < nums2[j]) + nums3[k++] = nums1[i++]; + else + nums3[k++] = nums2[j++]; + } + for (; i < nums1_size; i++) + nums3[k++] = nums1[i]; + for (; j < nums2_size; j++) + nums3[k++] = nums2[j]; + if (!(n % 2)) { + a = n / 2; + f = (nums3[a] + nums3[a - 1]) / 2; + return f; + } else { + f = nums3[n / 2]; + return f; + } + return -1; +} + +int main() { + int n11[] = {1, 3}, n21[] = {2}; + int n12[] = {1, 2}, n22[] = {3, 4}; + printf("%f\n", findMedianSortedArrays(n11, 2, n21, 1)); // expect: 2.00000 + printf("%f\n", findMedianSortedArrays(n12, 2, n22, 2)); // expect: 2.50000 +} diff --git a/median_two_sorted_arr.py b/median_two_sorted_arr.py new file mode 100644 index 0000000..3a57f77 --- /dev/null +++ b/median_two_sorted_arr.py @@ -0,0 +1,42 @@ +# 4. Median of Two Sorted Arrays + +""" +given two sorted arrays 'nums1' and 'nums2' of size 'm' and 'n', respectively +return the median of the two sorted arrays. the overall run time complexity +should be 'O(log(m + n))' +""" + + +class Solution(object): + def findMedianSortedArrays(self, nums1, nums2): + l = len(nums1) + len(nums2) + if l % 2 == 1: + return self.kth(nums1, nums2, l // 2) + else: + return ( + self.kth(nums1, nums2, l // 2) + self.kth(nums1, nums2, l // 2 - 1) + ) / 2.0 + + def kth(self, a, b, k): + if not a: + return b[k] + if not b: + return a[k] + ia, ib = len(a) // 2, len(b) // 2 + ma, mb = a[ia], b[ib] + if ia + ib < k: + if ma > mb: + return self.kth(a, b[ib + 1 :], k - ib - 1) + else: + return self.kth(a[i + 1 :], b, k - ia - 1) + else: + if ma > mb: + return self.kth(a[:ia], b, k) + else: + return self.kth(a, b[:ib], k) + + +if __name__ == "__main__": + obj = Solution() + print(obj.findMedianSortedArrays([1, 3], [2])) # expect: 2.00000 + print(obj.findMedianSortedArrays([1, 2], [3, 4])) # expect: 2.50000 diff --git a/meeting_rooms3.c b/meeting_rooms3.c new file mode 100644 index 0000000..462d84e --- /dev/null +++ b/meeting_rooms3.c @@ -0,0 +1,109 @@ +// 2402. Meeting Rooms III +#include "leetcode.h" + +/* + * you are given an integer 'n', there are 'n' rooms numbered 0 to 'n - 1'. + * guven a 2d integer array 'meetings', where 'meetings[i] = start[i], end[i]' + * means that a meeting will be held during the half closed time interval + * '[start[i], end[i]]'. all thevalues of 'start[i]' are unique. meetings are + * allocated to rooms in the following manner: each meeting will take place in + * the unused room with the lowest number. if there are no available rooms, the + * meeting will be delayed until a room becoms free. the dleayed meeting should + * have the same duration as the original meeting. when a room becoms unused, + * meetings that have an earlier original start time should be given the room, + * return the number of the room that held the most meetings. if there are + * multiple rooms, return the room with the lowest number. a half closed + * interval '[a, b)' is the interval between 'a' and 'b' including 'a' and not + * including 'b'. + */ + +void heapdown(int **room, int *heap, int heapsize) { + int curr = 1; + int child = curr << 1; + while (child <= heapsize) { + if (child + 1 <= heapsize && + room[heap[child + 1]][0] < room[heap[child]][0]) + child++; + if (room[heap[child]][0] >= room[heap[curr]][0]) + break; + heap[curr] ^= heap[child]; + heap[child] ^= heap[curr]; + heap[curr] ^= heap[child]; + curr = child; + child <<= 1; + } +} +void heapup(int **room, int *heap, int heapidx, int roomidx) { + int curr = heapidx; + int father = curr >> 1; + while (father >= 1) { + if (room[heap[father]][0] <= room[roomidx][0]) + break; + heap[curr] = heap[father]; + curr = father; + father >>= 1; + } + heap[curr] = roomidx; +} +int cmp(const void *a, const void *b) { + return (*(int **)a)[0] - (*(int **)b)[0]; +} +int mostBooked(int n, int **meetings, int meetingsSize, int *meetingsColSize) { + long long **room = malloc(n * sizeof(long long *)); + for (int i = 0; i < n; i++) { + room[i] = malloc(4 * sizeof(long long)); + room[i][0] = i; + room[i][1] = i; + room[i][2] = -1; + room[i][3] = 0; + } + qsort(meetings, meetingsSize, sizeof(meetings[0]), cmp); + int *nonbook = malloc((n + 1) * sizeof(int)); + int *booked = malloc((n + 1) * sizeof(int)); + int nonbookidx = 0; // 1~n + int bookidx = 0; // 1~n + for (int i = 0; i < n; i++) { + heapup(room, nonbook, i + 1, nonbookidx++); + } + for (int i = 0; i < meetingsSize; i++) { + long long poptime = meetings[i][0]; + int target = 0; + if (nonbookidx == 0) + poptime = fmax(poptime, room[booked[1]][0]); + // booked ->nonbooked + while (bookidx > 0 && room[booked[1]][0] <= poptime) { + target = booked[1]; + room[target][0] = room[target][1]; + heapup(room, nonbook, ++nonbookidx, target); + booked[1] = booked[bookidx--]; + heapdown(room, booked, bookidx); + } + // nonbooked ->booked + target = nonbook[1]; + room[target][2] = (room[target][2] <= meetings[i][0]) + ? meetings[i][1] + : room[target][2] + meetings[i][1] - meetings[i][0]; + room[target][3] += 1; + room[target][0] = room[target][2]; + heapup(room, booked, ++bookidx, target); + nonbook[1] = nonbook[nonbookidx--]; + heapdown(room, nonbook, nonbookidx); + } + int ans = 0; + int count = -1; + for (int i = 0; i < n; i++) { + if (room[i][3] > count) { + count = room[i][3]; + ans = i; + } + } + + return ans; +} + +int main() { + int m1[5][2] = {{0, 10}, {1, 5}, {2, 7}, {3, 4}}, + m2[5][2] = {{1, 20}, {2, 10}, {3, 5}, {4, 9}, {6, 8}}, *mcs1, *mcs2; + printf("%d\n", mostBooked(2, (int **)m1, 5, mcs1)); // expect: 0 + printf("%d\n", mostBooked(3, (int **)m2, 5, mcs2)); // expect: 1 +} diff --git a/meeting_rooms3.py b/meeting_rooms3.py new file mode 100644 index 0000000..7aa762f --- /dev/null +++ b/meeting_rooms3.py @@ -0,0 +1,48 @@ +# 2402. Meeting Rooms III + +""" +you are given an integer 'n', there are 'n' rooms numbered 0 to 'n - 1'. +guven a 2d integer array 'meetings', where 'meetings[i] = start[i], end[i]' +means that a meeting will be held during the half closed time interval +'[start[i], end[i]]'. all thevalues of 'start[i]' are unique. meetings are +allocated to rooms in the following manner: each meeting will take place in +the unused room with the lowest number. if there are no available rooms, the +meeting will be delayed until a room becoms free. the dleayed meeting should +have the same duration as the original meeting. when a room becoms unused, +meetings that have an earlier original start time should be given the room, +return the number of the room that held the most meetings. if there are +multiple rooms, return the room with the lowest number. a half closed +interval '[a, b)' is the interval between 'a' and 'b' including 'a' and not +including 'b'. +""" + + +class Solution(object): + def mostBooked(self, n, meetings): + """ + :type n: int + :type meetings: List[List[int]] + :rtype: int + """ + ready = [r for r in range(n)] + rooms = [] + heapify(ready) + ans = [0] * n + for s, e in sorted(meetings): + while rooms and rooms[0][0] <= s: + t, r = heappop(rooms) + heappush(ready, r) + if ready: + r = heappop(ready) + heappush(rooms, [e, r]) + else: + t, r = heappop(rooms) + heappush(rooms, [t + e - s, r]) + ans[r] += 1 + return ans.index(max(ans)) + + +if __name__ == "__main__": + obj = Solution() + print(obj.mostBooked(n=2, meetings=[[0, 10], [1, 5], [2, 7], [3, 4]])) + print(obj.mostBooked(n=3, meetings=[[1, 20], [2, 10], [3, 5], [4, 9], [6, 8]])) diff --git a/merge_between_linked_list.c b/merge_between_linked_list.c new file mode 100644 index 0000000..4115b20 --- /dev/null +++ b/merge_between_linked_list.c @@ -0,0 +1,40 @@ +// 1669. Merge In Between Linked Lists +#include "leetcode.h" + +/* + * given two linked lists 'l1' and 'l2' of sizes 'n' and 'm' respectively. + * remove 'l1' nodes from the a'th node to the b'th node, and put 'l2' in their + * place. the blue edges and nodes in the following figure indicate the result. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +struct ListNode *mergeInBetween(struct ListNode *list1, int a, int b, + struct ListNode *list2) { + struct ListNode *nodea = list1, *nodeb = list1; + int cnt = 0; + for (struct ListNode *node = list1; node; node = node->next) { + if (cnt == a - 1) + nodea = node; + if (cnt == b) { + nodeb = node->next; + break; + } + cnt++; + } + struct ListNode *tmp = list1; + bool is_change = false; + while (tmp) { + if (tmp == nodea) + tmp->next = list2; + if (!tmp->next && !is_change) { + tmp->next = nodeb; + is_change = true; + } + tmp = tmp->next; + } + return list1; +} diff --git a/merge_between_linked_list.py b/merge_between_linked_list.py new file mode 100644 index 0000000..4093a9f --- /dev/null +++ b/merge_between_linked_list.py @@ -0,0 +1,53 @@ +# 1669. Merge In Between Linked Lists + +""" +given two linked lists 'l1' and 'l2' of sizes 'n' and 'm' respectively. +remove 'l1' nodes from the a'th node to the b'th node, and put 'l2' in their +place. the blue edges and nodes in the following figure indicate the result. +""" + + +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, val=0, next=None): + self.val = val + self.next = next + + +class Solution(object): + def mergeInBetween(self, list1, a, b, list2): + """ + :type list1: ListNode + :type a: int + :type b: int + :type list2: ListNode + :rtype: ListNode + """ + start, end = None, list1 + for i in range(b): + if i == a - 1: + start = end + end = end.next + start.next = list2 + while list2.next: + list2 = list2.next + list2.next = end.next + end.next = None + return list1 + + +if __name__ == "__main__": + obj = Solution() + print( + obj.mergeInBetween( + list1=[10, 1, 13, 6, 9, 5], a=3, b=4, list2=[1000000, 1000001, 1000002] + ) + ) + print( + obj.mergeInBetween( + list1=[0, 1, 2, 3, 4, 5, 6], + a=2, + b=5, + list2=[1000000, 1000001, 1000002, 1000003, 1000004], + ) + ) diff --git a/merge_k_lists.cpp b/merge_k_lists.cpp new file mode 100644 index 0000000..375fb10 --- /dev/null +++ b/merge_k_lists.cpp @@ -0,0 +1,36 @@ +#include <bits/stdc++.h> +using namespace std; + +struct ListNode { + int val; + ListNode *next; + ListNode() : val(0), next(nullptr) {} + ListNode(int x) : val(x), next(nullptr) {} + ListNode(int x, ListNode *next) : val(x), next(next) {} +}; + +class Solution { +public: + ListNode *mergeKLists(vector<ListNode *> &lists) { + if (lists.size() == 0) + return NULL; + ListNode *head = lists[0]; + for (int i = 1; i < lists.size(); i++) + head = merge(head, lists[i]); + return head; + } + +private: + ListNode *merge(ListNode *list1, ListNode *list2) { + if (!list1) + return list2; + if (!list2) + return list1; + ListNode *head = list1->val <= list2->val ? list1 : list2; + head->next = list1->val <= list2->val ? merge(list1->next, list2) + : merge(list1, list2->next); + return head; + } +}; + +int main() {} diff --git a/merge_k_sorted_list.c b/merge_k_sorted_list.c new file mode 100644 index 0000000..b5f8ddc --- /dev/null +++ b/merge_k_sorted_list.c @@ -0,0 +1,47 @@ +// 23. Merge k Sorted Lists +#include <stddef.h> +#include <stdlib.h> + +struct ListNode { + int val; + struct ListNode *next; +}; + +struct ListNode *mergeKLists(struct ListNode **lists, int lists_size) { + if (lists_size == 0) + return NULL; + struct ListNode *head = malloc(sizeof(struct ListNode)); + struct ListNode *tmp = head, *min; + int id; + while (1) { + min = lists[0]; + id = 0; + for (int i = 1; i < lists_size; i++) { + if (min == NULL && lists[i]) { + min = lists[i]; + id = i; + } + if (lists[i] == NULL) + continue; + else { + if (lists[i]->val < min->val) { + min = lists[i]; + id = i; + } + } + } + if (min == NULL) { + tmp->next = NULL; + break; + } + tmp->next = min; + tmp = tmp->next; + lists[id] = lists[id]->next; + while (lists[id] && lists[id]->val == tmp->val) { + tmp->next = lists[id]; + tmp = tmp->next; + lists[id] = lists[id]->next; + } + } + return head->next; +} diff --git a/merge_lists.cpp b/merge_lists.cpp new file mode 100644 index 0000000..b57bf53 --- /dev/null +++ b/merge_lists.cpp @@ -0,0 +1,29 @@ +#include <bits/stdc++.h> +#include <cstddef> + +struct ListNode { + int val; + ListNode *next; + ListNode() : val(0), next(nullptr) {} + ListNode(int x) : val(x), next(nullptr) {} + ListNode(int x, ListNode *next) : val(x), next(next) {} +}; + +class Solution { +public: + ListNode *mergeTwoLists(ListNode *list1, ListNode *list2) { + if (list1 == NULL) + return list2; + if (list2 == NULL) + return list1; + if (list1->val <= list2->val) { + list1->next = mergeTwoLists(list1->next, list2); + return list1; + } else { + list2->next = mergeTwoLists(list1, list2->next); + return list2; + } + } +}; + +int main() {} diff --git a/merge_sorted_array.cpp b/merge_sorted_array.cpp new file mode 100644 index 0000000..6a98a38 --- /dev/null +++ b/merge_sorted_array.cpp @@ -0,0 +1,33 @@ +#include "leetcode.h" + +class Solution { +public: + void merge(vector<int> &nums1, int m, vector<int> &nums2, int n) { + int i = m - 1, j = n - 1, k = m + n - 1; + while (i >= 0 && j >= 0) { + if (nums1[i] > nums2[j]) + nums1[k--] = nums1[i--]; + else + nums1[k--] = nums2[j--]; + } + while (j >= 0) + nums1[k--] = nums2[j--]; + } +}; + +int main() { + Solution obj; + vector<int> nums1 = {1, 2, 3, 0, 0, 0}; + vector<int> nums2 = {2, 5, 6}; + int m = 3, n = 3; + cout << "nums1:\n"; + for (auto i : nums1) + cout << i; + cout << "\nnums2:\n"; + for (auto i : nums2) + cout << i; + obj.merge(nums1, m, nums2, n); + cout << "\nnums1 & nums2 merged:\n"; + for (auto i : nums1) + cout << i; +} diff --git a/merge_sorted_array.rs b/merge_sorted_array.rs new file mode 100644 index 0000000..1e2704d --- /dev/null +++ b/merge_sorted_array.rs @@ -0,0 +1,14 @@ +struct Solution; + +impl Solution { + pub fn merge(nums1: &mut Vec<i32>, m: i32, nums2: &mut Vec<i32>, n: i32) { + let (mut m ) + } +} + +fn main() { + let mut nums1 = vec![1,2,3,0,0,0]; + let mut nums2 = vec![2,5,6]; + let (m, n) = (3, 3); + Solution::merge(&mut nums1, m, &mut nums2, n); +} diff --git a/merge_string_alt.c b/merge_string_alt.c new file mode 100644 index 0000000..d69c5fc --- /dev/null +++ b/merge_string_alt.c @@ -0,0 +1,32 @@ +// 1768. Merge Strings Alternately +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given two strings 'word1' and 'word2', merge the strings by adding letters in + * alternating order, starting with 'word1'. if a string is longer than the + * other, append the additional letters onto the end of the merged string. + * return the merged string!! + */ + +char *mergeAlternately(char *word1, char *word2) { + char *ans = (char *)calloc(strlen(word1) + strlen(word2) + 1, sizeof(char)); + int i = 0, j = 0, k = 0; + while (i < strlen(word1) || j < strlen(word2)) { + if (i < strlen(word1)) + ans[k++] = word1[i++]; + if (j < strlen(word2)) + ans[k++] = word2[j++]; + } + return ans; +} + +int main() { + char w1[] = {"abc"}, w2[] = {"pqr"}, *ma1 = mergeAlternately(w1, w2); + char w3[] = {"ab"}, w4[] = {"pqrs"}, *ma2 = mergeAlternately(w3, w4); + char w5[] = {"abcd"}, w6[] = {"pq"}, *ma3 = mergeAlternately(w5, w6); + printf("%s\n", ma1); // expect: apbqcr + printf("%s\n", ma2); // expect: apbqrs + printf("%s\n", ma3); // expect: apbqcd +} diff --git a/merge_string_alt.cpp b/merge_string_alt.cpp new file mode 100644 index 0000000..d69c5fc --- /dev/null +++ b/merge_string_alt.cpp @@ -0,0 +1,32 @@ +// 1768. Merge Strings Alternately +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given two strings 'word1' and 'word2', merge the strings by adding letters in + * alternating order, starting with 'word1'. if a string is longer than the + * other, append the additional letters onto the end of the merged string. + * return the merged string!! + */ + +char *mergeAlternately(char *word1, char *word2) { + char *ans = (char *)calloc(strlen(word1) + strlen(word2) + 1, sizeof(char)); + int i = 0, j = 0, k = 0; + while (i < strlen(word1) || j < strlen(word2)) { + if (i < strlen(word1)) + ans[k++] = word1[i++]; + if (j < strlen(word2)) + ans[k++] = word2[j++]; + } + return ans; +} + +int main() { + char w1[] = {"abc"}, w2[] = {"pqr"}, *ma1 = mergeAlternately(w1, w2); + char w3[] = {"ab"}, w4[] = {"pqrs"}, *ma2 = mergeAlternately(w3, w4); + char w5[] = {"abcd"}, w6[] = {"pq"}, *ma3 = mergeAlternately(w5, w6); + printf("%s\n", ma1); // expect: apbqcr + printf("%s\n", ma2); // expect: apbqrs + printf("%s\n", ma3); // expect: apbqcd +} diff --git a/middle_linked_list.c b/middle_linked_list.c new file mode 100644 index 0000000..1284a23 --- /dev/null +++ b/middle_linked_list.c @@ -0,0 +1,23 @@ +// 876. Middle of the Linked List +#include "leetcode.h" + +/* + * given the head of a singly linked list, return the middle of the node of the + * linked list. if there are two middle nodes, return the second middle node. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +struct ListNode *middleNode(struct ListNode *head) { + struct ListNode *ans; + int c = 0, i; + for (ans = head; ans; ans = ans->next, c++) + ; + c /= 2; + for (i = 0, ans = head; i < c; ans = ans->next, i++) + ; + return ans; +} diff --git a/middle_linked_list.cpp b/middle_linked_list.cpp new file mode 100644 index 0000000..ba3a2a0 --- /dev/null +++ b/middle_linked_list.cpp @@ -0,0 +1,18 @@ +#include "leetcode.h" + +class Solution { +public: + ListNode *middleNode(ListNode *head) { + ListNode *tmp = head; + int len = 0; + while (tmp) { + len++; + tmp = tmp->next; + } + int mid = len / 2; + tmp = head; + while (tmp && mid--) + tmp = tmp->next; + return tmp; + } +}; diff --git a/middle_linked_list.py b/middle_linked_list.py new file mode 100644 index 0000000..d3c6762 --- /dev/null +++ b/middle_linked_list.py @@ -0,0 +1,26 @@ +# 876. Middle of the Linked List + +""" +given the head of a singly linked list, return the middle of the node of the +linked list. if there are two middle nodes, return the second middle node. +""" + +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, val=0, next=None): + self.val = val + self.next = next + +class Solution(object): + def middleNode(self, head): + """ + :type head: ListNode + :rtype: ListNode + """ + slow, fast = head, head + while fast: + fast = fast.next + if fast: + fast = fast.next + slow = slow.next + return slow diff --git a/middle_linked_list.rs b/middle_linked_list.rs new file mode 100644 index 0000000..ed84409 --- /dev/null +++ b/middle_linked_list.rs @@ -0,0 +1,28 @@ +#[derive(PartialEq, Eq, Clone, Debug)] +struct Solution; +pub struct ListNode { + pub val: i32, + pub next: Option<Box<ListNode>> +} + +impl ListNode { + #[inline] + fn new(val: i32) -> Self { + ListNode { + next: None, + val + } + } +} + +impl Solution { + pub fn middle_node(head: Option<Box<ListNode>>) -> Option<Box<ListNode>> { + let mut curr = &head; + let mut node_vec: Vec<Option<Box<ListNode>>> = vec![]; + while let Some(node) = curr.as_ref() { + node_vec.push(Some(node.clone())); + curr = &curr.as_ref().unwrap().next; + } + node_vec[node_vec.len() / 2].clone() + } +} diff --git a/min_abs_diff_bst.c b/min_abs_diff_bst.c new file mode 100644 index 0000000..ad3db74 --- /dev/null +++ b/min_abs_diff_bst.c @@ -0,0 +1,52 @@ +// 530. Minimum Absolute Difference in BST +#include <limits.h> +#include <stdlib.h> + +/* + * given the 'root' of a binary search tree (bst), return the minimum absolute + * difference between the values of any two different nodes in the tree + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +inline int min(int a, int b) { + if (a < b) + return a; + else + return b; +} + +void process(struct TreeNode *root, int *val) { + struct TreeNode *tmp; + if (root->left) { + tmp = root->left; + while (tmp->right) + tmp = tmp->right; + *val = min(*val, root->val - tmp->val); + if (*val == 1) + return; + process(root->left, val); + } + if (root->right) { + tmp = root->right; + while (tmp->left) + tmp = tmp->left; + *val = min(*val, tmp->val - root->val); + if (*val == 1) + return; + process(root->right, val); + } +} + +int getMinimumDifference(struct TreeNode *root) { + int *val = malloc(sizeof(int)); + *val = INT_MAX; + process(root, val); + int ans = *val; + free(val); + return ans; +} diff --git a/min_abs_diff_bst.cpp b/min_abs_diff_bst.cpp new file mode 100644 index 0000000..0c0ef82 --- /dev/null +++ b/min_abs_diff_bst.cpp @@ -0,0 +1,27 @@ +// 530. Minimum Absolute Difference in BST +#include "leetcode.h" + +/* + * given the 'root' of a binary search tree (bst), return the minimum absolute + * difference between the values of any two different nodes in the tree + */ + +class Solution { + int diff = INT_MAX; + TreeNode *prev = NULL; + void dfs(TreeNode *root) { + if (root->left) + dfs(root->left); + if (prev) + diff = min(diff, abs(prev->val - root->val)); + prev = root; + if (root->right) + dfs(root->right); + } + +public: + int getMinimumDifference(TreeNode *root) { + dfs(root); + return diff; + } +}; diff --git a/min_addition_beauty_int.c b/min_addition_beauty_int.c new file mode 100644 index 0000000..bd3b330 --- /dev/null +++ b/min_addition_beauty_int.c @@ -0,0 +1,48 @@ +// 2457. Minimum Addition to Make Integer Beautiful +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given: two positive integers 'n' & 'target' + * an integer is considered beautiful if the sum of its + * digits is less than or equal to the target. + * return minimum non-negative integer 'x' such that 'n + x' + * is beautiful. + */ + +long long makeIntegerBeautiful(long long n, int target) { + int *data = malloc(sizeof(int) * 64); + int digit = 0, idx = 0; + long long val = n, ans; + while (val) { + data[idx] = val % 10; + digit += data[idx]; + idx++; + val /= 10; + } + if (digit <= target) { + ans = 0; + goto exit; + } + digit = 0; + for (int i = idx - 1; i >= 0; i--) { + digit += data[i]; + if (digit >= target) { + long long tmp = 0; + for (int j = i; j >= 0; j--) + tmp = tmp * 10 + data[j]; + ans = pow(10, i + 1) - tmp; + break; + } + } +exit: + free(data); + return ans; +} + +int main() { + printf("%llu\n", makeIntegerBeautiful(16, 6)); // expect: 4 + printf("%llu\n", makeIntegerBeautiful(467, 6)); // expect: 33 + printf("%llu\n", makeIntegerBeautiful(1, 1)); // expect: 0 +} diff --git a/min_ascii_strs.c b/min_ascii_strs.c new file mode 100644 index 0000000..b5a64f8 --- /dev/null +++ b/min_ascii_strs.c @@ -0,0 +1,41 @@ +// 712. Minimum ASCII Delete Sum for Two Strings +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given two strings 's1' and 's2', return the lowest ascii sum of the deleted + * characters to make two strings equal + */ + +int minimumDeleteSum(char *s1, char *s2) { + int n = strlen(s1), m = strlen(s2), i, j; + int **dp = (int **)malloc((n + 1) * sizeof(int *)); + for (int i = 0; i <= n; i++) + dp[i] = (int *)malloc((m + 1) * sizeof(int)); + dp[0][0] = 0; + for (i = 1; i <= m; i++) + dp[0][i] = dp[0][i - 1] + s2[i - 1]; + for (i = 1; i <= n; i++) + dp[i][0] = dp[i - 1][0] + s1[i - 1]; + for (i = 1; i <= n; i++) + for (j = 1; j <= m; j++) { + if (s1[i - 1] == s2[j - 1]) + dp[i][j] = dp[i - 1][j - 1]; + else + dp[i][j] = fmin(dp[i - 1][j] + s1[i - 1], dp[i][j - 1] + s2[j - 1]); + } + int ans = dp[n][m]; + for (i = 0; i <= n; i++) + free(dp[i]); + free(dp); + return ans; +} + +int main() { + char s11[] = {"sea"}, s21[] = {"eat"}; + char s12[] = {"delete"}, s22[] = {"leet"}; + printf("%d\n", minimumDeleteSum(s11, s21)); // expect: 231 + printf("%d\n", minimumDeleteSum(s12, s22)); // expect: 403 +} diff --git a/min_ascii_strs.cpp b/min_ascii_strs.cpp new file mode 100644 index 0000000..07433d6 --- /dev/null +++ b/min_ascii_strs.cpp @@ -0,0 +1,38 @@ +// 712. Minimum ASCII Delete Sum for Two Strings +#include "leetcode.h" + +/* + * given two strings 's1' and 's2', return the lowest ascii sum of the deleted + * characters to make two strings equal + */ + +class Solution { +public: + int minimumDeleteSum(string s1, string s2) { + int n = s1.size(), m = s2.size(), sum1 = 0, sum2 = 0; + int dp[n + 1][m + 1]; + for (int i = 0; i < n; i++) + sum1 += s1[i]; + for (int i = 0; i < m; i++) + sum2 += s2[i]; + for (int i = 0; i <= n; i++) + for (int j = 0; j <= m; j++) + if (!i || !j) + dp[i][j] = 0; + for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) { + if (s1[i - 1] == s2[j - 1]) + dp[i][j] = s1[i - 1] + dp[i - 1][j - 1]; + else + dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); + } + int ans = dp[n][m]; + return sum1 + sum2 - 2 * ans; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.minimumDeleteSum("sea", "eat")); // expect: 231 + printf("%d\n", obj.minimumDeleteSum("delete", "leet")); // expect: 403 +} diff --git a/min_avg_diff.cpp b/min_avg_diff.cpp new file mode 100644 index 0000000..4bbc2b1 --- /dev/null +++ b/min_avg_diff.cpp @@ -0,0 +1,27 @@ +#include "leetcode.h" + +class Solution { +public: + int minimumAverageDifference(vector<int> &nums) { + long i = 0, j = 0, m = LONG_MAX, k, d; + long pfx = 0, sfx = accumulate(nums.begin(), nums.end(), 0L); + for (int n : nums) { + pfx += n; + sfx -= n; + j += 1; + k = nums.size() - j; + d = abs(pfx / j - sfx / (k ? k : 1)); + if (d < m) { + m = d; + i = j - 1; + } + } + return i; + } +}; + +int main() { + Solution obj; + vector<int> nums = {2, 5, 3, 9, 5, 3}; + cout << obj.minimumAverageDifference(nums); +} diff --git a/min_avg_diff.rs b/min_avg_diff.rs new file mode 100644 index 0000000..71c18aa --- /dev/null +++ b/min_avg_diff.rs @@ -0,0 +1,23 @@ +struct Solution; + +impl Solution { + pub fn minimum_average_difference(nums: Vec<i32>) -> i32 { + let (mut left, mut ans, mut min) = (0, 0, i64::MAX); + let mut right = nums.iter().map(|&x| x as i64).sum::<i64>(); + for i in 0..nums.len() { + left += nums[i] as i64; + right -= nums[i] as i64; + let diff = (left / (i + 1) as i64 - right / 1i64.max((nums.len() - i - 1) as i64)).abs(); + if diff < min { + ans = i as i32; + min = diff; + } + } + ans + } +} + +fn main() { + let nums = vec![2,5,3,9,5,3]; + print!("{}", Solution::minimum_average_difference(nums)); +} diff --git a/min_balls_in_bag.c b/min_balls_in_bag.c new file mode 100644 index 0000000..c95c0ef --- /dev/null +++ b/min_balls_in_bag.c @@ -0,0 +1,39 @@ +// 1760. Minimum Limit of Balls in a Bag +#include <stdbool.h> +#include <stdio.h> + +/* + * given an integer array 'nums' where the i'th bag contains + * 'nums[i]' balls. also given an integer 'max_operations'. + * you can perform the following operation at most 'max_operations' + * times; take any bag of balls and divide it into two new bags + * with a positive number of balls. the penalty is the maximum + * number of balls in a bag. you want to minimise your penalty + * after the operations. return the minimum possible penalty. + */ + +bool work(int *nums, int nums_size, int operation, int min) { + for (int i = 0; i < nums_size && operation >= 0; i++) + operation -= (nums[i] - 1) / min; + return operation >= 0; +} + +int minimumSize(int *nums, int nums_size, int max_operations) { + int i = 1, j = 1000000000, k; + bool can; + while (i < j) { + k = (i + j) / 2; + can = work(nums, nums_size, max_operations, k); + if (can) + j = k; + else + i = k + 1; + } + return j; +} + +int main() { + int n1[] = {9}, n2[] = {2, 4, 8, 2}; + printf("%d\n", minimumSize(n1, 1, 2)); // expect: 3 + printf("%d\n", minimumSize(n2, 4, 4)); // expect: 2 +} diff --git a/min_change_alt_binary_str.c b/min_change_alt_binary_str.c new file mode 100644 index 0000000..52a763d --- /dev/null +++ b/min_change_alt_binary_str.c @@ -0,0 +1,28 @@ +// 1758. Minimum Changes To Make Alternating Binary String +#include "leetcode.h" + +/* + * given a string 's' consisting only of the characters '0' and '1', in one + * operation, you can change any '0' to '1' or vice versa. the string is called + * alternating if no two adjacent characters are equal. for example the string + * "010" is alternating, while the string "0100" is not. return the minimum + * number of operations needed to make 's' alternating. + */ + +int minOperations(char *s) { + int n = strlen(s), cnt = 0; + for (int i = 0; i < n; i++) { + if (!(i % 2) && s[i] == '1') + cnt++; + else if (i % 2 && s[i] == '0') + cnt++; + } + return fmin(cnt, n - cnt); +} + +int main() { + char *s1 = "0100", *s2 = "10", *s3 = "1111"; + printf("%d\n", minOperations(s1)); // expect: 1 + printf("%d\n", minOperations(s2)); // expect: 0 + printf("%d\n", minOperations(s3)); // expect: 2 +} diff --git a/min_change_alt_binary_str.py b/min_change_alt_binary_str.py new file mode 100644 index 0000000..aaf2e05 --- /dev/null +++ b/min_change_alt_binary_str.py @@ -0,0 +1,39 @@ +# 1758. Minimum Changes To Make Alternating Binary String + +""" +given a string 's' consisting only of the characters '0' and '1', in one +operation, you can change any '0' to '1' or vice versa. the string is called +alternating if no two adjacent characters are equal. for example the string +"010" is alternating, while the string "0100" is not. return the minimum +number of operations needed to make 's' alternating. +""" + + +class Solution(object): + def count(self, s, pre): + cnt = 0 + for i in range(1, len(s)): + curr = s[i] + if curr == pre: + cnt += 1 + pre = "0" if pre == "1" else "1" + else: + pre = curr + return cnt + + def minOperations(self, s): + """ + :type s: str + :rtype: int + """ + c0 = s[0] + cnt1 = self.count(s, c0) + cnt2 = self.count(s, "0" if c0 == "1" else "1") + 1 + return min(cnt1, cnt2) + + +if __name__ == "__main__": + obj = Solution() + print(obj.minOperations("0100")) # expect: 1 + print(obj.minOperations("10")) # expect: 0 + print(obj.minOperations("1111")) # expect: 2 diff --git a/min_common_value.c b/min_common_value.c new file mode 100644 index 0000000..198cc29 --- /dev/null +++ b/min_common_value.c @@ -0,0 +1,52 @@ +// 2540. Minimum Common Value +#include "leetcode.h" + +/* + * given two integer arrays 'nums1' and 'nums2', sorted in non-decreasing order. + * return the minimum integer common to both arrays. if there is no common + * integer amongst 'nums1' and 'nums2', return -1. note that an integer is said + * to be common to 'nums1' and 'nums2' if both arrays have at least one + * occurence of that integer. + */ + +int getCommon(int *nums1, int nums1Size, int *nums2, int nums2Size) { + int p1 = 0, p2 = 0, n1 = nums1Size, n2 = nums2Size; + while (p1 < n1 || p2 < n2) { + if (p1 == n1) { + if (nums2[p2] > nums1[n1 - 1]) + return -1; + else { + for (int i = p2; i < n2; i++) + if (nums2[i] == nums1[n1 - 1]) + return nums2[i]; + return -1; + } + } + if (p2 == n2) { + if (nums1[p1] > nums2[n2 - 1]) + return -1; + else { + for (int i = p1; i < n1; i++) + if (nums1[i] == nums2[n2 - 1]) + return nums1[i]; + return -1; + } + } + if (nums1[p1] == nums2[p2]) + return nums1[p1]; + if (nums1[p1] < nums2[p2]) + p1++; + else + p2++; + } + return -1; +} + +int main() { + int n11[] = {1, 2, 3}, n21[] = {2, 4}, n12[] = {1, 2, 3, 6}, + n22[] = {2, 3, 4, 5}; + printf("%d\n", + getCommon(n11, ARRAY_SIZE(n11), n21, ARRAY_SIZE(n21))); // expect: 2 + printf("%d\n", + getCommon(n12, ARRAY_SIZE(n12), n22, ARRAY_SIZE(n22))); // expect: 2 +} diff --git a/min_common_value.py b/min_common_value.py new file mode 100644 index 0000000..b959ff9 --- /dev/null +++ b/min_common_value.py @@ -0,0 +1,26 @@ +# 2540. Minimum Common Value + +""" +given two integer arrays 'nums1' and 'nums2', sorted in non-decreasing order. +return the minimum integer common to both arrays. if there is no common +integer amongst 'nums1' and 'nums2', return -1. note that an integer is said +to be common to 'nums1' and 'nums2' if both arrays have at least one +occurence of that integer. +""" + + +class Solution(object): + def getCommon(self, nums1, nums2): + """ + :type nums1: List[int] + :type nums2: List[int] + :rtype: int + """ + st = set(nums1) & set(nums2) + return min(st) if len(st) else -1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.getCommon([1, 2, 3], [2, 4])) + print(obj.getCommon([1, 2, 3, 6], [2, 3, 4, 5])) diff --git a/min_cost_arr_equal.c b/min_cost_arr_equal.c new file mode 100644 index 0000000..74ff9ac --- /dev/null +++ b/min_cost_arr_equal.c @@ -0,0 +1,51 @@ +// 2448. Minimum Cost to Make Array Equal +#include <stdio.h> +#include <stdlib.h> + +/* + * given two 0-indexed arrays 'nums' and 'cost' consisting each of 'n' positive + * integers. you can do the following operation any number of times: + * - increase or decrease any element of the array 'nums' by 1 + * the cost of doing one operation on the i'th element is 'cost[i]'. return the + * minimum total cost such that all the elements of the array 'nums' become + * equal + */ + +long long helper(int *nums, int nums_size, int *cost, int mid) { + long long sum = 0; + for (int i = 0; i < nums_size; i++) { + long long k = abs(nums[i] - mid); + sum += k * cost[i]; + } + return sum; +} + +long long minCost(int *nums, int nums_size, int *cost, int cost_size) { + long long low = 1, high = 1e6; + while (low <= high) { + int mid = (low + high) / 2; + long long y1 = helper(nums, nums_size, cost, mid); + if (low == high) + return y1; + long long y2 = helper(nums, nums_size, cost, mid + 1); + long long y3 = helper(nums, nums_size, cost, mid - 1); + if (y2 >= y1 && y1 <= y3) + return y1; + if (y2 < y1) { + high = mid; + continue; + } + if (y3 < y1) { + low = mid; + continue; + } + } + return 0; +} + +int main() { + int n1[] = {1, 3, 5, 2}, c1[] = {2, 3, 1, 14}; + int n2[] = {2, 2, 2, 2, 2}, c2[] = {4, 2, 8, 1, 3}; + printf("%lld\n", minCost(n1, 4, c1, 4)); // expect: 8 + printf("%lld\n", minCost(n2, 5, c2, 5)); // expect: 0 +} diff --git a/min_cost_arr_equal.cpp b/min_cost_arr_equal.cpp new file mode 100644 index 0000000..3d2b95c --- /dev/null +++ b/min_cost_arr_equal.cpp @@ -0,0 +1,44 @@ +// 2448. Minimum Cost to Make Array Equal +#include "leetcode.h" + +/* + * given two 0-indexed arrays 'nums' and 'cost' consisting each of 'n' positive + * integers. you can do the following operation any number of times: + * - increase or decrease any element of the array 'nums' by 1 + * the cost of doing one operation on the i'th element is 'cost[i]'. return the + * minimum total cost such that all the elements of the array 'nums' become + * equal + */ + +class Solution { + long long helper(vector<int> &nums, vector<int> &cost, int x) { + long long res = 0; + for (int i = 0; i < nums.size(); ++i) + res += 1L * abs(nums[i] - x) * cost[i]; + return res; + } + +public: + long long minCost(vector<int> &nums, vector<int> &cost) { + long long left = 1, right = 1000000, ans = helper(nums, cost, 1), mid; + while (left < right) { + mid = (left + right) / 2; + long long y1 = helper(nums, cost, mid); + long long y2 = helper(nums, cost, mid + 1); + ans = min(y1, y2); + if (y1 < y2) + right = mid; + else + left = mid + 1; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 3, 5, 2}, c1 = {2, 3, 1, 14}; + vector<int> n2 = {2, 2, 2, 2, 2}, c2 = {4, 2, 8, 1, 3}; + printf("%lld\n", obj.minCost(n1, c1)); // expect: 8 + printf("%lld\n", obj.minCost(n2, c2)); // expect: 0 +} diff --git a/min_cost_change_expr.cpp b/min_cost_change_expr.cpp new file mode 100644 index 0000000..c75d10c --- /dev/null +++ b/min_cost_change_expr.cpp @@ -0,0 +1,40 @@ +#include "leetcode.h" + +class Solution { +public: + int minOperationsToFlip(string expression) { + vector<vector<array<char, 2>>> vva(1); + for (auto ch : expression) { + if (ch == '(') + vva.push_back(vector<array<char, 2>>()); + else if (ch == ')') { + auto val = eval(vva.back(), vva.back().size() - 1); + vva.pop_back(); + vva.back().push_back(val); + } else + vva.back().push_back({ch, 1}); + } + return eval(vva.back(), vva.back().size() - 1)[1]; + } + +private: + array<char, 2> eval(vector<array<char, 2>> &exp, int i) { + if (i == 0) + return exp[0]; + auto left = eval(exp, i - 2), right = exp[i]; + int v1 = left[0] - '0', v2 = right[0] - '0', cost = 1; + if (exp[i - 1][0] == '|') { + if (v1 == v2) + cost = min(left[1], right[1]) + (v1 == 1); + return {v1 | v2 ? '1' : '0', (char)cost}; + } + if (v1 == v2) + cost = min(left[1], right[1]) + (v1 == 0); + return {v1 & v2 ? '1' : '0', (char)cost}; + } +}; + +int main() { + Solution obj; + cout << obj.minOperationsToFlip("(0|(1|0&1))"); +} diff --git a/min_cost_climbing_stairs.c b/min_cost_climbing_stairs.c new file mode 100644 index 0000000..424680d --- /dev/null +++ b/min_cost_climbing_stairs.c @@ -0,0 +1,28 @@ +// 746. Min Cost Climbing Stairs +#include "leetcode.h" + +/* + * you are given an integer array 'cost' where 'cost[i]' is the cost of the i'th + * step on a staircase. once you pay the cost, you can either climb one or two + * steps. you can either start from the step with index 0 or the step with + * index 1. return the minimum cost to reach the top of the floor. + */ + +int minCostClimbingStairs(int *cost, int cost_size) { + int ans; + int *stairs = (int *)malloc(sizeof(int) * cost_size); + stairs[0] = cost[0]; + stairs[1] = cost[1]; + for (int i = 0; i < cost_size; i++) + stairs[i] = (stairs[i - 1] <= stairs[i - 2]) ? (stairs[i - 1] + cost[i]) + : (stairs[i - 2] + cost[i]); + ans = fmin(stairs[cost_size - 1], stairs[cost_size - 2]); + free(stairs); + return ans; +} + +int main() { + int c1[] = {10, 15, 20}, c2[] = {0, 100, 1, 1, 1, 100, 1, 1, 100, 1}; + printf("%d\n", minCostClimbingStairs(c1, 3)); // expect: 15 + printf("%d\n", minCostClimbingStairs(c2, 10)); // expect: 5 +} diff --git a/min_cost_climbing_stairs.cpp b/min_cost_climbing_stairs.cpp new file mode 100644 index 0000000..3df886a --- /dev/null +++ b/min_cost_climbing_stairs.cpp @@ -0,0 +1,16 @@ +#include "leetcode.h" + +class Solution { +public: + int minCostClimbingStairs(vector<int> &cost) { + for (int i = cost.size() - 3; ~i; i--) + cost[i] += min(cost[i + 1], cost[i + 2]); + return min(cost[0], cost[1]); + } +}; + +int main() { + Solution obj; + vector<int> cost = {10, 15, 20}; + cout << obj.minCostClimbingStairs(cost); +} diff --git a/min_cost_climbing_stairs.py b/min_cost_climbing_stairs.py new file mode 100644 index 0000000..a86ecd0 --- /dev/null +++ b/min_cost_climbing_stairs.py @@ -0,0 +1,25 @@ +# 746. Min Cost Climbing Stairs + +""" +you are given an integer array 'cost' where 'cost[i]' is the cost of the i'th +step on a staircase. once you pay the cost, you can either climb one or two +steps. you can either start from the step with index 0 or the step with +index 1. return the minimum cost to reach the top of the floor. +""" + + +class Solution(object): + def minCostClimbingStairs(self, cost): + n = len(cost) + dp = [0] * (n + 1) + for i in range(2, n + 1): + j1 = dp[i - 1] + cost[i - 1] + j2 = dp[i - 2] + cost[i - 2] + dp[i] = min(j1, j2) + return dp[n] + + +if __name__ == "__main__": + obj = Solution() + print(obj.minCostClimbingStairs([10, 15, 20])) # expect: 15 + print(obj.minCostClimbingStairs([1, 100, 1, 1, 1, 100, 1, 1, 100, 1])) # expect: 6 diff --git a/min_cost_connect_points.c b/min_cost_connect_points.c new file mode 100644 index 0000000..b04331b --- /dev/null +++ b/min_cost_connect_points.c @@ -0,0 +1,78 @@ +// 1584. Min Cost to Connect All Points +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given a array 'points' representing integer coordinates of some points on a + * 2d-plane, where 'points[i] = [x[i], y[i]]'. the cost of connecting two points + * '[x[i], y[i]]' and '[x[j], y[j]]' is the manhattan distance between them: + * '|x[i], - x[j]| + |y[i] + y[j]|', where '|val|' denotes the absolute value of + * 'val'. return the minimum cost to make all points connected. all points are + * connected if there is exactly one simple path betwen any two points. + */ + +int cmp(const void *p1, const void *p2) { + int *arr1 = *(int **)p1, *arr2 = *(int **)p2; + if (arr1[2] == arr2[2]) + return arr1[0] - arr2[0]; + return arr1[2] - arr2[2]; +} + +int UnionFind(int *UNION, int val) { + if (UNION[val] == val) + return val; + return UnionFind(UNION, UNION[val]); +} + +bool UnionSet(int *UNION, int *Usize, int a, int b) { + int Find_a = UnionFind(UNION, a), Find_b = UnionFind(UNION, b); + if (Find_a == Find_b) + return false; + if (Usize[Find_a] > Usize[Find_b]) { + UNION[Find_b] = UNION[Find_a]; + Usize[Find_a] += Usize[Find_b]; + } else { + UNION[Find_a] = UNION[Find_b]; + Usize[Find_b] += Usize[Find_a]; + } + return true; +} + +int minCostConnectPoints(int points[][2], int points_size, + int *points_col_size) { + int n = points_size, total_e = n * (n - 1) / 2, idx = 0; + int **table = malloc(total_e * sizeof(int *)); + for (int i = 0; i < total_e; i++) + table[i] = malloc(3 * sizeof(int)); + for (int i = 0; i < points_size; i++) + for (int j = i + 1; j < points_size; j++) { + table[idx][0] = i; + table[idx][1] = j; + table[idx][2] = + abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]); + idx++; + } + qsort(table, idx, sizeof(int *), cmp); + int *UNION = malloc(n * sizeof(int)), *Usize = malloc(n * sizeof(int)); + for (int i = 0; i < n; i++) { + UNION[i] = i; + Usize[i] = 1; + } + int ans = 0, edge = 0; + for (int i = 0; i < idx; i++) + if (UnionSet(UNION, Usize, table[i][0], table[i][1])) { + ans += table[i][2]; + edge++; + if (edge == n - 1) + break; + } + return ans; +} + +int main() { + int p1[5][2] = {{0, 0}, {2, 2}, {3, 10}, {5, 2}, {7, 0}}, + p2[3][2] = {{3, 12}, {-2, 5}, {-4, 1}}; + printf("%d\n", minCostConnectPoints(p1, 5, NULL)); // expect: 20 + printf("%d\n", minCostConnectPoints(p2, 3, NULL)); // expect: 18 +} diff --git a/min_cost_connect_points.cpp b/min_cost_connect_points.cpp new file mode 100644 index 0000000..09a00c3 --- /dev/null +++ b/min_cost_connect_points.cpp @@ -0,0 +1,51 @@ +#include "leetcode.h" + +class Solution { +public: + int minCostConnectPoints(vector<vector<int>> &points) { + int n = points.size(); + vector<vector<int>> cost(n, vector<int>(n)); + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + cost[i][j] = + abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]); + int ans = solve(n, cost); + return ans; + } + +private: + int minNode(int n, int keyVal[], bool mstSet[]) { + int mini = INT_MAX; + int miniIdx = -1; + for (int i = 0; i < n; i++) + if (mstSet[i] == false && keyVal[i] < mini) + mini = keyVal[i], miniIdx = i; + return miniIdx; + } + int solve(int n, vector<vector<int>> &city) { + int parent[n], keyVal[n]; + bool mstSet[n]; + for (int i = 0; i < n; i++) { + keyVal[i] = numeric_limits<int>::max(); + mstSet[i] = false; + } + parent[0] = -1; + keyVal[0] = 0; + for (int i = 0; i < n - 1; i++) { + int u = minNode(n, keyVal, mstSet); + mstSet[u] = true; + for (int j = 0; j < n; j++) { + if (city[u][j] && mstSet[j] == false && city[u][j] < keyVal[j]) { + keyVal[j] = city[u][j]; + parent[j] = u; + } + } + } + int cost = 0; + for (int i = 1; i < n; i++) + cost += city[parent[i]][i]; + return cost; + } +}; + +int main() {} diff --git a/min_cost_connect_points.py b/min_cost_connect_points.py new file mode 100644 index 0000000..d7c0b54 --- /dev/null +++ b/min_cost_connect_points.py @@ -0,0 +1,43 @@ +# 1584. Min Cost to Connect All Points +from collections import defaultdict +import heapq + +""" +given a array 'points' representing integer coordinates of some points on a +2d-plane, where 'points[i] = [x[i], y[i]]'. the cost of connecting two points +'[x[i], y[i]]' and '[x[j], y[j]]' is the manhattan distance between them: +'|x[i], - x[j]| + |y[i] + y[j]|', where '|val|' denotes the absolute value of +'val'. return the minimum cost to make all points connected. all points are +connected if there is exactly one simple path betwen any two points. +""" + + +class Solution(object): + def minCostConnectPoints(self, points): + manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]) + n, c = len(points), defaultdict(list) + for i in range(n): + for j in range(i + 1, n): + d = manhattan(points[i], points[j]) + c[i].append((d, j)) + c[j].append((d, i)) + cnt, ans, vis, heap = 1, 0, [0] * n, c[0] + vis[0] = 1 + heapq.heapify(heap) + while heap: + d, j = heapq.heappop(heap) + if not vis[j]: + vis[j], cnt, ans = 1, cnt + 1, ans + d + for record in c[j]: + heapq.heappush(heap, record) + if cnt >= n: + break + return ans + + +if __name__ == "__main__": + obj = Solution() + print( + obj.minCostConnectPoints([[0, 0], [2, 2], [3, 10], [5, 2], [7, 0]]) + ) # expect: 20 + print(obj.minCostConnectPoints([[3, 12], [-2, 5], [-4, 1]])) # expect: 18 diff --git a/min_cost_cut_stick.c b/min_cost_cut_stick.c new file mode 100644 index 0000000..9e94256 --- /dev/null +++ b/min_cost_cut_stick.c @@ -0,0 +1,63 @@ +// 1547. Minimum Cost to Cut a Stick +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a wooden stick of length 'n' units. the stick is labelled from 0 to + * 'n'. for example, a stick of length 6 is labelled as follows (see image). + * given an integer array 'cuts' where 'cuts[i]' denotes a position you should + * perform a cut at. you should perform the cuts in order, you can change the + * order of the cuts as you wish. the cost of one cut is the length of the stick + * to be cut, the total cost is the sum of costs of all cuts. when you cut a + * stick, it will be split into two smaller sticks ie. the sum of their lengths + * is the length of the stick before the cut. refer to first example for better + * explanation (see image). return minimum cost of the cuts + */ + +int cmp(const void *x, const void *y) { + const int a = *(const int *)x; + const int b = *(const int *)y; + if (a < b) + return -1; + else if (a > b) + return 1; + else + return 0; +} + +int get_min(int *dp, int *cuts, int start, int end, int size, int n) { + int idx = (start + 1) * size + (end - 1); + if (start + 1 >= end) + return 0; + else if (dp[idx] == -1) { + int curr_start = start - 1 ? 0 : cuts[start]; + int curr_end = end == size ? n : cuts[end]; + int min = INT_MAX; + for (int i = start + 1; i < end; i++) { + int tmp = 0; + tmp += get_min(dp, cuts, start, i, size, n); + tmp += get_min(dp, cuts, i, end, size, n); + if (tmp < min) + min = tmp; + } + min += curr_end - curr_start; + dp[idx] = min; + } + return dp[idx]; +} + +int minCost(int n, int *cuts, int cuts_size) { + int dp[cuts_size * cuts_size]; + qsort(cuts, cuts_size, sizeof(int), cmp); + memset(dp, 0xFF, sizeof(dp)); + return get_min(dp, cuts, -1, cuts_size, cuts_size, n); +} + +int main() { + int c1[] = {1, 3, 4, 5}, cs1 = 4, n1 = 7; + int c2[] = {5, 6, 1, 4, 2}, cs2 = 5, n2 = 9; + printf("%d\n", minCost(n1, c1, cs1)); // expect: 16 + printf("%d\n", minCost(n2, c2, cs2)); // expect: 23 +} diff --git a/min_cost_cut_stick.cpp b/min_cost_cut_stick.cpp new file mode 100644 index 0000000..5622868 --- /dev/null +++ b/min_cost_cut_stick.cpp @@ -0,0 +1,45 @@ +// 1547. Minimum Cost to Cut a Stick +#include "leetcode.h" + +/* + * given a wooden stick of length 'n' units. the stick is labelled from 0 to + * 'n'. for example, a stick of length 6 is labelled as follows (see image). + * given an integer array 'cuts' where 'cuts[i]' denotes a position you should + * perform a cut at. you should perform the cuts in order, you can change the + * order of the cuts as you wish. the cost of one cut is the length of the stick + * to be cut, the total cost is the sum of costs of all cuts. when you cut a + * stick, it will be split into two smaller sticks ie. the sum of their lengths + * is the length of the stick before the cut. refer to first example for better + * explanation (see image). return minimum cost of the cuts + */ + +class Solution { + int dp[102][102] = {}; + int dfs(vector<int> &cuts, int i, int j) { + if (j - i <= 1) + return 0; + if (!dp[i][j]) { + dp[i][j] = INT_MAX; + for (auto k = i + 1; k < j; ++k) + dp[i][j] = min(dp[i][j], + cuts[j] - cuts[i] + dfs(cuts, i, k) + dfs(cuts, k, j)); + } + return dp[i][j]; + } + +public: + int minCost(int n, vector<int> &cuts) { + cuts.push_back(0); + cuts.push_back(n); + sort(begin(cuts), end(cuts)); + return dfs(cuts, 0, cuts.size() - 1); + } +}; + +int main() { + Solution obj; + vector<int> c1 = {1, 3, 4, 5}; + vector<int> c2 = {5, 6, 1, 4, 2}; + printf("%d\n", obj.minCost(7, c1)); // expect: 16 + printf("%d\n", obj.minCost(9, c2)); // expect: 22 +} diff --git a/min_cost_hire_k_worker.c b/min_cost_hire_k_worker.c new file mode 100644 index 0000000..b276c73 --- /dev/null +++ b/min_cost_hire_k_worker.c @@ -0,0 +1,111 @@ +// 857. Minimum Cost to Hire K Workers +#include "leetcode.h" + +/* + * there are 'n' workers. you are given two integer arrays 'quality' and 'wage' + * where 'quality[i]' is the quality of the i'th worker and 'wage[i]' is the + * minimum wage expectation for the i'th worker. we want to hire exactly 'k' + * workers to form a paid group. to hire a group of 'k' workers, we must pay + * them according to the following rules. every worker in the paid group must be + * paid at least their minimum wage expectation. in the group, each worker's pay + * must be directly proportional to their quality. this means if a worker's + * quality is double that of another worker in the group, then they must be paid + * twice as much as the other worker. given the integer 'k', return the least + * amount of money needed to form apaid group satisfying the above conditions. + */ + +struct workers { + int q; + int w; + double w_p_q; +}; + +int cmp_work(const void *a, const void *b) { + double tmp = ((struct workers *)b)->w_p_q - ((struct workers *)a)->w_p_q; + if (tmp < 0) + return -1; + return 1; +} + +int cmp(const void *a, const void *b) { return *(int *)b - *(int *)a; } + +void max_heap_insert(int *heap, int *n, int val) { + int i = ++(*n), parent = i / 2; + while (i != 1 && val > heap[parent]) { + heap[i] = heap[parent]; + i = parent; + parent /= 2; + } + heap[i] = val; +} + +int max_heap_delete(int *heap, int *n) { + int val = heap[1], tmp = heap[*n--], parent = 1, child = parent * 2; + while (child <= *n) { + if (child < *n && heap[child] < heap[child + 1]) + child++; + if (tmp >= heap[child]) + break; + else { + heap[parent] = heap[child]; + parent = child; + child *= 2; + } + } + heap[parent] = tmp; + return val; +} + +void get_dp(struct workers *arr, int size, int num, int *dp) { + if (!num) + return; + int tmp[num + 1], n = 0, sum = 0; + for (int i = size - num; i < size; i++) { + max_heap_insert(tmp, &n, arr[i].q); + sum += arr[i].q; + } + dp[size - num] = sum; + for (int i = size - num - 1; i >= 0; i--) { + if (arr[i].q < tmp[1]) { + sum -= max_heap_delete(tmp, &n); + sum += arr[i].q; + max_heap_insert(tmp, &n, arr[i].q); + } + dp[i] = sum; + } +} + +double mincostToHireWorkers(int *quality, int qualitySize, int *wage, + int wageSize, int k) { + if (qualitySize == 1) + return wage[0]; + struct workers *member = + (struct workers *)malloc(qualitySize * sizeof(struct workers)); + for (int i = 0; i < qualitySize; i++) { + member[i].q = quality[i]; + member[i].w = wage[i]; + member[i].w_p_q = (double)wage[i] / quality[i]; + } + double ans = 1000000000, cost; + int max = 0x7fffffff, q_idx = 0, dp[qualitySize]; + qsort(member, qualitySize, sizeof(struct workers), cmp_work); + get_dp(member, qualitySize, k - 1, dp); + for (int i = 0; i <= qualitySize - k; i++) { + int total = member[i].q; + if (k != 1) + total += dp[i + 1]; + cost = total * member[i].w_p_q; + if (cost < ans) + ans = cost; + } + return ans; +} + +int main() { + int q1[] = {10, 20, 5}, w1[] = {70, 50, 30}, q2[] = {3, 1, 10, 10, 1}, + w2[] = {4, 8, 2, 2, 7}; + printf("%f\n", mincostToHireWorkers(q1, ARRAY_SIZE(q1), w1, ARRAY_SIZE(w1), + 2)); // expect: 105.0000 + printf("%f\n", mincostToHireWorkers(q2, ARRAY_SIZE(q2), w2, ARRAY_SIZE(w2), + 3)); // expect: 30.6667 +} diff --git a/min_cost_hire_k_worker.py b/min_cost_hire_k_worker.py new file mode 100644 index 0000000..b520c2b --- /dev/null +++ b/min_cost_hire_k_worker.py @@ -0,0 +1,45 @@ +# 857. Minimum Cost to Hire K Workers +import heapq + +""" +there are 'n' workers. you are given two integer arrays 'quality' and 'wage' +where 'quality[i]' is the quality of the i'th worker and 'wage[i]' is the +minimum wage expectation for the i'th worker. we want to hire exactly 'k' +workers to form a paid group. to hire a group of 'k' workers, we must pay +them according to the following rules. every worker in the paid group must be +paid at least their minimum wage expectation. in the group, each worker's pay +must be directly proportional to their quality. this means if a worker's +quality is double that of another worker in the group, then they must be paid +twice as much as the other worker. given the integer 'k', return the least +amount of money needed to form apaid group satisfying the above conditions. +""" + + +class Solution(object): + def mincostToHireWorkers(self, quality, wage, k): + """ + :type quality: List[int] + :type wage: List[int] + :type k: int + :rtype: float + """ + workers = sorted([float(w) / q, q] for w, q in zip(wage, quality)) + ans = float("inf") + qsum = 0 + heap = [] + for r, q in workers: + heapq.heappush(heap, -q) + qsum += q + if len(heap) > k: + qsum += heapq.heappop(heap) + if len(heap) == k: + ans = min(ans, qsum * r) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.mincostToHireWorkers(quality=[10, 20, 5], wage=[70, 50, 30], k=2)) + print( + obj.mincostToHireWorkers(quality=[3, 1, 10, 10, 1], wage=[4, 8, 2, 2, 7], k=3) + ) diff --git a/min_cost_ticket.c b/min_cost_ticket.c new file mode 100644 index 0000000..88abdb2 --- /dev/null +++ b/min_cost_ticket.c @@ -0,0 +1,54 @@ +// 983. Minimum Cost For Tickets +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * you have planned some train traveling one year in advance. the days of the + * year in which you will travel are given as an integer array 'days'. each day + * is an integer 1 - 365. train tickets are sold in three different ways: 1 day + * pass sold for 'costs[0]' dollars 7 day pass sold for 'costs[1]' dollars 30 + * day pass sold for 'costs[2]' dollars the passes allow that many days of + * consecutive travel. return mininum number of dollars you need to travel every + * day in the given list of days. + */ + +#define MIN(a, b, c) \ + ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c))) + +bool find_item(int *days, int days_size, int target) { + int left = 0, right = days_size - 1, mid; + while (left <= right) { + mid = (left + right) / 2; + if (days[mid] == target) + return true; + if (days[mid] > target) + right = mid - 1; + else + left = mid + 1; + } + return false; +} + +int mincostTickets(int *days, int days_size, int *costs, int costs_size) { + int arr_size = days[days_size - 1] + 30; + int *dp = calloc(arr_size, sizeof(int)); + for (int i = 30; i < arr_size; i++) { + if (find_item(days, days_size, i - 29) == false) + dp[i] = dp[i - 1]; + else + dp[i] = MIN(dp[i - 1] + costs[0], dp[i - 7] + costs[i], + dp[i - 30] + costs[2]); + } + int ans = dp[arr_size - 1]; + free(dp); + return ans; +} + +int main() { + int d1[] = {1, 4, 6, 7, 8, 20}, + d2[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 31}; + int c1[] = {2, 7, 15}; + printf("%d\n", mincostTickets(d1, 6, c1, 3)); // expect: 11 + printf("%d\n", mincostTickets(d2, 12, c1, 3)); // expect: 11 +} diff --git a/min_cost_ticket.cpp b/min_cost_ticket.cpp new file mode 100644 index 0000000..1d00853 --- /dev/null +++ b/min_cost_ticket.cpp @@ -0,0 +1,42 @@ +// 983. Minimum Cost For Tickets +#include "leetcode.h" + +/* + * you have planned some train traveling one year in advance. the days of the + * year in which you will travel are given as an integer array 'days'. each day + * is an integer 1 - 365. train tickets are sold in three different ways: 1 day + * pass sold for 'costs[0]' dollars 7 day pass sold for 'costs[1]' dollars 30 + * day pass sold for 'costs[2]' dollars the passes allow that many days of + * consecutive travel. return mininum number of dollars you need to travel every + * day in the given list of days. + */ + +class Solution { +public: + int mincostTickets(vector<int> &days, vector<int> &costs) { + unordered_map<int, int> tickets; + tickets[1] = costs[0]; + tickets[7] = costs[1]; + tickets[30] = costs[2]; + vector<int> dp(366, INT_MAX); + dp[0] = 0; + for (int i = 1; i < 366; i++) { + if (find(days.begin(), days.end(), i) == days.end()) { + dp[i] = dp[i - 1]; + continue; + } + for (auto t : tickets) + dp[i] = min(dp[i], dp[max(0, i - t.first)] + t.second); + } + return dp[365]; + } +}; + +int main() { + Solution obj; + vector<int> d1 = {1, 4, 6, 7, 8, 20}, + d2 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 30, 31}; + vector<int> c1 = {2, 7, 15}; + printf("%d\n", obj.mincostTickets(d1, c1)); // expect: 11 + printf("%d\n", obj.mincostTickets(d2, c1)); // expect: 17 +} diff --git a/min_days_make_bouquets.c b/min_days_make_bouquets.c new file mode 100644 index 0000000..6b1b1be --- /dev/null +++ b/min_days_make_bouquets.c @@ -0,0 +1,58 @@ +// 1482. Minimum Number of Days to Make m Bouquets +#include "leetcode.h" + +/* + * given an integer array 'bloomDay', an integer 'm', and an integer 'k'. you + * want to make 'm' bouquets. to make a bouquet, you need to use 'k' adjacent + * flowers from the garden. the garden consists of 'n' flowers, the i'th flower + * will bloom in the 'bloomDay[i]' and then can be used in exactly one bouquet. + * return the minimum number of days you need to wait to be able to make 'm' + * bouquets from the garden. if it is impossible to make 'm' bouquets, return -1 + */ + +int helper(int *bloomDay, int bloomDaySize, int day, int k) { + int cnt_bloom = 0, cnt = 0; + for (int i = 0; i < bloomDaySize; i++) { + if (bloomDay[i] <= day) { + cnt++; + if (cnt == k) { + cnt_bloom++; + cnt = 0; + } + } else + cnt = 0; + } + return cnt_bloom; +} + +int minDays(int *bloomDay, int bloomDaySize, int m, int k) { + int i, j, min_day = INT_MAX, max_day = INT_MIN; + for (int i = 0; i < bloomDaySize; i++) { + min_day = fmin(min_day, bloomDay[i]); + max_day = fmax(max_day, bloomDay[i]); + } + int left = min_day, right = max_day, mid, num_bloom; + while (left + 1 < right) { + mid = (left + right) / 2; + num_bloom = helper(bloomDay, bloomDaySize, mid, k); + if (num_bloom >= m) + right = mid; + else + left = mid + 1; + } + num_bloom = helper(bloomDay, bloomDaySize, left, k); + if (num_bloom >= m) + return left; + num_bloom = helper(bloomDay, bloomDaySize, right, k); + if (num_bloom >= m) + return right; + return -1; +} + +int main() { + int bd1[] = {1, 10, 3, 10, 2}, bd2[] = {1, 10, 3, 10, 2}, + bd3[] = {7, 7, 7, 7, 12, 7, 7}; + printf("%d\n", minDays(bd1, ARRAY_SIZE(bd1), 3, 1)); // expect: 3 + printf("%d\n", minDays(bd2, ARRAY_SIZE(bd2), 3, 2)); // expect: -1 + printf("%d\n", minDays(bd3, ARRAY_SIZE(bd3), 2, 3)); // expect: 2 +} diff --git a/min_days_make_bouquets.py b/min_days_make_bouquets.py new file mode 100644 index 0000000..02cf2e2 --- /dev/null +++ b/min_days_make_bouquets.py @@ -0,0 +1,45 @@ +# 1482. Minimum Number of Days to Make m Bouquets + +""" +given an integer array 'bloomDay', an integer 'm', and an integer 'k'. you +want to make 'm' bouquets. to make a bouquet, you need to use 'k' adjacent +flowers from the garden. the garden consists of 'n' flowers, the i'th flower +will bloom in the 'bloomDay[i]' and then can be used in exactly one bouquet. +return the minimum number of days you need to wait to be able to make 'm' +bouquets from the garden. if it is impossible to make 'm' bouquets, return -1 +""" + + +class Solution(object): + def minDays(self, bloomDay, m, k): + """ + :type bloomDay: List[int] + :type m: int + :type k: int + :rtype: int + """ + if m * k > len(bloomDay): + return -1 + left, right = 1, max(bloomDay) + while left < right: + mid = (left + right) / 2 + flow, bouq = 0, 0 + for i in bloomDay: + flow = 0 if i > mid else flow + 1 + if flow >= k: + flow = 0 + bouq += 1 + if bouq == m: + break + if bouq == m: + right = mid + else: + left = mid + 1 + return left + + +if __name__ == "__main__": + obj = Solution() + print(obj.minDays(bloomDay=[1, 10, 3, 10, 2], m=3, k=1)) + print(obj.minDays(bloomDay=[1, 10, 3, 10, 2], m=3, k=2)) + print(obj.minDays(bloomDay=[7, 7, 7, 7, 12, 7, 7], m=2, k=3)) diff --git a/min_deletions_unique_char.c b/min_deletions_unique_char.c new file mode 100644 index 0000000..3bcdcf3 --- /dev/null +++ b/min_deletions_unique_char.c @@ -0,0 +1,40 @@ +// 1647. Minimum Deletions to Make Character Frequencies Unique +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * a string 's' is called good if there are no two different characters in 's' + * that have the same frequency. given a string 's', return the minimum number + * of characters you need to delete to make 's' good. the frequency of a + * character in a string is the number of times it appears in the string. for + * example, in the string "aab", the frequency of 'a' is 2, while the frequency + * of 'b' is 1. + */ + +int cmp(const int *a, const int *b) { return (*b - *a); } + +int minDeletions(char *s) { + int n = strlen(s), ans[26] = {}, cnt = 0; + for (int i = 0; s[i] != '\0'; i++) + ans[s[i] - 'a']++; + qsort(ans, 26, sizeof(int), cmp); + for (int i = 1; i < 26; i++) { + if (!ans[i]) + continue; + while (ans[i] >= ans[i - 1]) { + cnt++; + ans[i]--; + if (!ans[i]) + break; + } + return cnt; + } +} + +int main() { + char s1[] = {"aab"}, s2[] = {"aaabbbcc"}, s3[] = {"ceabaacb"}; + printf("%d\n", minDeletions(s1)); // expect: 0 + printf("%d\n", minDeletions(s2)); // expect: 2 + printf("%d\n", minDeletions(s3)); // expect: 2 +} diff --git a/min_deletions_unique_char.cpp b/min_deletions_unique_char.cpp new file mode 100644 index 0000000..c971b21 --- /dev/null +++ b/min_deletions_unique_char.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" + +class Solution { +public: + int minDeletions(string s) { + vector<int> freq(26, 0); + int ans = 0; + for (char c : s) + freq[c - 'a']++; + sort(freq.begin(), freq.end()); + for (int i = 24; i >= 0; i--) { + if (freq[i] == 0) + break; + if (freq[i] >= freq[i + 1]) { + int prev = freq[i]; + freq[i] = max(0, freq[i + 1] - 1); + ans += prev - freq[i]; + } + } + return ans; + } +}; + +int main() { + Solution obj; + string s = "aab"; + cout << obj.minDeletions(s); +} diff --git a/min_deletions_unique_char.py b/min_deletions_unique_char.py new file mode 100644 index 0000000..7a31704 --- /dev/null +++ b/min_deletions_unique_char.py @@ -0,0 +1,31 @@ +# 1647. Minimum Deletions to Make Character Frequencies Unique +from collections import Counter + +""" +a string 's' is called good if there are no two different characters in 's' +that have the same frequency. given a string 's', return the minimum number +of characters you need to delete to make 's' good. the frequency of a +character in a string is the number of times it appears in the string. for +example, in the string "aab", the frequency of 'a' is 2, while the frequency +of 'b' is 1. +""" + + +class Solution: + def minDeletions(self, s): + cnt = Counter(s) + deletions = 0 + used_freq = set() + for char, freq in cnt.items(): + while freq > 0 and freq in used_freq: + freq -= 1 + deletions += 1 + used_freq.add(freq) + + return deletions + + +if __name__ == "__main__": + obj = Solution() + print(obj.minDeletions("aab")) # expect: 0 + print(obj.minDeletions("aaabbbcc")) # expect: 2 diff --git a/min_depth_binary_tree.c b/min_depth_binary_tree.c new file mode 100644 index 0000000..f1db72a --- /dev/null +++ b/min_depth_binary_tree.c @@ -0,0 +1,23 @@ +// 111. Minimum Depth of Binary Tree + +/* + * given a binary tree, find its minimum depth. the minimum depth is the number + * of nodes along the shortest path from the root node down to the nearest leaf + * node. note: a leaf is a node with no children. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int minDepth(struct TreeNode *root) { + if (!root) + return 0; + int l = minDepth(root->left); + int r = minDepth(root->right); + if (!l || !r) + return l + r + 1; + return 1 + (l > r ? r : l); +} diff --git a/min_depth_binary_tree.cpp b/min_depth_binary_tree.cpp new file mode 100644 index 0000000..7661fb2 --- /dev/null +++ b/min_depth_binary_tree.cpp @@ -0,0 +1,34 @@ +// 111. Minimum Depth of Binary Tree +#include "leetcode.h" + +/* + * given a binary tree, find its minimum depth. the minimum depth is the number + * of nodes along the shortest path from the root node down to the nearest leaf + * node. note: a leaf is a node with no children. + */ + +class Solution { +public: + int minDepth(TreeNode *root) { + if (!root) + return 0; + queue<TreeNode *> q; + q.push(root); + int i = 0; + while (!q.empty()) { + i++; + int k = q.size(); + for (int j = 0; j < k; j++) { + TreeNode *rt = q.front(); + if (rt->left) + q.push(rt->left); + if (rt->right) + q.push(rt->right); + q.pop(); + if (!rt->left && !rt->right) + return i; + } + } + return -1; + } +}; diff --git a/min_deviation_arr.c b/min_deviation_arr.c new file mode 100644 index 0000000..5d00d56 --- /dev/null +++ b/min_deviation_arr.c @@ -0,0 +1,88 @@ +// 1675. Minimize Deviation in Array +#include <stdio.h> + +#define SWAP(x, y) (x ^= y ^= x ^= y) +#define MIN(a, b) ((a < b) ? a : b) + +/* + * the deviation of the array is the maximum difference between any two elements + * in the array. return minimum deviation the array can have after performing + * 'nums' ops. + */ + +void check_larger(int *h, int posi) { + for (int cmp; posi >= 4; posi = cmp) { + cmp = (posi >> 2 << 1) + 1; + if (h[posi] > h[cmp]) + SWAP(h[posi], h[cmp]); + else + break; + } +} + +void check_smaller(int *h, int posi) { + for (int cmp; posi >= 4; posi = cmp) { + cmp = posi >> 2 << 1; + if (h[posi] < h[cmp]) + SWAP(h[posi], h[cmp]); + else + break; + } +} + +void insert(int *h, int top, int data) { + h[top] = data; + if (!(top & 1)) { + if (h[top] > h[top >> 1]) + check_larger(h, top); + else + check_smaller(h, top); + } else { + if (h[top] < h[top - 1]) { + SWAP(h[top], h[top - 1]); + check_smaller(h, top - 1); + } else + check_larger(h, top); + } +} + +void delete_max(int *h, int *top) { + h[3] = h[(*top)--]; + int par = 3, chi = 5; + while (chi <= (*top)) { + if (chi + 2 <= (*top) && h[chi + 2] > h[chi]) + chi += 2; + if (h[chi] > h[par]) { + SWAP(h[chi], h[par]); + par = chi; + chi = (chi << 1) - 1; + } else + break; + } + if (h[par] < h[par - 1]) + SWAP(h[par], h[par - 1]); +} + +int minimumDeviation(int *nums, int numsSize) { + int h[numsSize + 2], top = 1, ans; + for (int i = 0; i < numsSize; i++) { + if (nums[i] & 1) + nums[i] <<= 1; + insert(h, ++top, nums[i]); + } + ans = h[3] - h[2]; + while (!(h[3] & 1)) { + int t = h[3] >> 1; + delete_max(h, &top); + insert(h, ++top, t); + ans = MIN(ans, h[3] - h[2]); + } + return ans; +} + +int main() { + int n1[] = {1, 2, 3, 4}, n2[] = {4, 1, 5, 20, 3}, n3[] = {2, 10, 8}; + printf("%d\n", minimumDeviation(n1, 4)); // expect: 1 + printf("%d\n", minimumDeviation(n2, 5)); // expect: 3 + printf("%d\n", minimumDeviation(n3, 3)); // expect: 3 +} diff --git a/min_deviation_arr.cpp b/min_deviation_arr.cpp new file mode 100644 index 0000000..47099a6 --- /dev/null +++ b/min_deviation_arr.cpp @@ -0,0 +1,36 @@ +// 1675. Minimize Deviation in Array +#include "leetcode.h" + +/* + * the deviation of the array is the maximum difference between any two elements + * in the array. return minimum deviation the array can have after performing + * 'nums' ops. + */ + +class Solution { +public: + int minimumDeviation(vector<int> nums) { + int ans = INT_MAX, min_nums = INT_MAX; + for (int i = 0; i < nums.size(); ++i) { + nums[i] = nums[i] % 2 ? nums[i] * 2 : nums[i]; + min_nums = min(min_nums, nums[i]); + } + make_heap(begin(nums), end(nums)); + while (nums[0] % 2 == 0) { + ans = min(ans, nums[0] - min_nums); + min_nums = min(min_nums, nums[0] / 2); + pop_heap(begin(nums), end(nums)); + nums.back() /= 2; + push_heap(begin(nums), end(nums)); + } + return min(ans, nums[0] - min_nums); + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 2, 3, 4}, n2 = {4, 1, 5, 20, 3}, n3 = {2, 10, 8}; + cout << obj.minimumDeviation(n1) << endl; // expect: 1 + cout << obj.minimumDeviation(n2) << endl; // expect: 3 + cout << obj.minimumDeviation(n3) << endl; // expect: 3 +} diff --git a/min_difficulty_schedule.c b/min_difficulty_schedule.c new file mode 100644 index 0000000..c2296e5 --- /dev/null +++ b/min_difficulty_schedule.c @@ -0,0 +1,51 @@ +// 1335. Minimum Difficulty of a Job Schedule +#include "leetcode.h" + +/* +You want to schedule a list of jobs in d days. Jobs are dependent (i.e To work +on the ith job, you have to finish all the jobs j where 0 <= j < i). + +You have to finish at least one task every day. The difficulty of a job schedule +is the sum of difficulties of each day of the d days. The difficulty of a day is +the maximum difficulty of a job done on that day. + +You are given an integer array job_difficulty and an integer d. The difficulty +of the ith job is job_difficulty[i]. + +Return the minimum difficulty of a job schedule. If you cannot find a schedule +for the jobs return -1. +*/ + +int minDifficulty(int *job_difficulty, int job_difficulty_size, int d) { + int maxValue = 10001, max_difficulty = 0; + if (job_difficulty_size < d) + return -1; + if (d == 1) { + for (int i = 0; i < job_difficulty_size; i++) + max_difficulty = fmax(max_difficulty, job_difficulty[i]); + return max_difficulty; + } + max_difficulty = 0; + int min_job_diff[job_difficulty_size + 1]; + for (int i = 0; i < job_difficulty_size; i++) + min_job_diff[i] = maxValue; + min_job_diff[job_difficulty_size] = 0; + for (int day = 1; day <= d; ++day) { + for (int i = 0; i <= job_difficulty_size - day; i++) { + max_difficulty = 0, min_job_diff[i] = maxValue; + for (int j = i; j <= job_difficulty_size - day; j++) { + max_difficulty = fmax(max_difficulty, job_difficulty[j]); + min_job_diff[i] = + fmin(min_job_diff[i], max_difficulty + min_job_diff[j + 1]); + } + } + } + return min_job_diff[0]; +} + +int main() { + int jb1[] = {6, 5, 4, 3, 2, 1}, jb2[] = {9, 9, 9}, jb3[] = {1, 1, 1}; + printf("%d\n", minDifficulty(jb1, ARRAY_SIZE(jb1), 2)); // expect: 7 + printf("%d\n", minDifficulty(jb2, ARRAY_SIZE(jb2), 4)); // expect: -1 + printf("%d\n", minDifficulty(jb3, ARRAY_SIZE(jb3), 3)); // expect: 3 +} diff --git a/min_difficulty_schedule.cpp b/min_difficulty_schedule.cpp new file mode 100644 index 0000000..40fab6e --- /dev/null +++ b/min_difficulty_schedule.cpp @@ -0,0 +1,36 @@ +#include "leetcode.h" +#include <algorithm> +#include <vector> + +class Solution { +public: + int minDifficulty(vector<int> &jobDifficulty, int d) { + int n = jobDifficulty.size(); + if (n < d) + return -1; + vector<int> dp(n, 1000), dp2(n), stack; + for (int i = 0; i < d; ++i) { + stack.clear(); + for (int j = i; j < n; j++) { + dp2[j] = j ? dp[j - 1] + jobDifficulty[j] : jobDifficulty[j]; + while (stack.size() && + jobDifficulty[stack.back()] <= jobDifficulty[j]) { + int k = stack.back(); + stack.pop_back(); + dp[j] = min(dp2[j], dp2[k] - jobDifficulty[k] + jobDifficulty[j]); + } + if (stack.size()) + dp2[j] = min(dp2[j], dp2[stack.back()]); + stack.push_back(j); + } + swap(dp, dp2); + } + return dp[n - 1]; + } +}; + +int main() { + Solution obj; + vector<int> jobDifficulty = {6, 5, 4, 3, 2, 1}; + cout << obj.minDifficulty(jobDifficulty, 2); +} diff --git a/min_difficulty_schedule.py b/min_difficulty_schedule.py new file mode 100644 index 0000000..07d33c4 --- /dev/null +++ b/min_difficulty_schedule.py @@ -0,0 +1,52 @@ +# 1335. Minimum Difficulty of a Job Schedule + +""" +You want to schedule a list of jobs in d days. Jobs are dependent (i.e To work +on the ith job, you have to finish all the jobs j where 0 <= j < i). + +You have to finish at least one task every day. The difficulty of a job schedule +is the sum of difficulties of each day of the d days. The difficulty of a day is +the maximum difficulty of a job done on that day. + +You are given an integer array job_difficulty and an integer d. The difficulty of +the ith job is job_difficulty[i]. + +Return the minimum difficulty of a job schedule. If you cannot find a schedule +for the jobs return -1. +""" + + +class Solution(object): + def helper(self, job_difficulty, days_left, idx): + n = len(job_difficulty) + if days_left == 1: + return max(job_difficulty[idx:]) + max_difficulty = job_difficulty[idx] + days_left -= 1 + stop = n - idx - days_left + 1 + res = float("inf") + for i in range(1, stop): + max_difficulty = max(max_difficulty, job_difficulty[idx + i - 1]) + other = self.helper(job_difficulty, days_left, idx + i) + res = min(res, other + max_difficulty) + return res + + def minDifficulty(self, jobDifficulty, d): + """ + :type jobDifficulty: List[int] + :type d: int + :rtype: int + """ + if len(jobDifficulty) < d: + return -1 + total_sum = sum(jobDifficulty) + if total_sum == 0: + return 0 + return self.helper(jobDifficulty, d, 0) + + +if __name__ == "__main__": + obj = Solution() + print(obj.minDifficulty(jobDifficulty=[6, 5, 4, 3, 2, 1], d=2)) + print(obj.minDifficulty(jobDifficulty=[9, 9, 9], d=4)) + print(obj.minDifficulty(jobDifficulty=[1, 1, 1], d=3)) diff --git a/min_dist_bst_node.c b/min_dist_bst_node.c new file mode 100644 index 0000000..8a5d886 --- /dev/null +++ b/min_dist_bst_node.c @@ -0,0 +1,36 @@ +#include <limits.h> +#include <stddef.h> +#include <stdlib.h> + +/* 783. Minimum Distance Between BST Nodes + * given the 'root' of BST, return the minimum difference between the values + * of any two different nodes in the tree! + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +void tree2array(struct TreeNode *root, int *data, int *idx) { + if (root == NULL) + return; + tree2array(root->left, data, idx); + data[*idx] = root->val; + *idx = *idx + 1; + tree2array(root->right, data, idx); +} + +int minDiffInBST(struct TreeNode *root) { + int *data = malloc(100 * sizeof(int)); + int *idx = calloc(1, sizeof(int)); + tree2array(root, data, idx); + int min = INT_MAX; + for (int i = 1; i < (*idx); i++) + if ((data[i] - data[i - 1]) < min) + min = data[i] - data[i - 1]; + free(data); + free(idx); + return min; +} diff --git a/min_dist_bst_node.cpp b/min_dist_bst_node.cpp new file mode 100644 index 0000000..5222628 --- /dev/null +++ b/min_dist_bst_node.cpp @@ -0,0 +1,20 @@ +// 783. Minimum Distance Between BST Nodes +#include "leetcode.h" + +// given the 'root' of BST, return the minimum difference between the values +// of any two different nodes in the tree! + +class Solution { +public: + int ans = INT_MAX, pre = -1; + int minDiffInBST(TreeNode *root) { + if (root->left != NULL) + minDiffInBST(root->left); + if (pre >= 0) + ans = min(ans, root->val - pre); + pre = root->val; + if (root->right != NULL) + minDiffInBST(root->right); + return ans; + } +}; diff --git a/min_dist_target_element.cpp b/min_dist_target_element.cpp new file mode 100644 index 0000000..662c5ec --- /dev/null +++ b/min_dist_target_element.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + int getMinDistance(vector<int> &nums, int target, int start) { + int ans = INT_MAX; + for (int i = 0; i < nums.size(); i++) + if (nums[i] == target) + ans = min(ans, abs(i - start)); + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums = {1, 2, 3, 4, 5}; + int target = 5, start = 3; + // expect 1 + cout << obj.getMinDistance(nums, target, start); +} diff --git a/min_falling_path_sum.c b/min_falling_path_sum.c new file mode 100644 index 0000000..77cfee1 --- /dev/null +++ b/min_falling_path_sum.c @@ -0,0 +1,37 @@ +// 931. Minimum Falling Path Sum +#include "leetcode.h" + +/* + * given an 'n * n' array of integers 'matrix', return the minimum sum of any + * falling path through 'matrix'. a falling path starts at any element in the + * first row and choose the element in the next row that is either directly + * below or diagonally left/right. specifically, the next element from position + * '(row, col)' will be '(row + 1, col - 1), (row + 1, col), or (row + 1, col + + * 1)'. + */ + +int minFallingPathSum(int **matrix, int matrix_size, int *matrix_col_size) { + int **dp = (int **)malloc(sizeof(int *) * matrix_size); + for (int i = 0; i < matrix_size; i++) { + int *tmp = (int *)malloc(sizeof(int) * matrix_col_size[i]); + memset(tmp, 0, matrix_col_size[i]); + dp[i] = tmp; + } + for (int i = 0, n = matrix_col_size[0]; i < n; i++) + dp[0][i] = matrix[0][i]; + for (int i = 1; i < matrix_size; i++) { + for (int j = 0, n = matrix_col_size[i]; j < n; j++) { + if (!j) + dp[i][j] = matrix[i][j] + fmin(dp[i - 1][j], dp[i - 1][j + 1]); + else if (j == n - 1) + dp[i][j] = matrix[i][j] + fmin(dp[i - 1][j], dp[i - 1][j - 1]); + else + dp[i][j] = matrix[i][j] + + fmin(dp[i - 1][j - 1], fmin(dp[i - 1][j], dp[i - 1][j + 1])); + } + } + int ans = INT_MAX; + for (int i = 0, n = matrix_col_size[matrix_size - 1]; i < n; i++) + ans = fmin(ans, dp[matrix_size - 1][i]); + return ans; +} diff --git a/min_falling_path_sum.cpp b/min_falling_path_sum.cpp new file mode 100644 index 0000000..33c1cd8 --- /dev/null +++ b/min_falling_path_sum.cpp @@ -0,0 +1,45 @@ +#include "leetcode.h" + +/* + * given NxN array of integers 'matrix' return the minimum + * sum of any falling path through 'matrix' + * + * a falling path starts at any element in row 0 and chooses + * the element in the next row that is either directly below + * or diagonally left/right that obviously makes for the lowest sum + */ + +class Solution { +public: + int minFallingPathSum(vvd(int) & matrix) { + vvd(int) dp(matrix.size(), vector<int>(matrix.size(), INT_MAX)); + for (int i = 0; i < matrix.size(); i++) + dp[0][i] = matrix[0][i]; + for (int i = 1; i < matrix.size(); i++) { + for (int j = 0; j < matrix.size(); j++) { + if (j > 0 && j < matrix.size() - 1) { + dp[i][j] = + min(dp[i - 1][j - 1] + matrix[i][j], dp[i - 1][j] + matrix[i][j]); + dp[i][j] = min(dp[i - 1][i + 1] + matrix[i][j], dp[i][j]); + } else if (j == 0) + dp[i][j] = + min(dp[i - 1][j + 1] + matrix[i][j], dp[i - 1][j] + matrix[i][j]); + else if (j == matrix.size() - 1) + dp[i][j] = + min(dp[i - 1][j - 1] + matrix[i][j], dp[i - 1][j] + matrix[i][j]); + } + } + int ans = INT_MAX; + for (auto &x : dp[dp.size() - 1]) + ans = min(ans, x); + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) matrix = {{2, 1, 3}, // 1 + {6, 5, 4}, //-> 4 + {7, 8, 9}}; // 8 <- + cout << obj.minFallingPathSum(matrix); // expect 13 +} diff --git a/min_falling_path_sum.py b/min_falling_path_sum.py new file mode 100644 index 0000000..29eff1b --- /dev/null +++ b/min_falling_path_sum.py @@ -0,0 +1,41 @@ +# 931. Minimum Falling Path Sum + +""" +given an 'n n' array of integers 'matrix', return the minimum sum of any +falling path through 'matrix'. a falling path starts at any element in the +first row and choose the element in the next row that is either directly +below or diagonally left/right. specifically, the next element from position +'(row, col)' will be '(row + 1, col - 1), (row + 1, col), or (row + 1, col + +1)'. +""" + + +class Solution(object): + def minFallingPathSum(self, matrix): + """ + :type matrix: List[List[int]] + :rtype: int + """ + grid = matrix + for i in range(1, len(grid)): + for j in range(len(grid[i])): + if i - 1 >= 0 and j - 1 >= 0: + p1 = grid[i - 1][j - 1] + else: + p1 = float("inf") + if i - 1 >= 0: + p2 = grid[i - 1][j] + else: + p2 = float("inf") + if i - 1 >= 0 and j + 1 <= len(grid[0]) - 1: + p3 = grid[i - 1][j + 1] + else: + p3 = float("inf") + grid[i][j] += min(p1, p2, p3) + return min(grid[len(grid) - 1]) + + +if __name__ == "__main__": + obj = Solution() + print(obj.minFallingPathSum(matrix=[[2, 1, 3], [6, 5, 4], [7, 8, 9]])) + print(obj.minFallingPathSum(matrix=[[-19, 57], [-40, -5]])) diff --git a/min_falling_path_sum.rs b/min_falling_path_sum.rs new file mode 100644 index 0000000..4b704c1 --- /dev/null +++ b/min_falling_path_sum.rs @@ -0,0 +1,23 @@ +struct Solution; + +impl Solution { + pub fn min_falling_path_sum(matrix: Vec<Vec<i32>>) -> i32 { + matrix.into_iter().reduce(|prev, mut curr| { + prev.into_iter().chain(std::iter::once(i32::MAX)).scan((i32::MAX, i32::MAX, i32::MAX), |(w1, w2, w3), c| { + *w1 = *w2; + *w2 = *w3; + *w3 = c; + Some(c.min(*w1).min(*w2)) + }).skip(1).zip(curr.iter_mut()).for_each(|(p, c)| *c += p); + curr + }).unwrap().into_iter().min().unwrap() + } +} + +fn main() { + let matrix = vec![ + vec![2,1,3], + vec![6,5,4], + vec![7,8,9]]; + print!("{}", Solution::min_falling_path_sum(matrix)); +} diff --git a/min_falling_path_sum2.c b/min_falling_path_sum2.c new file mode 100644 index 0000000..128fb85 --- /dev/null +++ b/min_falling_path_sum2.c @@ -0,0 +1,42 @@ +// 1289. Minimum Falling Path Sum II +#include "leetcode.h" + +/* + * given a 'n * n' integer matrix 'grid' return the minimum sum of a falling + * path with non zero shifts. a falling path with non zero shifts is a choice of + * exactly one element from each row of 'grid' such that no two elements chosen + * in adjacent rows are in the same column + */ + +int min(int **grid, int gridSize, int *gridColSize, int curr) { + int min = INT_MAX; + for (int i = 0; i < curr; i++) + if (min > grid[gridSize][i]) + min = grid[gridSize][i]; + for (int i = curr + 1; i < *gridColSize; i++) + if (min > grid[gridSize][i]) + min = grid[gridSize][i]; + return min; +} + +int minFallingPathSum(int **grid, int gridSize, int *gridColSize) { + int **list = (int **)malloc(sizeof(int *) * 2); + list[0] = malloc(sizeof(int) * *gridColSize); + list[1] = malloc(sizeof(int) * *gridColSize); + gridSize--; + int k = gridSize % 2; + for (int i = 0; i < *gridColSize; i++) + list[k][i] = grid[gridSize][i]; + gridSize--; + int other = k; + while (gridSize >= 0) { + k = gridSize % 2; + for (int i = 0; i < *gridColSize; i++) + list[k][i] = min(list, other, gridColSize, i) + grid[gridSize][i]; + other = k; + gridSize--; + } + int ans = min(list, 0, gridColSize, *gridColSize); + free(list[0]), free(list[1]), free(list); + return ans; +} diff --git a/min_falling_path_sum2.py b/min_falling_path_sum2.py new file mode 100644 index 0000000..1cd1c19 --- /dev/null +++ b/min_falling_path_sum2.py @@ -0,0 +1,28 @@ +# 1289. Minimum Falling Path Sum II +from heapq import nsmallest + +""" +given a 'n * n' integer matrix 'grid' return the minimum sum of a falling +path with non zero shifts. a falling path with non zero shifts is a choice of +exactly one element from each row of 'grid' such that no two elements chosen +in adjacent rows are in the same column +""" + + +class Solution(object): + def minFallingPathSum(self, grid): + """ + :type grid: List[List[int]] + :rtype: int + """ + for i in range(1, len(grid)): + r = nsmallest(2, grid[i - 1]) + for j in range(len(grid[0])): + grid[i][j] += r[1] if grid[i - 1][j] == r[0] else r[0] + return min(grid[-1]) + + +if __name__ == "__main__": + obj = Solution() + print(obj.minFallingPathSum(grid=[[1, 2, 3], [4, 5, 6], [7, 8, 9]])) + print(obj.minFallingPathSum(grid=[[7]])) diff --git a/min_flips_abc.c b/min_flips_abc.c new file mode 100644 index 0000000..289304f --- /dev/null +++ b/min_flips_abc.c @@ -0,0 +1,39 @@ +// 1318. Minimum Flips to Make a OR b Equal to c +#include <stdio.h> +#include <stdlib.h> + +/* + * given three positive numbers 'a, b, c'. return the minimum flips required in + * some bits of 'a | b == c'. flip operation consists of changing any single bit + * 1 to 0 or changing the bit 0 to 1 in their binary representation + */ + +int minFlips(int a, int b, int c) { + int *digit = calloc(31, sizeof(int)); + int idx = 0; + while (a) { + digit[idx] += (a & 1); + a >>= 1; + idx++; + } + idx = 0; + while (b) { + digit[idx] += (b & 1); + b >>= 1; + idx++; + } + int ans = 0; + for (int i = 0; i < 31; i++) { + if ((c >> i) & 1) + ans += (digit[i] == 0); + else + ans += digit[i]; + } + return ans; +} + +int main() { + printf("%d\n", minFlips(2, 6, 5)); // expect: 3 + printf("%d\n", minFlips(4, 2, 7)); // expect: 1 + printf("%d\n", minFlips(1, 2, 3)); // expect: 0 +} diff --git a/min_flips_abc.cpp b/min_flips_abc.cpp new file mode 100644 index 0000000..b51b261 --- /dev/null +++ b/min_flips_abc.cpp @@ -0,0 +1,22 @@ +// 1318. Minimum Flips to Make a OR b Equal to c +#include "leetcode.h" + +/* + * given three positive numbers 'a, b, c'. return the minimum flips required in + * some bits of 'a | b == c'. flip operation consists of changing any single bit + * 1 to 0 or changing the bit 0 to 1 in their binary representation + */ + +class Solution { +public: + int minFlips(int a, int b, int c) { + return __builtin_popcount(c ^= a | b) + __builtin_popcount(a & b & c); + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.minFlips(2, 6, 5)); // expect: 3 + printf("%d\n", obj.minFlips(4, 2, 7)); // expect: 1 + printf("%d\n", obj.minFlips(1, 2, 3)); // expect: 0 +} diff --git a/min_flips_bin_string.c b/min_flips_bin_string.c new file mode 100644 index 0000000..d3eef06 --- /dev/null +++ b/min_flips_bin_string.c @@ -0,0 +1,53 @@ +// 1888. Minimum Number of Flips to Make the Binary String Alternating +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * you are given a binary string 's'. you are allowed to perform two types of + * operations on the string in any sequence: 1: remove the character at the + * start of the string 's' and append it to the end of the string. 2: pick any + * characters in 's' and flip its value, ie. if its value is 0 it becomes 1 and + * vice versa. return the minimum number of type-2 operations needed to perform + * such that 's' becomes alternating. the string is called alternating if no two + * adjacent characters are equal. for example, the strings "010" and "1010" are + * alternating, while the string "0110" is not. + */ + +int minFlips(char *s) { + int n = strlen(s), idx = 0, min_ops = INT_MAX, diff1 = 0, diff2 = 0, left = 0, + right = 0; + char *g_str = calloc(1, 2 * n + 1); + char *z_tar = calloc(1, 2 * n + 1); + char *o_tar = calloc(1, 2 * n + 1); + strcat(g_str, s); + strcat(g_str, s); + for (int i = 0; i < 2 * n; i++) { + z_tar[idx] = i % 2 ? '1' : '0'; + o_tar[idx++] = i % 2 ? '0' : '1'; + } + while (right < 2 * n) { + diff1 += g_str[right] != z_tar[right]; + diff2 += g_str[right] != o_tar[right]; + if (right - left + 1 > n) { + if (g_str[left] != z_tar[left]) + diff1--; + if (g_str[left] != o_tar[left]) + diff2--; + left++; + } + if (right - left + 1 == n) + min_ops = fmin(min_ops, fmin(diff1, diff2)); + right++; + } + return min_ops; +} + +int main() { + char s1[] = {"111000"}, s2[] = {"010"}, s3[] = {"1110"}; + printf("%d\n", minFlips(s1)); // expect: 2 + printf("%d\n", minFlips(s2)); // expect: 0 + printf("%d\n", minFlips(s3)); // expect: 1 +} diff --git a/min_flips_bin_string.py b/min_flips_bin_string.py new file mode 100644 index 0000000..8b4b262 --- /dev/null +++ b/min_flips_bin_string.py @@ -0,0 +1,50 @@ +# 1888. Minimum Number of Flips to Make the Binary String Alternating + +""" +you are given a binary string 's'. you are allowed to perform two types of +operations on the string in any sequence: 1: remove the character at the +start of the string 's' and append it to the end of the string. 2: pick any +characters in 's' and flip its value, ie. if its value is 0 it becomes 1 and +vice versa. return the minimum number of type-2 operations needed to perform +such that 's' becomes alternating. the string is called alternating if no two +adjacent characters are equal. for example, the strings "010" and "1010" are +alternating, while the string "0110" is not. +""" + + +class Solution(object): + def minFlips(self, s): + n = len(s) + k = len(s) + s = s if k % 2 == 0 else s + s + arr1, arr2 = [], [] + for i in range(n): + arr1.append("0" if i % 2 == 0 else "1") + arr2.append("1" if i % 2 == 0 else "0") + alt1 = "".join(arr1) + alt2 = "".join(arr2) + diff1, diff2 = 0, 0 + i, j = 0, 0 + while j < n: + if s[j] != alt1[j]: + diff1 += 1 + if s[j] != alt2[j]: + diff2 += 1 + if j - i + 1 < k: + j += 1 + else: + n = min(n, diff1, diff2) + if s[i] != alt1[i]: + diff1 -= 1 + if s[i] != alt2[i]: + diff2 -= 1 + i += 1 + j += 1 + return n + + +if __name__ == "__main__": + obj = Solution() + print(obj.minFlips("111000")) # expect: 2 + print(obj.minFlips("010")) # expect: 0 + print(obj.minFlips("1110")) # expect: 1 diff --git a/min_fuel_report_captial.c b/min_fuel_report_captial.c new file mode 100644 index 0000000..afa0ba1 --- /dev/null +++ b/min_fuel_report_captial.c @@ -0,0 +1,82 @@ +// 2477. Minimum Fuel Cost to Report to the Capital +#include <stdio.h> +#include <stdlib.h> + +/* + * there is a tree (ie. a connected, undirected graph with no cycles) structure + * country network consisting of 'n' cities numbered from 0 to 'n - 1' and + * exactly 'n - 1' roads the capital city is city 0. given a 2d integer array + * 'roads' where 'roads[i] = [ai, bi]' denotes that there exists a bidirectional + * road connecting cities ai & bi. there is a meeting for the representitive of + * each city. the meeting is in the capital city. there is a car in each city. + * given integer seats that indicates the number of seats in each car. a + * representitive can use the car in their city to travel or change the car and + * ride with another representitive. the cost of traveling between two cities is + * 1 liter of fuel. return minimum number of liters of fuel needed to reach + * capital city. + */ + +void dfs(int seats, int from, int now, long long *ans, int **can_go, int *cnt, + int *ppl) { + if (cnt[now] == 1) { + *ppl = 1; + return; + } + int next = 0, next_city = 0; + for (int i = 0; i < cnt[now]; i++) { + if (can_go[now][i] == from) { + i++; + while (i < cnt[now]) { + dfs(seats, now, can_go[now][i], ans, can_go, cnt, &next_city); + *ans += next_city / seats; + if (next_city % seats != 0) + *ans += 1; + next += next_city; + i++; + } + } else { + dfs(seats, now, can_go[now][i], ans, can_go, cnt, &next_city); + *ans += next_city / seats; + if (next_city % seats != 0) + *ans += 1; + next += next_city; + } + } + *ppl = next + 1; + return; +} + +long long minimumFuelCost(int **roads, int roadsSize, int *roadsColSize, + int seats) { + int **can_go = malloc(sizeof(int *) * (roadsSize + 1)); + for (int i = 0; i <= roadsSize; i++) + can_go[i] = malloc(sizeof(int) * 20); + int *cnt = calloc((roadsSize + 1), sizeof(int)); + for (int i = 0; i < roadsSize; i++) { + can_go[roads[i][0]][cnt[roads[i][0]]] = roads[i][1]; + can_go[roads[i][1]][cnt[roads[i][1]]] = roads[i][0]; + cnt[roads[i][0]]++; + cnt[roads[i][1]]++; + } + long long ans = 0; + int ppl = 0; + for (int i = 0; i < cnt[0]; i++) { + dfs(seats, 0, can_go[0][i], &ans, can_go, cnt, &ppl); + ans += (ppl / seats); + if (ppl % seats != 0) + ans += 1; + } + free(cnt); + for (int i = 0; i <= roadsSize; i++) + free(can_go[i]); + free(can_go); + return ans; +} + +int main() { + int roads1[3][2] = {{0, 1}, {0, 2}, {0, 3}}; + int rs1 = 3; + int rcs1[] = {3}; + int seats1 = 5; + printf("%lld\n", minimumFuelCost(roads1, rs1, rcs1, seats1)); +} diff --git a/min_fuel_report_captial.cpp b/min_fuel_report_captial.cpp new file mode 100644 index 0000000..5d13beb --- /dev/null +++ b/min_fuel_report_captial.cpp @@ -0,0 +1,50 @@ +// 2477. Minimum Fuel Cost to Report to the Capital +#include "leetcode.h" + +/* + * there is a tree (ie. a connected, undirected graph with no cycles) structure + * country network consisting of 'n' cities numbered from 0 to 'n - 1' and + * exactly 'n - 1' roads the capital city is city 0. given a 2d integer array + * 'roads' where 'roads[i] = [ai, bi]' denotes that there exists a bidirectional + * road connecting cities ai & bi. there is a meeting for the representitive of + * each city. the meeting is in the capital city. there is a car in each city. + * given integer seats that indicates the number of seats in each car. a + * representitive can use the car in their city to travel or change the car and + * ride with another representitive. the cost of traveling between two cities is + * 1 liter of fuel. return minimum number of liters of fuel needed to reach + * capital city. + */ + +class Solution { +public: + long long minimumFuelCost(vvd(int) & roads, int seats) { + vvd(int) al(roads.size() + 1); + for (auto &r : roads) { + al[r[0]].push_back(r[1]); + al[r[1]].push_back(r[0]); + } + long long ans = 0; + return dfs(0, -1, 0, seats, al, ans); + } + +private: + long long dfs(int i, int prev, int depth, int seats, vvd(int) & al, + long long &ans) { + long long riders = 1; + for (int j : al[i]) + if (j != prev) + riders += dfs(j, i, depth + 1, seats, al, ans); + if (depth == 0) + return ans; + ans += (riders / seats) * depth + (riders % seats ? 1 : 0); + return riders % seats; + } +}; + +int main() { + Solution obj; + vvd(int) roads1 = {{0, 1}, {0, 2}, {0, 3}}; + vvd(int) roads2 = {{3, 1}, {3, 2}, {1, 0}, {0, 4}, {0, 5}, {4, 6}}; + cout << obj.minimumFuelCost(roads1, 5) << endl; // expect: 3 + cout << obj.minimumFuelCost(roads2, 2) << endl; // expect: 7 +} diff --git a/min_genetic_mutation.cpp b/min_genetic_mutation.cpp new file mode 100644 index 0000000..8bbf503 --- /dev/null +++ b/min_genetic_mutation.cpp @@ -0,0 +1,33 @@ +#include "leetcode.h" + +class Solution { +public: + int minMutation(string start, string end, vector<string> &bank) { + deque<pair<string, int>> dqp({{start, 0}}); + set<string> s(bank.begin(), bank.end()); + vector<char> nucleotides = {'A', 'T', 'G', 'C'}; + while (!dqp.empty()) { + auto [g, m] = dqp.front(); + dqp.pop_front(); + if (g == end) + return m; + for (int i = 0; i < g.size(); ++i) + for (char n : nucleotides) { + string gm = g; + gm[i] = n; + if (s.count(gm)) { + s.erase(gm); + dqp.emplace_back(gm, m + 1); + } + } + } + return -1; + } +}; + +int main() { + Solution obj; + string start = "AACCGGTT", end = "AACCGGTA"; + vector<string> bank = {"AACCGGTA"}; + cout << obj.minMutation(start, end, bank); +} diff --git a/min_genetic_mutation.rs b/min_genetic_mutation.rs new file mode 100644 index 0000000..1362636 --- /dev/null +++ b/min_genetic_mutation.rs @@ -0,0 +1,53 @@ +use std::collections::HashSet; +struct Solution; + +impl Solution { + pub fn min_mutation(start: String, end: String, mut bank: Vec<String>) -> i32 { + match bank.iter().position(|w| end.eq(w)) { + None => return -1, + Some(idx) => bank.swap_remove(idx) + }; + let (mut left, mut right, mut next) = (HashSet::new(), HashSet::new(), HashSet::new()); + left.insert(start); + right.insert(end); + let mut len = 0; + while !left.is_empty() && !right.is_empty() { + if left.len() > right.len() { + std::mem::swap(&mut left, &mut right); + } + for w in left.drain() { + let mut idx = 0; + for word in right.iter() { + if Self::is_adjacent(&w, word.as_str()) { + return len + 1; + } + } + while idx < bank.len() { + if !is_adjacent(&w, &bank[idx]) { + idx += 1; + continue; + } + let neighbor = bank.swap_remove(idx); + next.insert(neighbor); + } + } + std::mem::swap(&mut left, &mut next); + len += 1; + } + -1 + } + fn is_adjacent(a: &str, b: &str) -> bool { + let (a, b) = (a.as_bytes(), b.as_bytes()); + assert_eq!(a.len(), b.len()); + let mut diff = 0; + for idx in 0..a.len() { + if a[idx] != b[idx] { + diff += 1; + } + if diff > 1 { + break; + } + } + diff == 1 + } +} diff --git a/min_height_tree.c b/min_height_tree.c new file mode 100644 index 0000000..a5cac34 --- /dev/null +++ b/min_height_tree.c @@ -0,0 +1,64 @@ +// 310. Minimum Height Trees +#include "leetcode.h" + +/* + * a tree is an undirected graph in which any two vertices are connected by + * exactly one path. in other words, any connected graph without simple cycles + * is a tee. given a tree of 'n' nodes from 0 to 'n - 1' and an array of 'n - 1' + * edges where 'edges[i] = [ai, bi]' indicates that there is an undirected edge + * between the two nodes 'ai' and 'bi'in the the tree, you can choose any node + * of the tree as the root. return a list of all mht's root labels. you can + * return the answer in any order. + */ + +int *findMinHeightTrees(int n, int **edges, int edgesSize, int *edgesColSize, + int *returnSize) { + int *ans = (int *)malloc(sizeof(int) * n); + *returnSize = 0; + if (n == 1) { + (*returnSize)++; + ans[*returnSize - 1] = 0; + return ans; + } + int **graph = (int **)malloc(sizeof(int *) * n); + for (int i = 0; i < n; i++) + graph[i] = (int *)malloc(sizeof(int)); + int *col_sizes = (int *)calloc(n, sizeof(int)); + for (int i = 0; i < *returnSize; i++) { + int begin = edges[i][0], end = edges[i][1]; + col_sizes[begin]++; + graph[begin] = (int *)realloc(graph[begin], sizeof(int) * col_sizes[begin]); + graph[begin][col_sizes[begin] - 1] = end; + col_sizes[end]++; + graph[end] = (int *)realloc(graph[end], sizeof(int) * col_sizes[end]); + graph[end][col_sizes[end] - 1] = begin; + } + int *degrees = (int *)malloc(sizeof(int) * n); + for (int i = 0; i < n; i++) { + degrees[i] = col_sizes[i]; + if (col_sizes[i] == 1) { + (*returnSize)++; + ans[*returnSize - 1] = i; + } + } + int cnt = n, next = 0; + int *next_level = (int *)malloc(sizeof(int) * n); + while (cnt > 2) { + for (int i = 0; i < *returnSize; i++) { + int end = ans[i]; + cnt--; + for (int k = 0; k < col_sizes[end]; k++) { + int begin = graph[end][k]; + degrees[begin]--; + if (degrees[begin] == 1) + next_level[next++] = graph[end][k]; + } + } + *returnSize = next; + next = 0; + int *tmp = ans; + ans = next_level; + next_level = tmp; + } + return ans; +} diff --git a/min_height_tree.py b/min_height_tree.py new file mode 100644 index 0000000..2f8c0b1 --- /dev/null +++ b/min_height_tree.py @@ -0,0 +1,43 @@ +# 310. Minimum Height Trees + +""" +a tree is an undirected graph in which any two vertices are connected by +exactly one path. in other words, any connected graph without simple cycles +is a tee. given a tree of 'n' nodes from 0 to 'n - 1' and an array of 'n - 1' +edges where 'edges[i] = [ai, bi]' indicates that there is an undirected edge +between the two nodes 'ai' and 'bi'in the the tree, you can choose any node +of the tree as the root. return a list of all mht's root labels. you can +return the answer in any order. +""" + + +class Solution(object): + def findMinHeightTrees(self, n, edges): + """ + :type n: int + :type edges: List[List[int]] + :rtype: List[int] + """ + if n == 1: + return [0] + adj = [set() for _ in range(n)] + for i, j in edges: + adj[i].add(j) + adj[j].add(i) + leaves = [i for i in range(n) if len(adj[i]) == 1] + while n > 2: + n -= len(leaves) + new_leaves = [] + for i in leaves: + j = adj[i].pop() + adj[j].remove(i) + if len(adj[j]) == 1: + new_leaves.append(j) + leaves = new_leaves + return leaves + + +if __name__ == "__main__": + obj = Solution() + print(obj.findMinHeightTrees(n=4, edges=[[1, 0], [1, 2], [1, 3]])) + print(obj.findMinHeightTrees(n=6, edges=[[3, 0], [3, 1], [3, 2], [3, 4], [5, 4]])) diff --git a/min_incr_arr_unique.c b/min_incr_arr_unique.c new file mode 100644 index 0000000..8344521 --- /dev/null +++ b/min_incr_arr_unique.c @@ -0,0 +1,31 @@ +// 945. Minimum Increment to Make Array Unique +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array 'nums'. in one move, you can pick an index 'i' where + * '0 <= i < nums.length' and increment 'nums[i]' by 1. return the minimum + * number of moves to make every value in 'nums' unique. the test cases are + * generated so that the answer fits in a 32-bit integer. + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int minIncrementForUnique(int *nums, int nums_size) { + qsort(nums, nums_size, sizeof(int), cmp); + int ans = 0, min = nums[0]; + for (int i = 1; i < nums_size; i++) { + if (nums[i] <= min) { + ans += (min + 1 - nums[i]); + nums[i] = min + 1; + } + min = nums[i]; + } + return ans; +} + +int main() { + int n1[] = {1, 2, 2}, n2[] = {3, 2, 1, 2, 1, 7}; + printf("%d\n", minIncrementForUnique(n1, 3)); // expect: 1 + printf("%d\n", minIncrementForUnique(n2, 6)); // expect: 6 +} diff --git a/min_incr_arr_unique.cpp b/min_incr_arr_unique.cpp new file mode 100644 index 0000000..9121d48 --- /dev/null +++ b/min_incr_arr_unique.cpp @@ -0,0 +1,32 @@ +// 945. Minimum Increment to Make Array Unique +#include "leetcode.h" + +/* + * given an integer array 'nums'. in one move, you can pick an index 'i' where + * '0 <= i < nums.length' and increment 'nums[i]' by 1. return the minimum + * number of moves to make every value in 'nums' unique. the test cases are + * generated so that the answer fits in a 32-bit integer. + */ + +class Solution { +public: + int minIncrementForUnique(vector<int> &nums) { + int n = nums.size(), ans = 0; + if (n < 2) + return 0; + sort(nums.begin(), nums.end()); + for (int i = 1; i < n; ++i) + if (nums[i] <= nums[i - 1]) { + ans += nums[i - 1] + 1 - nums[i]; + nums[i] = nums[i - 1] + 1; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 2, 2}, n2 = {3, 2, 1, 2, 1, 7}; + printf("%d\n", obj.minIncrementForUnique(n1)); // expect: 1 + printf("%d\n", obj.minIncrementForUnique(n2)); // expect: 6 +} diff --git a/min_increment_arr_unique.c b/min_increment_arr_unique.c new file mode 100644 index 0000000..f8aa1d8 --- /dev/null +++ b/min_increment_arr_unique.c @@ -0,0 +1,30 @@ +// 945. Minimum Increment to Make Array Unique +#include "leetcode.h" + +/* + * given an integer array 'nums'. in one move you can pick an index i where 0 <= + * i < nums.len and increment nums[i] by 1. return the minimum number of moves + * to make every value in nums unique. the test cases are generated so that the + * answer fits in a 32 bit integer. + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int minIncrementForUnique(int *nums, int numsSize) { + int ans = 0, min; + qsort(nums, numsSize, sizeof(int), cmp); + for (int i = 1; i < numsSize; i++) { + min = nums[0]; + if (nums[i] > min) + min = nums[i]; + else + ans += (++min) - nums[i]; + } + return ans; +} + +int main() { + int n1[] = {1, 2, 2}, n2[] = {3, 2, 1, 2, 1, 7}; + printf("%d\n", minIncrementForUnique(n1, sizeof(n1))); // expect: 1 + printf("%d\n", minIncrementForUnique(n2, sizeof(n2))); // expect: 1 +} diff --git a/min_increment_arr_unique.py b/min_increment_arr_unique.py new file mode 100644 index 0000000..702d13f --- /dev/null +++ b/min_increment_arr_unique.py @@ -0,0 +1,27 @@ +# 945. Minimum Increment to Make Array Unique + +""" +given an integer array 'nums'. in one move you can pick an index i where 0 <= +i < nums.len and increment nums[i] by 1. return the minimum number of moves +to make every value in nums unique. the test cases are generated so that the +answer fits in a 32 bit integer. +""" + + +class Solution(object): + def minIncrementForUnique(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + ans, need = 0, 0 + for i in sorted(nums): + ans += max(need - i, 0) + need = max(need + 1, i + 1) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.minIncrementForUnique([1, 2, 2])) + print(obj.minIncrementForUnique([3, 2, 1, 2, 1, 7])) diff --git a/min_insertion_make_palindrome.c b/min_insertion_make_palindrome.c new file mode 100644 index 0000000..b993e9d --- /dev/null +++ b/min_insertion_make_palindrome.c @@ -0,0 +1,47 @@ +// 1312. Minimum Insertion Steps to Make a String Palindrome +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given string 's'. in one step you can insert any character at any index of + * the string. return the minimum number of steps to make 's' palindrome. a + * palindrome string is one that reads the same backward as well as forward. + */ + +int minInsertions(char *s) { + int n = strlen(s); + int **dp = malloc(n * sizeof(int)); + for (int i = 0; i < n; i++) + dp[i] = calloc(n, sizeof(int)); + for (int i = 0; i < n; i++) + dp[i][i] = 1; + for (int i = 0; i < n - 1; i++) { + if (s[i] == s[i + 1]) + dp[i][i + 1] = 2; + else + dp[i][i + 1] = 1; + } + for (int len = 2; len <= n; len++) { + for (int i = 0; i <= n - len; i++) { + int j = i + len - 1; + if (s[i] == s[j]) + dp[i][j] = 2 + dp[i + 1][j - 1]; + else + dp[i][j] = fmax(dp[i + 1][j], dp[i][j - 1]); + } + } + int ans = n - dp[0][n - 1]; + for (int i = 0; i < n; i++) + free(dp[i]); + free(dp); + return ans; +} + +int main() { + char s1[] = {"zzazz"}, s2[] = {"mbadm"}, s3[] = {"leetcode"}; + printf("%d\n", minInsertions(s1)); // expect: 0; + printf("%d\n", minInsertions(s2)); // expect: 2; + printf("%d\n", minInsertions(s3)); // expect: 5; +} diff --git a/min_insertion_make_palindrome.cpp b/min_insertion_make_palindrome.cpp new file mode 100644 index 0000000..7af74da --- /dev/null +++ b/min_insertion_make_palindrome.cpp @@ -0,0 +1,32 @@ +// 1312. Minimum Insertion Steps to Make a String Palindrome +#include "leetcode.h" + +/* + * given string 's'. in one step you can insert any character at any index of + * the string. return the minimum number of steps to make 's' palindrome. a + * palindrome string is one that reads the same backward as well as forward. + */ + +class Solution { +public: + int minInsertions(string s) { + vector<int> memo(s.size(), 0); + int prv, tmp; + for (int i = s.size() - 2; i >= 0; i--) { + prv = 0; + for (int j = i; j < s.size(); j++) { + tmp = memo[j]; + memo[j] = s[i] == s[j] ? prv : 1 + min(memo[j], memo[j - 1]); + prv = tmp; + } + } + return memo[s.size() - 1]; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.minInsertions("zzazz")); // expect: 0 + printf("%d\n", obj.minInsertions("mbadm")); // expect: 2 + printf("%d\n", obj.minInsertions("leetcode")); // expect: 5 +} diff --git a/min_jump_reach_home.cpp b/min_jump_reach_home.cpp new file mode 100644 index 0000000..4a66f27 --- /dev/null +++ b/min_jump_reach_home.cpp @@ -0,0 +1,44 @@ +#include "leetcode.h" + +class Solution { +public: + int minimumJumps(vector<int> &forbidden, int a, int b, int x) { + unordered_set<int> f(forbidden.begin(), forbidden.end()); + vvd(int) visited(2, vector<int>(5000)); + queue<pair<int, bool>> qp; + qp.push({0, false}); + visited[0][0] = 1; + visited[1][0] = 1; + int ans = 0; + while (!qp.empty()) { + int len = qp.size(); + while (len > 0) { + len--; + int curr = qp.front().first; + bool flag = qp.front().second; + if (curr == x) + return ans; + qp.pop(); + int forward = curr + a, backward = curr - b; + if (forward < 5000 && visited[0][forward] == 0 && !f.count(forward)) { + qp.push({forward, false}); + visited[0][forward] = 1; + } + if (backward >= 0 && visited[1][backward] == 0 && !f.count(backward) && + !flag) { + qp.push({backward, true}); + visited[1][backward] = 1; + } + } + ans++; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> forbidden = {14, 4, 18, 1, 15}; + int a = 3, b = 15, x = 9; + cout << obj.minimumJumps(forbidden, a, b, x); +} diff --git a/min_len_str_del_end.c b/min_len_str_del_end.c new file mode 100644 index 0000000..d19c782 --- /dev/null +++ b/min_len_str_del_end.c @@ -0,0 +1,33 @@ +// 1750. Minimum Length of String After Deleting Similar Ends +#include "leetcode.h" + +/* + * given a string 's' consisting of only characters a, b, and c you are asked to + * apply the following algorithm on the string any number of times. first, pick + * a non-empty prefix from the string 's' where all the characters in the prefix + * are equal. next, pick a non-empty suffix from the string 's' where all the + * characters in the suffix are equal. the prefix and the suffix should not + * intersect at any index. the characters from the prefix and the suffix must be + * the same. delete both the prefix and the suffix. return the minimum length of + * 's' after performining the above operation any number of times. + */ + +int minimumLength(char *s) { + int n = strlen(s); + int left = 0, right = n - 1; + while (left < n && right > left && s[left] == s[right]) { + char c = s[left]; + while (s[left] == c) + left++; + while (right > left && s[right] == c) + right--; + } + return right - left + 1; +} + +int main() { + char *s1 = "ca", *s2 = "cabaabac", *s3 = "aabccabba"; + printf("%d\n", minimumLength(s1)); // expect: 2 + printf("%d\n", minimumLength(s2)); // expect: 0 + printf("%d\n", minimumLength(s3)); // expect: 3 +} diff --git a/min_len_str_del_end.py b/min_len_str_del_end.py new file mode 100644 index 0000000..409410d --- /dev/null +++ b/min_len_str_del_end.py @@ -0,0 +1,30 @@ +# 1750. Minimum Length of String After Deleting Similar Ends + +""" +g given a string 's' consisting of only characters a, b, and c you are asked to +g apply the following algorithm on the string any number of times. first, pick +g a non-empty prefix from the string 's' where all the characters in the prefix +g are equal. next, pick a non-empty suffix from the string 's' where all the +g characters in the suffix are equal. the prefix and the suffix should not +g intersect at any index. the characters from the prefix and the suffix must be +g the same. delete both the prefix and the suffix. return the minimum length of +g 's' after performining the above operation any number of times. +""" + + +class Solution(object): + def minimumLength(self, s): + """ + :type s: str + :rtype: int + """ + while len(s) > 1 and s[0] == s[-1]: + s = s.strip(s[0]) + return len(s) + + +if __name__ == "__main__": + obj = Solution() + print(obj.minimumLength("ca")) + print(obj.minimumLength("cabaabac")) + print(obj.minimumLength("aabccabba")) diff --git a/min_max_array.c b/min_max_array.c new file mode 100644 index 0000000..441c9b4 --- /dev/null +++ b/min_max_array.c @@ -0,0 +1,28 @@ +// 2439. Minimize Maximum of Array +#include <stdio.h> +#include <stdlib.h> + +/* + * given a 0-indexed array 'nums' comprising of n unsigned integers. ine one + * operation you must choose an integer 'i' such that '1 <= i < n' and 'nums[i] + * > 0'. decrease 'nums[i]' by 1 or increase 'nums[i]' by 1. return minimum + * possible value of the max integer 'nums' after performing any number of + * operations. + */ + +#define MAX(a, b) a > b ? a : b + +int minmizeArrayValue(int *nums, int nums_size) { + long long ans, pre = 0; + for (int i = 0; i < nums_size; i++) { + pre += nums[i]; + ans = MAX(ans, (pre + i) / (i + 1)); + } + return ans; +} + +int main() { + int n1[] = {3, 7, 1, 6}, n2[] = {10, 1}; + printf("%d\n", minmizeArrayValue(n1, 4)); // expect: 5 + printf("%d\n", minmizeArrayValue(n2, 2)); // expect: 10 +} diff --git a/min_max_array.cpp b/min_max_array.cpp new file mode 100644 index 0000000..6da3f2b --- /dev/null +++ b/min_max_array.cpp @@ -0,0 +1,43 @@ +// 2439. Minimize Maximum of Array +#include "leetcode.h" + +/* + * given a 0-indexed array 'nums' comprising of n unsigned integers. ine one + * operation you must choose an integer 'i' such that '1 <= i < n' and 'nums[i] + * > 0'. decrease 'nums[i]' by 1 or increase 'nums[i]' by 1. return minimum + * possible value of the max integer 'nums' after performing any number of + * operations. + */ + +class Solution { + bool valid(vector<int> &nums, int mid) { + long sum = 0; + for (int i = 0; i < nums.size(); i++) { + sum += nums[i]; + if (sum > (long)mid * (i + 1)) + return false; + } + return true; + } + +public: + int minimizeArrayValue(vector<int> &nums) { + int left = 0, right = *max_element(nums.begin(), nums.end()), ans = 0; + while (left <= right) { + int mid = (left + right) >> 1; + if (valid(nums, mid)) { + ans = mid; + right = mid - 1; + } else + left = mid + 1; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {3, 7, 1, 6}, n2 = {10, 1}; + printf("%d\n", obj.minimizeArrayValue(n1)); // expect: 5 + printf("%d\n", obj.minimizeArrayValue(n2)); // expect: 10 +} diff --git a/min_max_diff_pair.c b/min_max_diff_pair.c new file mode 100644 index 0000000..6172bc7 --- /dev/null +++ b/min_max_diff_pair.c @@ -0,0 +1,38 @@ +// 2616. Minimize the Maximum Difference of Pairs +#include <stdio.h> +#include <stdlib.h> + +/* + * given a 0-indexed integer array 'nums' and an integer 'p'. find 'p' pairs of + * indices of 'nums' such that the maximum difference amongst all the pairs is + * minimised. also, ensure no index appears more than once amongst that 'p' + * pairs. note that for a pair of elements at the index 'i' and 'j'. the + * difference of this pair is '|nums[i] - nums[j]|', where '|x|' represents the + * absolute value of 'x'. return the minimum maximum difference among all 'p' + * pairs. we define the maximum of an empty set to be zero. + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int minimizeMax(int *nums, int nums_size, int p) { + qsort(nums, nums_size, sizeof(int), cmp); + int i, j, left = 0, right = nums[nums_size - 1] - nums[0]; + while (left < right) { + int mid = (left + right) / 2; + int cnt = 0; + for (int i = 0; i + 1 < nums_size; ++i) + if (mid >= nums[i + 1] - nums[i]) + ++cnt, ++i; + if (cnt >= p) + right = mid; + else + left = mid + 1; + } + return left; +} + +int main() { + int n1[] = {10, 1, 2, 7, 1, 3}, n2[] = {4, 2, 1, 2}; + printf("%d\n", minimizeMax(n1, 6, 2)); // expect: 1 + printf("%d\n", minimizeMax(n2, 4, 1)); // expect: 0 +} diff --git a/min_max_diff_pair.cpp b/min_max_diff_pair.cpp new file mode 100644 index 0000000..ac6dc3b --- /dev/null +++ b/min_max_diff_pair.cpp @@ -0,0 +1,47 @@ +// 2616. Minimize the Maximum Difference of Pairs +#include "leetcode.h" + +/* + * given a 0-indexed integer array 'nums' and an integer 'p'. find 'p' pairs of + * indices of 'nums' such that the maximum difference amongst all the pairs is + * minimised. also, ensure no index appears more than once amongst that 'p' + * pairs. note that for a pair of elements at the index 'i' and 'j'. the + * difference of this pair is '|nums[i] - nums[j]|', where '|x|' represents the + * absolute value of 'x'. return the minimum maximum difference among all 'p' + * pairs. we define the maximum of an empty set to be zero. + */ + +class Solution { + bool can_form_pair(vector<int> &nums, int p, int mid) { + int cnt = 0; + for (int i = 0; i < nums.size() - 1 && cnt < p;) { + if (nums[i + 1] - nums[i] <= mid) { + cnt++; + i += 2; + } else + i++; + } + return cnt >= p; + } + +public: + int minimizeMax(vector<int> &nums, int p) { + sort(nums.begin(), nums.end()); + int left = 0, right = nums.end() - nums.begin(); + while (left < right) { + int mid = (left + right) / 2; + if (can_form_pair(nums, p, mid)) + right = mid; + else + left = mid + 1; + } + return left; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {10, 1, 2, 7, 1, 3}, n2 = {4, 2, 1, 2}; + printf("%d\n", obj.minimizeMax(n1, 2)); // expect: 1 + printf("%d\n", obj.minimizeMax(n2, 1)); // expect: 0 +} diff --git a/min_max_pair_arr.c b/min_max_pair_arr.c new file mode 100644 index 0000000..f233ca1 --- /dev/null +++ b/min_max_pair_arr.c @@ -0,0 +1,31 @@ +// 1877. Minimize Maximum Pair Sum in Array +#include "leetcode.h" + +/* + * the pair sum of pair '(a, b)' is equal to 'a + b'. the maximum pair sum is + * the largest pair sum in a list of pairs. given an array 'nums' of even length + * 'n', pair up the lements of 'nums' into 'n / 2' pairs such that each element + * of 'nums' is in exactly one pair and the maximum pair sum is minimised. + * return the minimised maximium pair sum after optimally pairing up the + * elements. + */ + +int cmp(const void *a, const void *b) { + return *(const int *)a - *(const int *)b; +} + +int minPairSum(int *nums, int nums_size) { + qsort(nums, nums_size, sizeof(int), cmp); + int start = 0, end = nums_size - 1, ans = 0; + while (start < end) { + int tmp = nums[start++] + nums[end--]; + ans = tmp > ans ? tmp : ans; + } + return ans; +} + +int main() { + int n1[] = {3, 5, 2, 3}, n2[] = {3, 5, 4, 2, 4, 6}; + printf("%d\n", minPairSum(n1, ARRAY_SIZE(n1))); // expect: 7 + printf("%d\n", minPairSum(n2, ARRAY_SIZE(n2))); // expect: 8 +} diff --git a/min_max_pair_arr.py b/min_max_pair_arr.py new file mode 100644 index 0000000..1a7dba3 --- /dev/null +++ b/min_max_pair_arr.py @@ -0,0 +1,25 @@ +# 1877. Minimize Maximum Pair Sum in Array + +""" +the pair sum of pair '(a, b)' is equal to 'a + b'. the maximum pair sum is +the largest pair sum in a list of pairs. given an array 'nums' of even length +'n', pair up the lements of 'nums' into 'n / 2' pairs such that each element +of 'nums' is in exactly one pair and the maximum pair sum is minimised. +return the minimised maximium pair sum after optimally pairing up the +elements. +""" + + +class Solution(object): + def minPairSum(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + return max(a + b for a, b in zip(sorted(nums), sorted(nums)[::-1])) + + +if __name__ == "__main__": + obj = Solution() + print(obj.minPairSum([3, 5, 2, 3])) # expect: 7 + print(obj.minPairSum([3, 5, 4, 2, 4, 6])) # expect: 8 diff --git a/min_money_required_trans.c b/min_money_required_trans.c new file mode 100644 index 0000000..f49718b --- /dev/null +++ b/min_money_required_trans.c @@ -0,0 +1,40 @@ +// 2412. Minimum Money Required Before Transactions +#include "leetcode.h" + +/* + * given a 0-indexed 2d integer array 'transactions' where 'transactions[i] = + * [cost_i, cashback_i]'. the array describes transactions where each + * transaction must be completed exactly once in some order. atany given moment + * you have a certain amoiunt of money in order to complete transaction 'i', + * money must be greater than or equal to cost[i]. after performing a + * transaction, 'money' becomes 'money - cost[i] + cashback[i]'. return the + * minimum amount of 'money' required before any transaction so that all the + * transactions can be completed regardless of the order of transactions. + */ + +long long minimumMoney(int **transactions, int transactionsSize, + int *transactionsColSize) { + long long ans = 0; + int cashback = 0, money = -1; + for (int i = 0; i < transactionsSize; i++) + if (transactions[i][0] > transactions[i][1]) { + ans += transactions[i][0] - transactions[i][1]; + if (cashback < transactions[i][1]) + cashback = transactions[i][1]; + } else { + if (money < transactions[i][0]) + money = transactions[i][0]; + } + ans += cashback < money ? money : cashback; + return ans; +} + +int main() { + int t1[2][3], t2[2][2], tcs1[] = {2, 2, 2}, tcs2[] = {2, 2}; + t1[0][0] = 2, t1[0][1] = 5, t1[0][2] = 4; + t1[1][0] = 1, t1[1][1] = 0, t1[1][2] = 2; + t2[0][0] = 3, t2[0][1] = 0, t2[1][0] = 0, t2[1][1] = 3; + printf("%lld\n", minimumMoney((int **)t1, ARRAY_SIZE(t1), tcs1)); // expect: + // 10 + printf("%lld\n", minimumMoney((int **)t2, ARRAY_SIZE(t2), tcs2)); // expect: 3 +} diff --git a/min_money_required_trans.py b/min_money_required_trans.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/min_money_required_trans.py diff --git a/min_move_palindrome.c b/min_move_palindrome.c new file mode 100644 index 0000000..3355500 --- /dev/null +++ b/min_move_palindrome.c @@ -0,0 +1,76 @@ +// 2193. Minimum Number of Moves to Make Palindrome +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a string 's' consisting of only lowercase ascii characters. + * in one move you can select any two adjacent characters of 's' + * and swap them. return the minimum number of moves needed to + * make 's' a palindrome. note that the input will be generated + * such that 's' can always be converted to a palindrome + */ + +void helper(char *s, int now, int len, int *ans) { + while (now < len) { + while (s[len] == 'A') + len--; + if (s[now] == s[len]) + return; + else { + int copy = now + 1; + if (s[copy] == 'A') + *ans -= 1; + while (s[len] != s[copy]) { + copy++; + if (s[copy] == 'A') + *ans -= 1; + } + *ans += copy - now; + s[copy] = 'A'; + len--; + } + } +} + +void find_min(char *s, int now, int len, int *ans) { + while (now < len) { + while (s[now] == 'A') + now++; + while (s[len] == 'A') + len--; + if (s[now] == s[len]) { + now++; + len--; + } else { + int copy = len - 1, copy_a = *ans; + if (s[copy] == 'A') + *ans -= 1; + while (s[now] != s[copy]) { + copy--; + if (s[copy] == 'A') + *ans -= 1; + } + if (copy != now) { + *ans += len - copy; + s[copy] = 'A'; + } else { + *ans = copy_a; + helper(s, now, len, ans); + } + now++; + } + } +} + +int minMovesToMakePalindrome(char *s) { + int len = strlen(s), ans = 0; + find_min(s, 0, len - 1, &ans); + return ans; +} + +int main() { + char s1[] = {"aabb"}, s2[] = {"letelt"}; + printf("%d\n", minMovesToMakePalindrome(s1)); // expect: 2 + printf("%d\n", minMovesToMakePalindrome(s2)); // expect: 2 +} diff --git a/min_move_palindrome.cpp b/min_move_palindrome.cpp new file mode 100644 index 0000000..6455889 --- /dev/null +++ b/min_move_palindrome.cpp @@ -0,0 +1,34 @@ +// 2193. Minimum Number of Moves to Make Palindrome +#include "leetcode.h" + +/* + * given a string 's' consisting of only lowercase ascii characters. + * in one move you can select any two adjacent characters of 's' + * and swap them. return the minimum number of moves needed to + * make 's' a palindrome. note that the input will be generated + * such that 's' can always be converted to a palindrome + */ + +class Solution { +public: + int minMovesToMakePalindrome(string s) { + int ans = 0; + while (s.size()) { + int i = s.find(s.back()); + if (8 == s.size() - 1) + ans += i / 2; + else { + ans += i; + s.erase(i, 1); + } + s.pop_back(); + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.minMovesToMakePalindrome("aabb"); // expect: 2 + cout << obj.minMovesToMakePalindrome("letelt"); // expect: 2 +} diff --git a/min_moves_equal_array.c b/min_moves_equal_array.c new file mode 100644 index 0000000..4a4b42e --- /dev/null +++ b/min_moves_equal_array.c @@ -0,0 +1,23 @@ +// 453. Minimum Moves to Equal Array Elements +#include "leetcode.h" + +/* + * given an integer array 'nums' of size 'n', return the minimum number of moves + * required to make all array elements equal. in one move you can increment 'n - + * 1' elements of the array by 1 + */ + +int minMoves(int *nums, int numsSize) { + int sum = 0, min = nums[0]; + for (int i = 0; i < numsSize; i++) { + sum += nums[i]; + min = fmin(min, nums[i]); + } + return sum - numsSize * min; +} + +int main() { + int n1[] = {1, 2, 3}, n2[] = {1, 1, 1}; + printf("%d\n", minMoves(n1, ARRAY_SIZE(n1))); // expect: 3 + printf("%d\n", minMoves(n2, ARRAY_SIZE(n2))); // expect: 0 +} diff --git a/min_moves_equal_array.py b/min_moves_equal_array.py new file mode 100644 index 0000000..fa909cd --- /dev/null +++ b/min_moves_equal_array.py @@ -0,0 +1,22 @@ +# 453. Minimum Moves to Equal Array Elements + +""" +given an integer array 'nums' of size 'n', return the minimum number of moves +required to make all array elements equal. in one move you can increment 'n - +1' elements of the array by 1 +""" + + +class Solution(object): + def minMoves(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + return sum(nums) - len(nums) * min(nums) + + +if __name__ == "__main__": + obj = Solution() + print(obj.minMoves([1, 2, 3])) + print(obj.minMoves([1, 1, 1])) diff --git a/min_moves_equal_array2.cpp b/min_moves_equal_array2.cpp new file mode 100644 index 0000000..e5fcfd0 --- /dev/null +++ b/min_moves_equal_array2.cpp @@ -0,0 +1,18 @@ +#include "leetcode.h" + +class Solution { +public: + int minMoves2(vector<int> &nums) { + sort(nums.begin(), nums.end()); + int mid = nums.size() / 2, steps = 0; + for (int i = 0; i < nums.size(); i++) + steps += abs(nums[i] - nums[mid]); + return steps; + } +}; + +int main() { + Solution obj; + vector<int> nums = {1, 2, 3}; + cout << obj.minMoves2(nums); +} diff --git a/min_num_arrow_balloon.c b/min_num_arrow_balloon.c new file mode 100644 index 0000000..57dfaa2 --- /dev/null +++ b/min_num_arrow_balloon.c @@ -0,0 +1,53 @@ +// 452. Minimum Number of Arrows to Burst Balloons +#include "leetcode.h" + +/* + * there are some spherical balloons taped onto a flat wall that represents the + * xy plane. the ballooons are represented as a 2d integer array 'points' where + * 'points[i] = [x_start, x_end]'. you do not know the exact y coordinates of + * the balloons. arrows can be shot up directly vertically in the positive y + * direction. from different points along the x axis. given the array points, + * return the minimum number of arrows that must be shot to burst all balloons. + */ + +int cmp(const void **p1, const void **p2) { + int *arr1 = *(int **)p1; + int *arr2 = *(int **)p2; + if (arr1[1] == arr2[1]) { + if (arr1[0] == arr2[0]) + return 0; + else if (arr1[0] > arr2[0]) + return 1; + else + return -1; + } else { + if (arr1[1] == arr2[1]) + return 0; + else if (arr1[1] > arr2[1]) + return 1; + else + return -1; + } +} + +int findMinArrowShots(int **points, int pointsSize, int *pointsColSize) { + qsort(points, pointsSize, sizeof(int *), cmp); + int k = points[0][1], cnt = 1; + for (int i = 1; i < pointsSize; i++) { + if (points[i][0] > k) { + cnt++; + k = points[i][1]; + } + } + return cnt; +} + +int main() { + int p1[4][2] = {{10, 16}, {2, 8}, {1, 6}, {7, 12}}, + p2[4][4] = {{1, 2}, {3, 4}, {5, 6}, {7, 8}}; + int pcs1, pcs2; + printf("%d\n", + findMinArrowShots((int **)p1, ARRAY_SIZE(p1), &pcs1)); // expect: 2 + printf("%d\n", + findMinArrowShots((int **)p2, ARRAY_SIZE(p2), &pcs2)); // expect: 2 +} diff --git a/min_num_arrow_balloon.cpp b/min_num_arrow_balloon.cpp new file mode 100644 index 0000000..fc8699f --- /dev/null +++ b/min_num_arrow_balloon.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + int findMinArrowShots(vvd(int) & points) { + if (points.size() == 0) + return 0; + sort(points.begin(), points.end(), cmp); + int arrows = 1, end = points[0][1]; + for (int i = 1; i < points.size(); i++) + if (points[i][0] > end) { + arrows++; + end = points[i][1]; + } + return arrows; + } + +private: + static bool cmp(vector<int> &x, vector<int> &y) { return x[1] < y[1]; } +}; + +int main() { + Solution obj; + vvd(int) points1 = {{10, 16}, {2, 8}, {1, 6}, {7, 12}}, + points2 = {{1, 2}, {3, 4}, {5, 6}, {7, 8}}, + points3 = {{1, 2}, {2, 3}, {3, 4}, {4, 5}}; + cout << obj.findMinArrowShots(points1) << endl; // expect: 2 + cout << obj.findMinArrowShots(points2) << endl; // expect: 4 + cout << obj.findMinArrowShots(points3) << endl; // expect: 2 +} diff --git a/min_num_arrow_balloon.py b/min_num_arrow_balloon.py new file mode 100644 index 0000000..650cd00 --- /dev/null +++ b/min_num_arrow_balloon.py @@ -0,0 +1,31 @@ +# 452. Minimum Number of Arrows to Burst Balloons + +""" +there are some spherical balloons taped onto a flat wall that represents the +xy plane. the ballooons are represented as a 2d integer array 'points' where +'points[i] = [x_start, x_end]'. you do not know the exact y coordinates of +the balloons. arrows can be shot up directly vertically in the positive y +direction. from different points along the x axis. given the array points, +return the minimum number of arrows that must be shot to burst all balloons. +""" + + +class Solution(object): + def findMinArrowShots(self, points): + """ + :type points: List[List[int]] + :rtype: int + """ + points.sort(key=lambda p: p[1]) + ans, arrow = 0, 0 + for [start, end] in points: + if ans == 0 or start > arrow: + ans, arrow = ans + 1, end + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.findMinArrowShots(points=[[10, 16], [2, 8], [1, 6], [7, 12]])) + print(obj.findMinArrowShots(points=[[1, 2], [3, 4], [5, 6], [7, 8]])) + print(obj.findMinArrowShots(points=[[1, 2], [2, 3], [3, 4], [4, 5]])) diff --git a/min_num_arrow_balloon.rs b/min_num_arrow_balloon.rs new file mode 100644 index 0000000..6204bfe --- /dev/null +++ b/min_num_arrow_balloon.rs @@ -0,0 +1,20 @@ +struct Solution; + +impl Solution { + pub fn find_min_arrow_shots(mut points: Vec<Vec<i32>>) -> i32 { + points.sort_unstable_by(|a, b| a[1].cmp(&b[1])); + let (mut arrows, mut target) = (0, points[0][1]); + for p in points { + if p[0] > target && p[1] > target { + arrows += 1; + target = p[1]; + } + } + arrows + 1 + } +} + +fn main() { + let points = vec![vec![10,16],vec![2,8],vec![1,6],vec![7,12]]; + println!("{}", Solution::find_min_arrow_shots(points)); //expect: 2 +} diff --git a/min_num_days_disconnect_island.cpp b/min_num_days_disconnect_island.cpp new file mode 100644 index 0000000..f1598c8 --- /dev/null +++ b/min_num_days_disconnect_island.cpp @@ -0,0 +1,50 @@ +#include "leetcode.h" + +class Solution { +public: + int minDays(vector<vector<int>> &grid) { + int islands = islandCount(grid); + int n = grid.size(), m = grid[0].size(); + if (islands > 1 || islands == 0) + return 0; + else { + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (grid[i][j]) { + grid[i][j] = 0; + islands = islandCount(grid); + grid[i][j] = 1; + if (islands > 1 || islands == 1) + return 1; + } + } + } + } + return 2; + } + +private: + vector<int> dx = {1, -1, 0, 0}, dy = {0, 0, 1, -1}; + void dfs(int x, int y, vector<vector<int>> &grid, vector<vector<int>> &vis) { + int n = grid.size(), m = grid[0].size(); + vis[x][y] = 1; + for (int a = 0; a < 4; a++) { + int nx = x + dx[a], ny = y + dy[a]; + if (nx >= 0 && ny >= 0 && nx < n && ny < m && !vis[nx][ny] && + grid[nx][ny]) + dfs(nx, nx, grid, vis); + } + } + int islandCount(vector<vector<int>> &grid) { + int count = 0, n = grid.size(), m = grid[0].size(); + vector<vector<int>> vis(n, vector<int>(m, 0)); + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (!vis[i][j] && grid[i][j]) { + dfs(i, j, grid, vis); + } + } + } + return count; + } +}; diff --git a/min_num_game.c b/min_num_game.c new file mode 100644 index 0000000..ca34d08 --- /dev/null +++ b/min_num_game.c @@ -0,0 +1,39 @@ +// 2974. Minimum Number Game +#include "leetcode.h" + +/* + * given a 0-indexed array 'ums' of even length and there is also an empty array + * 'arr'. alice and bob decided to play a game where in every round alice and + * bob will do one move. the rules of the game are as follows: every round, + * first alice will remove the minimum element from 'nums', and then bob does + * the same. now, first bob will append the removed element in the array 'arr' + * and alice does the same. the game continues until 'nums' becomes empty. + * return the resulting array 'arr'. + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int *numberGame(int *nums, int numsSize, int *returnSize) { + int *arr = (int *)malloc(sizeof(int) * numsSize); + qsort(nums, numsSize, sizeof(int), cmp); + for (int i = 0; i < numsSize; i += 2) { + arr[i] = nums[i + 1]; + arr[i + 1] = nums[i]; + } + *returnSize = numsSize; + return arr; +} + +int main() { + int n1[] = {5, 4, 2, 3}, n2[] = {2, 5}; + int rs1 = 0, rs2 = 0; + int *ng1 = numberGame(n1, ARRAY_SIZE(n1), &rs1); + int *ng2 = numberGame(n2, ARRAY_SIZE(n2), &rs2); + for (int i = 0; i < ARRAY_SIZE(n1); i++) + printf("%d ", ng1[i]); + printf("\n"); + for (int i = 0; i < ARRAY_SIZE(n2); i++) + printf("%d ", ng2[i]); + printf("\n"); + free(ng1), free(ng2); +} diff --git a/min_num_game.py b/min_num_game.py new file mode 100644 index 0000000..e409de6 --- /dev/null +++ b/min_num_game.py @@ -0,0 +1,29 @@ +# 2974. Minimum Number Game +from functools import reduce +from pandas import concat + +""" +given a 0-indexed array 'ums' of even length and there is also an empty array +'arr'. alice and bob decided to play a game where in every round alice and +bob will do one move. the rules of the game are as follows: every round, +first alice will remove the minimum element from 'nums', and then bob does +the same. now, first bob will append the removed element in the array 'arr' +and alice does the same. the game continues until 'nums' becomes empty. +return the resulting array 'arr'. +""" + + +class Solution(object): + def numberGame(self, nums): + """ + :type nums: List[int] + :rtype: List[int] + """ + n = iter(sorted(nums)) + return reduce(concat, [(b, a) for a, b in zip(n, n)]) + + +if __name__ == "__main__": + obj = Solution() + print(obj.numberGame(nums=[5, 4, 2, 3])) + print(obj.numberGame(nums=[2, 5])) diff --git a/min_num_moves_seat_everyone.c b/min_num_moves_seat_everyone.c new file mode 100644 index 0000000..105ebde --- /dev/null +++ b/min_num_moves_seat_everyone.c @@ -0,0 +1,43 @@ +// 2037. Minimum Number of Moves to Seat Everyone +#include "leetcode.h" + +/* + * there are 'n' seats and 'n' students in a room. you are given an array + * 'seats' of length 'n' where 'seats[i]' is the position of the i'th seat. you + * are also given the array 'students' of length 'n' where 'students[j]' is the + * position of the j'th student. you may perform the following move any number + * of times. return the minimum number of moves required to move each student to + * a seat such that no two students are in the same. + */ + +int minMovesToSeat(int *seats, int seatsSize, int *students, int studentsSize) { + int tmp, sum = 0; + for (int i = 0; i < seatsSize; i++) { + for (int j = i + 1; j < seatsSize; j++) { + if (seats[i] > seats[j]) { + tmp = seats[i]; + seats[i] = seats[j]; + seats[j] = tmp; + } + if (students[i] > students[j]) { + tmp = students[i]; + students[i] = students[j]; + students[j] = tmp; + } + } + sum += abs(students[i] - seats[i]); + } + return sum; +} + +int main() { + int seats1[] = {3, 1, 5}, seats2[] = {4, 1, 5, 9}, seats3[] = {2, 2, 6, 6}; + int students1[] = {2, 7, 4}, students2[] = {1, 3, 2, 6}, + students3[] = {1, 3, 2, 6}; + printf("%d\n", minMovesToSeat(seats1, ARRAY_SIZE(seats1), students1, + ARRAY_SIZE(students1))); // expect: 4 + printf("%d\n", minMovesToSeat(seats2, ARRAY_SIZE(seats2), students2, + ARRAY_SIZE(students2))); // expect: 4 + printf("%d\n", minMovesToSeat(seats3, ARRAY_SIZE(seats3), students3, + ARRAY_SIZE(students3))); // expect: 4 +} diff --git a/min_num_moves_seat_everyone.py b/min_num_moves_seat_everyone.py new file mode 100644 index 0000000..ffe55c5 --- /dev/null +++ b/min_num_moves_seat_everyone.py @@ -0,0 +1,29 @@ +# 2037. Minimum Number of Moves to Seat Everyone + +""" +there are 'n' seats and 'n' students in a room. you are given an array +'seats' of length 'n' where 'seats[i]' is the position of the i'th seat. you +are also given the array 'students' of length 'n' where 'students[j]' is the +position of the j'th student. you may perform the following move any number +of times. return the minimum number of moves required to move each student to +a seat such that no two students are in the same. +""" + + +class Solution(object): + def minMovesToSeat(self, seats, students): + """ + :type seats: List[int] + :type students: List[int] + :rtype: int + """ + seats.sort() + students.sort() + return sum(abs(seat - student) for seat, student in zip(seats, students)) + + +if __name__ == "__main__": + obj = Solution() + print(obj.minMovesToSeat(seats=[3, 1, 5], students=[2, 7, 4])) + print(obj.minMovesToSeat(seats=[4, 1, 5, 9], students=[1, 3, 2, 6])) + print(obj.minMovesToSeat(seats=[2, 2, 6, 6], students=[1, 3, 2, 6])) diff --git a/min_num_opp_arr_cont.c b/min_num_opp_arr_cont.c new file mode 100644 index 0000000..053a302 --- /dev/null +++ b/min_num_opp_arr_cont.c @@ -0,0 +1,42 @@ +// 2009. Minimum Number of Operations to Make Array Continuous +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * you are given an integer array 'nums'. in one operation, you can replace any + * element in 'nums' with any integer. 'nums' is considered continuous if both + * of the following conditions are fulfilled: + * - all elements in 'nums' are unique + * - the difference between the maximum element and the minimum element in + * 'nums' equals 'nums.len - 1' return the minimum number of operations to make + * 'nums' continuous. + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int minOperations(int *nums, int nums_size) { + int n = nums_size, idx = 1, ans = INT_MAX, j = 0; + qsort(nums, n, sizeof(int), cmp); + int *arr = malloc(n * sizeof(int)); + arr[0] = nums[0]; + for (int i = 1; i < n; i++) + if (nums[i] != nums[i - 1]) { + arr[idx] = nums[i]; + idx++; + } + for (int i = 0; i < idx; i++) + while (j < idx && arr[j] - arr[i] + 1 <= n) { + ans = fmin(ans, n - (j - i + 1)); + j++; + } + return ans; +} + +int main() { + int n1[] = {4, 2, 5, 3}, n2[] = {1, 2, 3, 5, 6}, n3[] = {1, 10, 100, 1000}; + printf("%d\n", minOperations(n1, 4)); // expect: 0 + printf("%d\n", minOperations(n2, 5)); // expect: 1 + printf("%d\n", minOperations(n3, 4)); // expect: 3 +} diff --git a/min_num_opp_arr_cont.cpp b/min_num_opp_arr_cont.cpp new file mode 100644 index 0000000..5dcb40f --- /dev/null +++ b/min_num_opp_arr_cont.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + int minOperations(vector<int> &nums) { + int n = nums.size(), ans = n, j = 0; + sort(nums.begin(), nums.end()); + nums.erase(unique(nums.begin(), nums.end()), nums.end()); + for (int i = 0; i < nums.size(); ++i) { + while (j < nums.size() && nums[j] < nums[i] + n) + ++j; + ans = min(ans, n - j + i); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums = {4, 2, 5, 3}; + cout << obj.minOperations(nums); +} diff --git a/min_num_opp_arr_cont.py b/min_num_opp_arr_cont.py new file mode 100644 index 0000000..977320e --- /dev/null +++ b/min_num_opp_arr_cont.py @@ -0,0 +1,32 @@ +# 2009. Minimum Number of Operations to Make Array Continuous +from bisect import bisect + +""" +you are given an integer array 'nums'. in one operation, you can replace any +element in 'nums' with any integer. 'nums' is considered continuous if both +of the following conditions are fulfilled: +- all elements in 'nums' are unique +- the difference between the maximum element and the minimum element in +'nums' equals 'nums.len - 1' return the minimum number of operations to make +'nums' continuous. +""" + + +class Solution(object): + def minOperations(self, nums): + n = len(nums) + nums = sorted(set(nums)) + ans = n + for i, start in enumerate(nums): + end = start + n - 1 + idx = bisect_right(nums, end) + unique_len = idx - i + ans = min(ans, n - unique_len) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.minOperations([4, 2, 5, 3])) # expect: 0 + print(obj.minOperations([1, 2, 3, 5, 6])) # expect: 1 + print(obj.minOperations([1, 10, 100, 1000])) # expect: 3 diff --git a/min_num_opp_arr_equal_xor.c b/min_num_opp_arr_equal_xor.c new file mode 100644 index 0000000..b4622ef --- /dev/null +++ b/min_num_opp_arr_equal_xor.c @@ -0,0 +1,34 @@ +// 2997. Minimum Number of Operations to Make Array XOR Equal to K +#include "leetcode.h" + +/* + * given a 0-indexed array 'nums' and a positive integer 'k'. you can apply the + * following operation on the array any number of times: choose any element of + * the array and flip a bit in its binary representation. flipping a bit means + * chaning a 0 to a 1 or vice versa. return the minimum number of operations + * required to make the bitwise xor of all elements in the array equal to 'k'. + * note that you can flip leading zero bits in the binary representation of the + * elements. for example, for the number of '101_2' you can flip the fouth bit + * and obtain '1101_2' + */ + +int minOperations(int *nums, int numsSize, int k) { + int xor = 0, ops = 0; + for (int i = 0; i < numsSize; i++) + xor ^= nums[i]; + if (xor == k) + return 0; + while (k || xor) { + if (k % 2 != xor % 2) + ops++; + k /= 2; + xor /= 2; + } + return ops; +} + +int main() { + int n1[] = {2, 1, 3, 4}, n2[] = {2, 0, 2, 0}; + printf("%d\n", minOperations(n1, ARRAY_SIZE(n1), 1)); // expect: 2 + printf("%d\n", minOperations(n2, ARRAY_SIZE(n2), 0)); // expect: 0 +} diff --git a/min_num_opp_arr_equal_xor.py b/min_num_opp_arr_equal_xor.py new file mode 100644 index 0000000..79bd53a --- /dev/null +++ b/min_num_opp_arr_equal_xor.py @@ -0,0 +1,35 @@ +# 2997. Minimum Number of Operations to Make Array XOR Equal to K + +""" +given a 0-indexed array 'nums' and a positive integer 'k'. you can apply the +following operation on the array any number of times: choose any element of +the array and flip a bit in its binary representation. flipping a bit meops +chaning a 0 to a 1 or vice versa. return the minimum number of operations +required to make the bitwise xor of all elements in the array equal to 'k'. +note that you can flip leading zero bits in the binary representation of the +elements. for example, for the number of '101_2' you can flip the fouth bit +and obtain '1101_2' +""" + + +class Solution(object): + def minOperations(self, nums, k): + """ + :type nums: List[int] + :type k: int + :rtype: int + """ + cnt = k + for n in nums: + cnt ^= n + ops = 0 + while cnt: + ops += cnt & 1 + cnt >>= 1 + return ops + + +if __name__ == "__main__": + obj = Solution() + print(obj.minOperations(nums=[2, 1, 3, 4], k=1)) + print(obj.minOperations(nums=[2, 0, 2, 0], k=0)) diff --git a/min_num_ops_arr_empty.c b/min_num_ops_arr_empty.c new file mode 100644 index 0000000..1b207cb --- /dev/null +++ b/min_num_ops_arr_empty.c @@ -0,0 +1,34 @@ +// 2870. Minimum Number of Operations to Make Array Empty +#include "leetcode.h" + +/* + * you are given a 0-indexed array 'nums' consisting of positive integers. there + * are two types of operations that you can apply on the array any number of + * times. choose two elements with equal values and delete them from the array. + * choose three elements with equal values and delete them from the array. + * return the minimum number of operations required to make the array empty, or + * -1 if it is not possible. + */ + +int minOperations(int *nums, int nums_size) { + int ans = 0, ctr[1000001] = {0}; + for (int i = 0; i < nums_size; i++) + ctr[nums[i]]++; + for (int i = 0; i < 1000001; i++) { + if (ctr[i] == 1) + return -1; + if (ctr[i]) { + if (ctr[i] % 3) + ans += ctr[i] / 3 + 1; + else + ans += ctr[i] / 3; + } + } + return ans; +} + +int main() { + int n1[] = {2, 3, 3, 2, 2, 4, 2, 3, 4}, n2[] = {2, 1, 2, 2, 3, 3}; + printf("%d\n", minOperations(n1, ARRAY_SIZE(n1))); // expect: 4 + printf("%d\n", minOperations(n2, ARRAY_SIZE(n2))); // expect: -1 +} diff --git a/min_num_ops_arr_empty.py b/min_num_ops_arr_empty.py new file mode 100644 index 0000000..0fbb80f --- /dev/null +++ b/min_num_ops_arr_empty.py @@ -0,0 +1,34 @@ +# 2870. Minimum Number of Operations to Make Array Empty +from collections import Counter + +""" +you are given a 0-indexed array 'nums' consisting of positive integers. there +are two types of operations that you can apply on the array any number of +times. choose two elements with equal values and delete them from the array. +choose three elements with equal values and delete them from the array. +return the minimum number of operations required to make the array empty, or +-1 if it is not possible. +""" + + +class Solution(object): + def minOperations(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + ctr = Counter(nums) + cnt = 0 + for i in ctr.values(): + if i == 1: + return -1 + cnt += i // 3 + if i % 3: + cnt += 1 + return cnt + + +if __name__ == "__main__": + obj = Solution() + print(obj.minOperations(nums=[2, 3, 3, 2, 2, 4, 2, 3, 4])) # expect: 4 + print(obj.minOperations(nums=[2, 1, 2, 2, 3, 3])) # expect: -1 diff --git a/min_num_ops_ball_box.c b/min_num_ops_ball_box.c new file mode 100644 index 0000000..a6cba59 --- /dev/null +++ b/min_num_ops_ball_box.c @@ -0,0 +1,25 @@ +// 1769. Minimum Number of Operations to Move All Balls to Each Box +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int *minOperations(char *boxes, int *returnSize) { + int len = strlen(boxes), steps; + int *ans = malloc(len * sizeof(int)); + for (int i = 0; i < len; i++) { + steps = 0; + for (int j = 0; j < len; j++) + if (boxes[j] == '1') + steps += abs(i - j); + ans[i] = steps; + } + *returnSize = len; + return ans; +} + +int main() { + char boxes1[] = {"110"}, boxes2[] = {"001011"}; + int rs1[] = {3}, rs2[] = {6}; + printf("%c\n", *minOperations(boxes1, rs1)); // expect: 1,1,3 + printf("%c\n", *minOperations(boxes2, rs2)); // expect: 11,8,5,4,3,4 +} diff --git a/min_num_refueling_stops.cpp b/min_num_refueling_stops.cpp new file mode 100644 index 0000000..34d929b --- /dev/null +++ b/min_num_refueling_stops.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + int minRefuelStops(int target, int startFuel, vector<vector<int>> &stations) { + int n = stations.size(), ans = 0; + priority_queue<int> pq; + for (int i = 0; i <= n; i++) { + int dist = i == n ? target : stations[i][0]; + while (startFuel < dist) { + if (!pq.size()) + return -1; + startFuel += pq.top(); + ans++; + pq.pop(); + } + if (i < n) + pq.push(stations[i][1]); + } + return ans; + } +}; diff --git a/min_num_steps_anagram.c b/min_num_steps_anagram.c new file mode 100644 index 0000000..211c932 --- /dev/null +++ b/min_num_steps_anagram.c @@ -0,0 +1,31 @@ +// 1347. Minimum Number of Steps to Make Two Strings Anagram +#include "leetcode.h" + +/* + * given two trings of the same length 's' and 't'. in one step you can choose + * any character of 't' and replace itwith another characters. return the + * minimum numberof steps to make 't' an anagram of 's'. an anagram of a string + * is a string that contains the same characters witha different ordering. + */ + +int minSteps(char *s, char *t) { + int *alpha = calloc(26, sizeof(int)); + for (int i = 0; i < strlen(s); i++) { + alpha[s[i] - 'a']++; + alpha[t[i] - 'a']--; + } + int ans = 0; + for (int i = 0; i < 26; i++) + if (alpha[i] > 0) + ans += alpha[i]; + return ans; +} + +int main() { + char *s1 = "bab", *t1 = "aba"; + char *s2 = "leetcode", *t2 = "practice"; + char *s3 = "anagram", *t3 = "mangaar"; + printf("%d\n", minSteps(s1, t1)); // expect: 1 + printf("%d\n", minSteps(s2, t2)); // expect: 5 + printf("%d\n", minSteps(s3, t3)); // expect: 0 +} diff --git a/min_num_steps_anagram.py b/min_num_steps_anagram.py new file mode 100644 index 0000000..cd3692a --- /dev/null +++ b/min_num_steps_anagram.py @@ -0,0 +1,34 @@ +# 1347. Minimum Number of Steps to Make Two Strings Anagram + +""" +given two trings of the same length 's' and 't'. in one step you can choose +any character of 't' and replace itwith another characters. return the +minimum numberof steps to make 't' an anagram of 's'. an anagram of a string +is a string that contains the same characters witha different ordering. +""" + + +class Solution(object): + def minSteps(self, s, t): + """ + :type s: str + :type t: str + :rtype: int + """ + cnt_s = [0] * 26 + cnt_t = [0] * 26 + for char in s: + cnt_s[ord(char) - ord("a")] += 1 + for char in t: + cnt_t[ord(char) - ord("a")] += 1 + steps = 0 + for i in range(26): + steps += abs(cnt_s[i] - cnt_t[i]) + return steps // 2 + + +if __name__ == "__main__": + obj = Solution() + print(obj.minSteps(s="bab", t="aba")) + print(obj.minSteps(s="leetcode", t="practice")) + print(obj.minSteps(s="anagram", t="mangaar")) diff --git a/min_num_vertices_node.c b/min_num_vertices_node.c new file mode 100644 index 0000000..5dec4ce --- /dev/null +++ b/min_num_vertices_node.c @@ -0,0 +1,48 @@ +// 1557. Minimum Number of Vertices to Reach All Nodes +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given a directed acyclic graph, with 'n' vertices numbered from 0 to 'n - 1', + * and an array 'edges', where 'edges[i] = [fromi, toi]' representes a directed + * edge from node 'fromi' to node 'toi'. find the smallest set of vertices from + * which all nodes in the graph are reachale. it's guaranteed that a unique + * solution exists. notice you cano return the vertices in any order. + */ + +int *findSmallestSetOfVertices(int n, int **edges, int edges_size, + int *edges_col_size, int *return_size) { + int cnt = n; + bool *node = calloc(n, sizeof(bool)); + for (int i = 0; i < edges_size; i++) { + if (!node[edges[i][1]]) { + node[edges[i][1]] = 1; + cnt--; + } + } + int *ans = malloc(cnt * sizeof(int)); + int a_idx = 0; + for (int i = 0; i < n; i++) { + if (!node[i]) { + ans[a_idx] = i; + a_idx++; + } + } + free(node); + *return_size = cnt; + return ans; +} + +int main() { + int e1[5][2] = {{0, 1}, {0, 2}, {2, 5}, {3, 4}, {4, 2}}; + int e2[5][2] = {{0, 1}, {2, 1}, {3, 1}, {1, 4}, {2, 4}}; + int ecs[] = {5}, rs[] = {}; + int *t1 = findSmallestSetOfVertices(6, e1, 5, ecs, rs); + int *t2 = findSmallestSetOfVertices(3, e2, 5, ecs, rs); + for (int i = 0; i < 5; i++) + printf("%d ", t1[i]); // expect: 0 3 + printf("\n"); + for (int i = 0; i < 5; i++) + printf("%d ", t2[i]); // expect: 0 2 3 +} diff --git a/min_num_vertices_node.cpp b/min_num_vertices_node.cpp new file mode 100644 index 0000000..d39b08b --- /dev/null +++ b/min_num_vertices_node.cpp @@ -0,0 +1,34 @@ +// 1557. Minimum Number of Vertices to Reach All Nodes +#include "leetcode.h" + +/* + * given a directed acyclic graph, with 'n' vertices numbered from 0 to 'n - 1', + * and an array 'edges', where 'edges[i] = [fromi, toi]' representes a directed + * edge from node 'fromi' to node 'toi'. find the smallest set of vertices from + * which all nodes in the graph are reachale. it's guaranteed that a unique + * solution exists. notice you cano return the vertices in any order. + */ + +class Solution { +public: + vector<int> findSmallestSetOfVertices(int n, vvd(int) & edges) { + vector<int> ans, seen(n); + for (auto e : edges) + seen[e[1]] = 1; + for (int i = 0; i < n; ++i) + if (!seen[i]) + ans.push_back(i); + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) e1 = {{0, 1}, {0, 2}, {2, 5}, {3, 4}, {4, 2}}; + vvd(int) e2 = {{0, 1}, {2, 1}, {3, 1}, {1, 4}, {2, 4}}; + for (auto i : obj.findSmallestSetOfVertices(6, e1)) + printf("%d ", i); // expect: 0 3 + printf("\n"); + for (auto i : obj.findSmallestSetOfVertices(5, e2)) + printf("%d ", i); // expect: 0 2 3 +} diff --git a/min_one_bit_0.cpp b/min_one_bit_0.cpp new file mode 100644 index 0000000..9820ace --- /dev/null +++ b/min_one_bit_0.cpp @@ -0,0 +1,18 @@ +#include "leetcode.h" + +class Solution { +public: + unordered_map<int, int> um{{0, 0}}; + inline int bto0(int b) { return (1 << (b + 1)) - 1; } + int minimumOneBitOperations(int n) { + if (um.count(n)) + return um[n]; + int b = 31 - __builtin_clz(n); + return um[n] = bto0(b) - minimumOneBitOperations(n - (1 << b)); + } +}; + +int main() { + Solution obj; + cout << obj.minimumOneBitOperations(39769175); // expect 4 +} diff --git a/min_one_bit_0.rs b/min_one_bit_0.rs new file mode 100644 index 0000000..1b52362 --- /dev/null +++ b/min_one_bit_0.rs @@ -0,0 +1,29 @@ +struct Solution; + +impl Solution { + pub fn minimum_one_bit_operations(n: i32) -> i32 { + if n <= 1 { + return n; + } + let mut max = 1usize; + while max < n as usize { + max += max; + } + let mut dp = vec![0; max as usize + 1]; + dp[1] = 1; + let (mut start, mut _i) = (2usize, 1); + while start < max as usize { + for i in 0..start / 2 { + dp[start + i] = dp[start / 2 + i] + start; + dp[start * 3 / 2 + i] = dp[i] + start; + } + start *= 2; + } + dp[max] = max * 2 - 1; + dp[n as usize] as i32 + } +} + +fn main() { + print!("{}", Solution::minimum_one_bit_operations(39769175)); +} diff --git a/min_one_bit_op_zero.c b/min_one_bit_op_zero.c new file mode 100644 index 0000000..8dea211 --- /dev/null +++ b/min_one_bit_op_zero.c @@ -0,0 +1,29 @@ +// 1611. Minimum One Bit Operations to Make Integers Zero +#include "leetcode.h" + +/* + * given an integer 'n', you must transform it into '0' using the following + * operations: change the rightmost (LSB) bit in the binary representation of + * 'n', or change the i'th bit in the binary representation of 'n' if the '(i - + * 1)'th bit is set to 1 and the '(i - 2)'th through the 0th bits are set to 0. + * return the minimum number of operations to transform 'n' into '0'. + */ + +int minimumOneBitOperations(int n) { + int tmp = n, sign = 1, cnt = 0, pos = 0; + while (tmp) { + if (tmp & (1 << pos)) { + cnt += sign * ((1 << (pos + 1)) - 1); + tmp &= ~(1 << pos); + sign *= -1; + } + pos--; + } + return cnt; +} + +int main() { + printf("%d\n", minimumOneBitOperations(3)); // expect: 2 + printf("%d\n", minimumOneBitOperations(6)); // expect: 4 + printf("%d\n", minimumOneBitOperations(8174)); // expect: N/A +} diff --git a/min_one_bit_op_zero.py b/min_one_bit_op_zero.py new file mode 100644 index 0000000..9150552 --- /dev/null +++ b/min_one_bit_op_zero.py @@ -0,0 +1,28 @@ +# 1611. Minimum One Bit Operations to Make Integers Zero + +""" +given an integer 'n', you must transform it into '0' using the following +operations: change the rightmost (LSB) bit in the binary representation of +'n', or change the i'th bit in the binary representation of 'n' if the '(i - +1)'th bit is set to 1 and the '(i - 2)'th through the 0th bits are set to 0. +return the minimum number of operations to transform 'n' into '0'. +""" + + +class Solution(object): + def minimumOneBitOperations(self, n): + """ + :type n: int + :rtype: int + """ + cnt = 0 + while n: + cnt = -cnt - (n ^ (n - 1)) + n &= n - 1 + return abs(cnt) + + +if __name__ == "__main__": + obj = Solution() + print(obj.minimumOneBitOperations(3)) # expect: 2 + print(obj.minimumOneBitOperations(6)) # expect: 4 diff --git a/min_operations_arr_eq.c b/min_operations_arr_eq.c new file mode 100644 index 0000000..4c65db9 --- /dev/null +++ b/min_operations_arr_eq.c @@ -0,0 +1,58 @@ +// 2602. Minimum Operations to Make All Array Elements Equal +#include "leetcode.h" + +/* + * given an array 'nums' consisting of positive integers. you are also given an + * integer array 'queries' of size 'm'. for the i'th query, you want to make all + * of the elements of 'nums' equal to 'queries[i]'. you can perform the + * following operation on the array any number of times: increase or decrease an + * element of the array by 1. return an array 'ans' of size 'm' where 'ans[i]' + * is the minimum number of operations to make all elements of 'nums' equal to + * 'queries[i]'. note that after each query the array is reset to its original + * state + */ + +int cmp(const void *a, const void *b) { return (*(int *)a - *(int *)b); } + +long long *minOperations(int *nums, int numsSize, int *queries, int queriesSize, + int *returnSize) { + long long *prefix_sum = (long long *)calloc(numsSize + 1, sizeof(long long)); + long long *ans = (long long *)calloc(queriesSize, sizeof(long long)); + qsort(nums, numsSize, sizeof(int), cmp); + for (int i = 1; i <= numsSize; i++) + prefix_sum[i] = prefix_sum[i - 1] + nums[i - 1]; + for (int i = 0; i < queriesSize; i++) { + if (queries[i] < nums[0]) + ans[i] = prefix_sum[numsSize] - (long long)queries[i] * numsSize; + else if (queries[i] > nums[numsSize - 1]) + ans[i] = (long long)queries[i] * numsSize - prefix_sum[numsSize]; + else { + int l = 0, r = numsSize - 1, m; + while (l < r) { + m = l + ((r - l) >> 1); + if (nums[m] < queries[i]) + l = m + 1; + else + r = m; + } + ans[i] = (long long)queries[i] * (2 * l - numsSize) + + prefix_sum[numsSize] - 2 * prefix_sum[l]; + } + } + *returnSize = queriesSize; + return ans; +} + +int main() { + int n1[] = {3, 1, 6, 8}, q1[] = {1, 5}; + int n2[] = {2, 9, 6, 3}, q2[] = {10}; + int rcs1[] = {}, rcs2[] = {}; + long long *mo1 = minOperations(n1, ARRAY_SIZE(n1), q1, ARRAY_SIZE(q1), rcs1); + long long *mo2 = minOperations(n2, ARRAY_SIZE(n2), q2, ARRAY_SIZE(q2), rcs2); + for (int i = 0; i < 2; i++) + printf("%lld ", mo1[i]); // expect: 14 10 + printf("\n"); + for (int i = 0; i < 1; i++) + printf("%lld ", mo2[i]); // expect: 20 + printf("\n"); +} diff --git a/min_operations_arr_eq.py b/min_operations_arr_eq.py new file mode 100644 index 0000000..0434365 --- /dev/null +++ b/min_operations_arr_eq.py @@ -0,0 +1,35 @@ +# 2602. Minimum Operations to Make All Array Elements Equal +from itertools import accumulate +from bisect import bisect_left + +""" +given an array 'nums' consisting of positive integers. you are also given an +integer array 'queries' of size 'm'. for the i'th query, you want to make all +of the elements of 'nums' equal to 'queries[i]'. you can perform the +following operation on the array any number of times: increase or decrease an +element of the array by 1. return an array 'ans' of size 'm' where 'ans[i]' +is the minimum number of operations to make all elements of 'nums' equal to +'queries[i]'. note that after each query the array is reset to its original +state +""" + + +class Solution(object): + def minOperations(self, nums, queries): + """ + :type nums: List[int] + :type queries: List[int] + :rtype: List[int] + """ + nums.sort() + ans, n, prefix = [], len(nums), [0] + list(accumulate(nums)) + for i in queries: + j = bisect_left(nums, i) + ans.append(i * (2 * j - n) + prefix[n] - 2 * prefix[j]) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.minOperations(nums=[3, 1, 6, 8], queries=[1, 5])) + print(obj.minOperations(nums=[2, 9, 6, 3], queries=[10])) diff --git a/min_operations_subseq.c b/min_operations_subseq.c new file mode 100644 index 0000000..018c56d --- /dev/null +++ b/min_operations_subseq.c @@ -0,0 +1,94 @@ +// 1713. Minimum Operations to Make a Subsequence +#include "leetcode.h" + +/* + * given an array 'target' that consists of distinct integers and another + * integer array 'arr' that can have duplicates. in one operatioin, you can + * insert any integer at any position in 'arr'. note that you can inser the + * integer at the very beginning or end of the array. return the minimum number + * of operations needed to make 'target' a subsequence of 'arr'. a subsequence + * of anarray is a new array generated from the original array by deleting some + * elements (possibly none) without changing the remaining elements. + */ + +int cmp(const void *a, const void *b) { + int *a1 = *(int **)a; + int *b1 = *(int **)b; + return a1[1] - b1[1]; +} + +int binary_search(int *nums, int n, int val) { + int left = 0, right = n - 1, mid; + if (val <= nums[0]) + return 0; + while (left < right) { + mid = left + (right - left) / 2; + if (nums[mid] == val) + return mid; + if (nums[mid] > val) + right = mid; + else + left = mid + 1; + } + return left; +} + +int bfs(int **nums, int n, int val) { + int left = 0, right = n - 1, mid; + if (val < nums[0][1] || val > nums[n - 1][1]) + return -1; + while (left < right) { + mid = left + (right - left) / 2; + if (nums[mid][1] == val) + return nums[mid][0]; + if (nums[mid][1] > val) + right = mid - 1; + else + left = mid + 1; + } + if (nums[left][1] == val) + return nums[left][0]; + return -1; +} + +int minOperations(int *target, int targetSize, int *arr, int arrSize) { + int t = targetSize, a = arrSize, idx = 0; + int **copy_target = (int **)malloc(t * sizeof(int *)); + for (int i = 0; i < t; i++) { + copy_target[i] = malloc(2 * sizeof(int)); + copy_target[i][0] = i; + copy_target[i][1] = target[i]; + } + qsort(copy_target, t, sizeof(int *), cmp); + for (int i = 0; i < a; i++) { + int pos = bfs(copy_target, t, arr[i]); + if (pos != -1) { + arr[idx] = pos; + idx++; + } + } + if (!idx) + return t; + int *stack = (int *)malloc(idx * sizeof(int)); + stack[0] = arr[0]; + int s_idx = 1; + for (int i = 1; i < idx; i++) + if (arr[i] > stack[s_idx - 1]) { + stack[s_idx] = arr[i]; + s_idx++; + } else { + int x = binary_search(stack, s_idx, arr[i]); + stack[x] = arr[i]; + } + free(copy_target), free(stack); + return t - s_idx; +} + +int main() { + int t1[] = {5, 1, 3}, t2[] = {6, 4, 8, 1, 3, 2}, a1[] = {9, 4, 2, 3, 4}, + a2[] = {4, 7, 6, 2, 3, 8, 6, 1}; + printf("%d\n", + minOperations(t1, ARRAY_SIZE(t1), a1, ARRAY_SIZE(a1))); // expect: 2 + printf("%d\n", + minOperations(t2, ARRAY_SIZE(t2), a2, ARRAY_SIZE(a2))); // expect: 3 +} diff --git a/min_operations_subseq.py b/min_operations_subseq.py new file mode 100644 index 0000000..241daf1 --- /dev/null +++ b/min_operations_subseq.py @@ -0,0 +1,45 @@ +# 1713. Minimum Operations to Make a Subsequence +from bisect import bisect_left + +""" +given an array 'target' that consists of distinct integers and another +integer array 'arr' that can have duplicates. in one operatioin, you can +insert any integer at any position in 'arr'. note that you can inser the +integer at the very beginning or end of the array. return the minimum number +of operations needed to make 'target' a subsequence of 'arr'. a subsequence +of anarray is a new array generated from the original array by deleting some +elements (possibly none) without changing the remaining elements. +""" + + +class Solution(object): + def minOperations(self, target, arr): + """ + :type target: List[int] + :type arr: List[int] + :rtype: int + """ + dic = {num: i for i, num in enumerate(target)} + a = [] + for num in arr: + if num in dic: + a.append(dic[num]) + return len(target) - self.len_list(self, nums) + + def len_list(self, nums): + if not nums: + return 0 + piles = [] + for n in nums: + idx = bisect_left(piles, n) + if idx == len(piles): + piles.append(num) + else: + piles[idx] = n + return len(piles) + + +if __name__ == "__main__": + obj = Solution() + print(obj.minOperations(target=[5, 1, 3], arr=[9, 4, 2, 3, 4])) + print(obj.minOperations(target=[6, 4, 8, 1, 3, 2], arr=[4, 7, 6, 2, 3, 8, 6, 1])) diff --git a/min_operations_x_zero.c b/min_operations_x_zero.c new file mode 100644 index 0000000..b550af6 --- /dev/null +++ b/min_operations_x_zero.c @@ -0,0 +1,87 @@ +// 1658. Minimum Operations to Reduce X to Zero +#include <limits.h> +#include <math.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array 'nums' and an integer 'x'. in one operation, you can + * either remove the leftmost or the rightmost element from the array 'nums' and + * subtract its value from 'x'. note that this modifies the array for future + * operations. return the minimum number of operations to reduce 'x' to exactly + * 0. if it is possible, otherwise return -1 + */ + +int minOperations(int *nums, int nums_size, int x) { + int n = nums_size, mod = 1e5 + 7, i; + bool *table = calloc(mod, sizeof(bool)); + int **hash = malloc(sizeof(int *) * mod); + long long pre_sum = nums[n - 1]; + hash[pre_sum % mod] = calloc(2, sizeof(int)); + hash[pre_sum % mod][0] = nums[n - 1]; + hash[pre_sum % mod][1] = n - 1; + table[pre_sum % mod] = true; + for (i = n - 2; i >= 0; i--) { + pre_sum += nums[i]; + if (pre_sum > x) + break; + if (!table[pre_sum % mod]) { + table[pre_sum % mod] = true; + hash[pre_sum % mod] = calloc(2, sizeof(int)); + hash[pre_sum % mod][0] = pre_sum; + hash[pre_sum % mod][1] = i; + } else { + int pos = pre_sum + 1; + while (table[pos % mod]) + pos++; + table[pos % mod] = true; + hash[pos % mod] = calloc(2, sizeof(int)); + hash[pos % mod][0] = pre_sum; + hash[pos % mod][1] = i; + } + } + if (i == -1 && pre_sum == x) + return n; + int min = INT_MAX, sum = 0, k = 0; + while (sum <= x && k < n) { + int rem = x - sum; + if (!rem) { + min = fmin(min, k); + break; + } + if (table[rem % mod]) { + if (hash[rem % mod][0] == rem) { + if (k >= hash[rem % mod][1]) + break; + if (n - hash[rem % mod][1] + k < min) + min = n - hash[rem % mod][1] + k; + } else { + int pos = rem + 1; + while (table[pos % mod]) { + if (hash[pos % mod][0] == rem) { + if (k >= hash[pos % mod][1]) + break; + if (n - hash[pos % mod][1] + k < min) + min = n - hash[pos % mod][1] + k; + } + pos++; + } + } + } + sum += nums[k]; + k++; + } + if (min == INT_MAX) + return -1; + else + return min; +} + +int main() { + int n1[] = {1, 1, 4, 2, 3}, n2[] = {5, 6, 7, 8, 9}, + n3[] = {3, 2, 20, 1, 1, 3}; + printf("%d\n", minOperations(n1, 5, 5)); // expect: 2 + printf("%d\n", minOperations(n2, 5, 4)); // expect: -1 + printf("%d\n", minOperations(n3, 6, 10)); // expect: 5 +} diff --git a/min_operations_x_zero.cpp b/min_operations_x_zero.cpp new file mode 100644 index 0000000..a838ab9 --- /dev/null +++ b/min_operations_x_zero.cpp @@ -0,0 +1,27 @@ +#include "leetcode.h" + +class Solution { +public: + int minOperations(vector<int> &nums, int x) { + unordered_map<int, int> left; + int ans = INT_MAX; + for (auto i = 0, sum = 0; i < nums.size() && sum <= x; ++i) { + left[sum] = i; + sum += nums[i]; + } + for (int i = nums.size() - 1, sum = 0; i >= 0 && sum <= x; --i) { + auto it = left.find(x - sum); + if (it != end(left) && i + 1 >= it->second) + ans = min(ans, (int)nums.size() - i - 1 + it->second); + sum += nums[i]; + } + return ans = INT_MAX ? -1 : ans; + } +}; + +int main() { + Solution obj; + vector<int> nums = {1, 1, 4, 2, 3}; + int x = 5; + cout << obj.minOperations(nums, x); +} diff --git a/min_operations_x_zero.py b/min_operations_x_zero.py new file mode 100644 index 0000000..f245bfe --- /dev/null +++ b/min_operations_x_zero.py @@ -0,0 +1,36 @@ +# 1658. Minimum Operations to Reduce X to Zero + +""" +given an integer array 'nums' and an integer 'x'. in one operation, you can +either remove the leftmost or the rightmost element from the array 'nums' and +subtract its value from 'x'. note that this modifies the array for future +operations. return the minimum number of operations to reduce 'x' to exactly +0. if it is possible, otherwise return -1 +""" + + +class Solution(object): + def minOperations(self, nums, x): + target, n = sum(nums) - x, len(nums) + + if target == 0: + return n + + max_len = cur_sum = left = 0 + + for right, val in enumerate(nums): + cur_sum += val + while left <= right and cur_sum > target: + cur_sum -= nums[left] + left += 1 + if cur_sum == target: + max_len = max(max_len, right - left + 1) + + return n - max_len if max_len else -1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.minOperations([1, 1, 4, 2, 3], 5)) # expect: 2 + print(obj.minOperations([5, 6, 7, 8, 9], 4)) # expect: -1 + print(obj.minOperations([3, 2, 20, 1, 1, 3], 10)) # expect: 5 diff --git a/min_path_sum.c b/min_path_sum.c new file mode 100644 index 0000000..f2cabbd --- /dev/null +++ b/min_path_sum.c @@ -0,0 +1,20 @@ +// 64. Minimum Path Sum +#include <math.h> + +// given 'm x n grid' filled with non-negative numbers, find a path from top +// left to bottom right, which minimises the sum of all numbers along its path + +int minPathSum(int **grid, int grid_size, int *grid_col_size) { + int i, j; + for (i = 0; i < grid_size; i++) { + for (j = 0; j < (*grid_col_size); j++) { + if (i - 1 >= 0 && j - 1 >= 0) + grid[i][j] += fmin(grid[i - 1][j], grid[i][j - 1]); + else if (i - 1 >= 0) + grid[i][j] += grid[i - 1][j]; + else if (j - 1 >= 0) + grid[i][j] += grid[i][j - 1]; + } + } + return grid[i - 1][j - 1]; +} diff --git a/min_path_sum.cpp b/min_path_sum.cpp new file mode 100644 index 0000000..2240f59 --- /dev/null +++ b/min_path_sum.cpp @@ -0,0 +1,29 @@ +// 64. Minimum Path Sum +#include "leetcode.h" + +// given 'm x n grid' filled with non-negative numbers, find a path from top +// left to bottom right, which minimises the sum of all numbers along its path + +class Solution { +public: + int minPathSum(vvd(int) & grid) { + int m = grid.size(), n = grid[0].size(); + vvd(int) sum(m, vector<int>(n, grid[0][0])); + for (int i = 1; i < m; i++) + sum[i][0] = sum[i - 1][0] + grid[i][0]; + for (int j = 1; j < n; j++) + sum[0][j] = sum[0][j - 1] + grid[0][j]; + for (int i = 1; i < m; i++) + for (int j = 1; j < n; j++) + sum[i][j] = min(sum[i - 1][j], sum[i][j - 1]) + grid[i][j]; + return sum[m - 1][n - 1]; + } +}; + +int main() { + Solution obj; + vvd(int) g1 = {{1, 3, 1}, {1, 5, 1}, {4, 2, 1}}; + vvd(int) g2 = {{1, 2, 3}, {4, 5, 6}}; + printf("%d\n", obj.minPathSum(g1)); // expect: 7 + printf("%d\n", obj.minPathSum(g2)); // expect: 12 +} diff --git a/min_penalty_shop.c b/min_penalty_shop.c new file mode 100644 index 0000000..4e41053 --- /dev/null +++ b/min_penalty_shop.c @@ -0,0 +1,63 @@ +// 2483. Minimum Penalty for a Shop +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + You are given the customer visit log of a shop represented by a 0-indexed +string customers consisting only of characters 'N' and 'Y': + + if the ith character is 'Y', it means that customers come at the ith hour + whereas 'N' indicates that no customers come at the ith hour. + +If the shop closes at the jth hour (0 <= j <= n), the penalty is calculated as +follows: + + For every hour when the shop is open and no customers come, the penalty +increases by 1. For every hour when the shop is closed and customers come, the +penalty increases by 1. + +Return the earliest hour at which the shop must be closed to incur a minimum +penalty. + +Note that if a shop closes at the jth hour, it means the shop is closed at the +hour j. +*/ + +int bestClosingTime(char *customers) { + int n = strlen(customers); + int *pre_n = malloc((n + 1) * sizeof(int)); + int *suf_y = malloc((n + 1) * sizeof(int)); + pre_n[0] = 0; + for (int i = 0; i < n; i++) { + pre_n[i + 1] = pre_n[i]; + if (customers[i] == 'N') + pre_n[i + 1]++; + } + suf_y[n] = 0; + for (int i = n - 1; i >= 0; i--) { + suf_y[i] = suf_y[i + 1]; + if (customers[i] == 'Y') + suf_y[i]++; + } + int min = INT_MAX, min_id = 0; + for (int i = 0; i <= n; i++) { + int d = pre_n[i] + suf_y[i]; + if (d < min) { + min = d; + min_id = i; + } + if (!min) + break; + } + free(pre_n), free(suf_y); + return min_id; +} + +int main() { + char c1[] = {"YYNY"}, c2[] = {"NNNNN"}, c3[] = {"YYYY"}; + printf("%d\n", bestClosingTime(c1)); // expect: 2 + printf("%d\n", bestClosingTime(c2)); // expect: 0 + printf("%d\n", bestClosingTime(c3)); // expect: 4 +} diff --git a/min_remove_valid_parentheses.c b/min_remove_valid_parentheses.c new file mode 100644 index 0000000..90300df --- /dev/null +++ b/min_remove_valid_parentheses.c @@ -0,0 +1,44 @@ +// 1249. Minimum Remove to Make Valid Parentheses +#include "leetcode.h" + +/* + * given a string s of '(' and ')' and lowercase english characters. your task + * is to remove the minimum number of parentheses so that the resulting + * parentheses string is valid and return any valid string. formally, a + * parentheses string is valid if and only if it is the empty string, contains + * only lowercase characters, or it can be written as AB where A and B are valid + * strings, or it can be written as (A) where A is a valid string. + */ + +char *minRemoveToMakeValid(char *s) { + int n = strlen(s), size = 0, p = 0; + bool *flag = calloc(n, sizeof(bool)); + int *stack = malloc(n * sizeof(int)); + for (int i = 0; i < n; i++) { + if (s[i] == '(') { + stack[size] = i; + size++; + } + if (s[i] == ')') { + if (size) + size--; + else + flag[i] = 1; + } + } + for (int i = 0; i < size; i++) + flag[stack[i]] = 1; + char *ans = malloc((n + 1) * sizeof(char)); + for (int i = 0; i < n; i++) + if (!flag[i]) + ans[p] = s[i], p++; + ans[p] = '\0'; + return ans; +} + +int main() { + char *s1 = "lee(t(c)o)de)", *s2 = "a)b(c)d", *s3 = "))(("; + printf("%s\n", minRemoveToMakeValid(s1)); + printf("%s\n", minRemoveToMakeValid(s2)); + printf("%s\n", minRemoveToMakeValid(s3)); +} diff --git a/min_remove_valid_parentheses.py b/min_remove_valid_parentheses.py new file mode 100644 index 0000000..ed6554b --- /dev/null +++ b/min_remove_valid_parentheses.py @@ -0,0 +1,38 @@ +# 1249. Minimum Remove to Make Valid Parentheses + +""" +given a string s of '(' and ')' and lowercase english characters. your task +is to remove the minimum number of parentheses so that the resulting +parentheses string is valid and return any valid string. formally, a +parentheses string is valid if and only if it is the empty string, contains +only lowercase characters, or it can be written as AB where A and B are valid +strings, or it can be written as (A) where A is a valid string. +""" + + +class Solution(object): + def minRemoveToMakeValid(self, s): + """ + :type s: str + :rtype: str + """ + s = list(s) + stack = [] + for i, c in enumerate(s): + if c == "(": + stack.append(i) + elif c == ")": + if stack: + stack.pop() + else: + s[i] = "" + while stack: + s[stack.pop()] = "" + return "".join(s) + + +if __name__ == "__main__": + obj = Solution() + print(obj.minRemoveToMakeValid(s="lee(t(c)o)de)")) + print(obj.minRemoveToMakeValid(s="a)b(c)d")) + print(obj.minRemoveToMakeValid(s="))((")) diff --git a/min_replacement_array.c b/min_replacement_array.c new file mode 100644 index 0000000..160f046 --- /dev/null +++ b/min_replacement_array.c @@ -0,0 +1,34 @@ +// 2366. Minimum Replacements to Sort the Array +#include <stdio.h> + +/* + * given a 0-indexed array 'nums'. in one operation you can replace any element + * of the array with any two elements that sum to it. + * - for example consider 'nums = [5,6,7]'. in one operation we can replace + * 'nums[1]' with 2 and 4 and convert 'nums' to '[5,2,4,7]'. return the minimum + * number of operations to make an array that is sorted in non-decreasing order. + */ + +long long minimumReplacement(int *nums, int nums_size) { + long long ans = 0; + int max = nums[nums_size - 1], divisor; + for (int i = nums_size - 2; i >= 0; i--) { + if (nums[i] > max) { + if (!(nums[i] % max)) + ans += (nums[i] / max) - 1; + else { + ans += (nums[i] / max); + divisor = (nums[i] / max) + 1; + max = nums[i] / divisor; + } + } else + max = nums[i]; + } + return ans; +} + +int main() { + int n1[] = {3, 9, 3}, n2[] = {1, 2, 3, 4, 5}; + printf("%lld\n", minimumReplacement(n1, 3)); // expect: 2 + printf("%lld\n", minimumReplacement(n2, 5)); // expect: 0 +} diff --git a/min_replacement_array.py b/min_replacement_array.py new file mode 100644 index 0000000..c0930c1 --- /dev/null +++ b/min_replacement_array.py @@ -0,0 +1,16 @@ +# 2366. Minimum Replacements to Sort the Array +class Solution(object): + def minimumReplacement(self, nums): + x = nums[-1] + ans = 0 + for i in reversed(nums): + k = (i + x - 1) // x + x = i // k + ans += k - 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.minimumReplacement([3, 9, 3])) # expect: 2 + print(obj.minimumReplacement([1, 2, 3, 4, 5])) # expect: 0 diff --git a/min_rounds_complete_all_tasks.cpp b/min_rounds_complete_all_tasks.cpp new file mode 100644 index 0000000..0d78073 --- /dev/null +++ b/min_rounds_complete_all_tasks.cpp @@ -0,0 +1,27 @@ +#include "leetcode.h" + +class Solution { +public: + int minimumRounds(vector<int> &tasks) { + unordered_map<int, int> um; + for (auto i : tasks) + um[i]++; + int count = 0; + for (auto i : um) { + int t = i.second; + if (t == 1) + return -1; + count += t / 3; + if (t % 3 != 0) + count++; + } + return count; + } +}; + +int main() { + Solution obj; + vector<int> tasks1 = {2, 2, 3, 3, 2, 4, 4, 4, 4, 4}, tasks2 = {2, 3, 3}; + cout << obj.minimumRounds(tasks1) << endl; + cout << obj.minimumRounds(tasks2) << endl; +} diff --git a/min_rounds_complete_all_tasks.rs b/min_rounds_complete_all_tasks.rs new file mode 100644 index 0000000..1c9b7dd --- /dev/null +++ b/min_rounds_complete_all_tasks.rs @@ -0,0 +1,30 @@ +use std::collections::HashMap; +struct Solution; + +impl Solution { + pub fn minimum_rounds(tasks: Vec<i32>) -> i32 { + let (mut map, mut ans) = (HashMap::new(), 0); + for t in tasks { + let val = map.get_mut(&t); + if let Some(v) = val { + *v += 1; + } else { + map.insert(t, 1); + } + } + for c in map.into_values() { + if c == 1 { + return -1; + } + ans += (c + 2) / 3; + } + ans + } +} + +fn main() { + let tasks1 = vec![2,2,3,3,2,4,4,4,4,4]; + let tasks2 = vec![2,3,3]; + println!("{}", Solution::minimum_rounds(tasks1)); + println!("{}", Solution::minimum_rounds(tasks2)); +} diff --git a/min_score_path_city.c b/min_score_path_city.c new file mode 100644 index 0000000..38ad947 --- /dev/null +++ b/min_score_path_city.c @@ -0,0 +1,48 @@ +// 2492. Minimum Score of a Path Between Two Cities +#include <limits.h> +#include <math.h> +#include <stdlib.h> + +int find_father(int **u, int val) { + int k = val; + while (k != u[k][0]) + k = u[k][0]; + return k; +} + +int minScore(int n, int **roads, int roads_size, int *roads_col_size) { + int **u = malloc((n + 1) * sizeof(int *)); + for (int i = 1; i <= n; i++) { + u[i] = malloc(3 * sizeof(int)); + u[i][0] = i; + u[i][1] = 1; + u[i][2] = INT_MAX; + } + for (int i = 0; i < roads_size; i++) { + int a = find_father(u, roads[i][0]); + int b = find_father(u, roads[i][1]); + int min = fmin(roads[i][2], fmin(u[a][2], u[b][2])); + if (a == b) { + u[a][2] = min; + continue; + } + if (u[a][1] >= u[b][1]) { + u[b][0] = a; + u[a][2] = min; + u[a][1] += u[b][1]; + } else { + u[a][0] = b; + u[b][2] = min; + u[b][1] += u[a][1]; + } + } + int first = find_father(u, 1), last = find_father(u, n), ans; + if (first != last) + ans = -1; + else + ans = u[first][2]; + for (int i = 1; i <= n; i++) + free(u[i]); + free(u); + return ans; +} diff --git a/min_score_path_city.cpp b/min_score_path_city.cpp new file mode 100644 index 0000000..5a25ec3 --- /dev/null +++ b/min_score_path_city.cpp @@ -0,0 +1,32 @@ +// 2492. Minimum Score of a Path Between Two Cities +#include "leetcode.h" + +class Solution { +public: + int minScore(int n, vvd(int) & roads) { + unordered_map<int, unordered_map<int, int>> graph; + for (auto r : roads) + graph[r[0]][r[1]] = graph[r[1]][r[0]] = r[2]; + unordered_set<int> vis; + function<int(int)> dfs; + dfs = [&](int n) -> int { + int res = INT_MAX; + vis.insert(n); + for (auto [adj, scr] : graph[n]) { + if (!vis.count(adj)) + res = min(res, dfs(adj)); + res = min(res, scr); + } + return res; + }; + return dfs(1); + } +}; + +int main() { + Solution obj; + vvd(int) r1 = {{1, 2, 9}, {2, 3, 6}, {2, 4, 5}, {1, 4, 7}}; + vvd(int) r2 = {{1, 2, 2}, {1, 3, 4}, {3, 4, 7}}; + printf("%d\n", obj.minScore(4, r1)); // expect: 5 + printf("%d\n", obj.minScore(4, r2)); // expect: 2 +} diff --git a/min_score_polygon.c b/min_score_polygon.c new file mode 100644 index 0000000..de648d9 --- /dev/null +++ b/min_score_polygon.c @@ -0,0 +1,50 @@ +// 1039. Minimum Score Triangulation of Polygon +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given a convex n-sided polygon where each vertex has an integer value. you + * are given an integer array 'values' where 'values[i]' is the value of the + * i'th vertex (ie. clockwise order). you will triangulate the polygon into 'n - + * 2' triangles. for each triangle, the value of that triangle is the product of + * the values of its vertices and the total score of the triangulation is the + * sum of these values over all 'n - 2' triangles in the triangulation. return + * the smallest possible total score that you can achieve with some + * triangulation of the polygon + */ + +int minScoreTriangulation(int *values, int values_size) { + int n = values_size, **dp = malloc(n * sizeof(int *)); + for (int i = 0; i < n; i++) { + dp[i] = malloc(n * sizeof(int)); + dp[i][i] = 0; + if (i + 1 < n) + dp[i][i + 1] = 0; + for (int j = i + 2; j < n; j++) + dp[i][j] = INT_MAX / 3; + } + for (int len = 3; len <= n; len++) { + for (int i = 0; i < n; i++) { + int j = i + len - 1; + if (j >= n) + break; + for (int k = i + 1; k < j; k++) + dp[i][j] = fmin(dp[i][j], dp[i][k] + values[i] * values[k] * values[j] + + dp[k][j]); + } + } + int ans = dp[0][n - 1]; + for (int i = 0; i < n; i++) + free(dp[i]); + free(dp); + return ans; +} + +int main() { + int v1[] = {1, 2, 3}, v2[] = {3, 7, 4, 5}, v3[] = {1, 3, 1, 4, 1, 5}; + printf("%d\n", minScoreTriangulation(v1, 3)); // expect: 6 + printf("%d\n", minScoreTriangulation(v2, 4)); // expect: 144 + printf("%d\n", minScoreTriangulation(v3, 6)); // expect: 13 +} diff --git a/min_size_subarr_sum.c b/min_size_subarr_sum.c new file mode 100644 index 0000000..ee81734 --- /dev/null +++ b/min_size_subarr_sum.c @@ -0,0 +1,37 @@ +// 209. Minimum Size Subarray Sum +#include <limits.h> +#include <stdio.h> + +/* + * given an array of positive integer 'nums' and a positive integer 'target', + * return the minimal length of a subarray whose sum is greater than or equal to + * 'target'. if there is no such subarray, return 0 instead. + */ + +int minSubArrayLen(int target, int *nums, int nums_size) { + int sum = 0, cnt = INT_MAX, left = 0, right = 0; + for (int i = 0; i < nums_size; i++) { + right++; + sum += nums[i]; + if (sum >= target && (right - left) < cnt) + cnt = right - left; + while (sum > target) { + sum -= nums[left]; + left++; + if (sum >= target && (right - left) < cnt) + cnt = right - left; + } + } + if (cnt == INT_MAX) + return 0; + else + return cnt; +} + +int main() { + int n1[] = {2, 3, 1, 2, 4, 3}, n2[] = {1, 4, 4}, + n3[] = {1, 1, 1, 1, 1, 1, 1, 1}; + printf("%d\n", minSubArrayLen(7, n1, 6)); // expect: 2 + printf("%d\n", minSubArrayLen(4, n2, 3)); // expect: 1 + printf("%d\n", minSubArrayLen(11, n3, 8)); // expect: 0 +} diff --git a/min_size_subarr_sum.cpp b/min_size_subarr_sum.cpp new file mode 100644 index 0000000..3e54b2b --- /dev/null +++ b/min_size_subarr_sum.cpp @@ -0,0 +1,32 @@ +// 209. Minimum Size Subarray Sum +#include "leetcode.h" + +/* + * given an array of positive integer 'nums' and a positive integer 'target', + * return the minimal length of a subarray whose sum is greater than or equal to + * 'target'. if there is no such subarray, return 0 instead. + */ + +class Solution { +public: + int minSubArrayLen(int target, vector<int> &nums) { + int i = 0, n = nums.size(), ans = n + 1; + for (int j = 0; j < n; ++j) { + target -= nums[j]; + while (target <= 0) { + ans = min(ans, j - i + 1); + target += nums[i++]; + } + } + return ans % (n + 1); + } +}; + +int main() { + Solution obj; + vector<int> n1 = {2, 3, 1, 2, 4, 3}, n2 = {1, 4, 4}, + n3 = {1, 1, 1, 1, 1, 1, 1, 1}; + printf("%d\n", obj.minSubArrayLen(7, n1)); // expect: 2 + printf("%d\n", obj.minSubArrayLen(4, n2)); // expect: 1 + printf("%d\n", obj.minSubArrayLen(11, n3)); // expect: 0 +} diff --git a/min_speed_arrive_time.c b/min_speed_arrive_time.c new file mode 100644 index 0000000..421093c --- /dev/null +++ b/min_speed_arrive_time.c @@ -0,0 +1,44 @@ +// 1870. Minimum Speed to Arrive on Time +#include <math.h> +#include <stdio.h> + +/* + * given a floating point number 'hour', representing the amount of time you + * have to reach the office. to commute to the office, you must take 'n' trains + * in sequential order. you are also given an integer array 'dist' of length 'n' + * where 'dist[i]' describes the distance in kilometres of the i'th train ride. + * each train can only depart at an integer hour, so you may need to wait in + * between each ride. return the minimum number speed in km/h that all the + * trains must travel at for you to reach the office on time, or '-1' if it is + * possible to be on time. + */ + +double hours(int *dist, int dist_size, double hour) { + double res = 0; + for (int i = 0; i < dist_size - 1; i++) + res += ceil(1.0 * dist[i] / hour); + res += (((double)dist[dist_size - 1]) / hour); + return res; +} + +int minSpeedOnTime(int *dist, int dist_size, double hour) { + if (hour <= dist_size - 1) + return -1; + int left = 1, right = 1e7, mid, ans; + while (left < right) { + mid = (left + right) / 2; + if (hours(dist, dist_size, mid) <= hour) { + right = mid; + ans = mid; + } else + left = mid + 1; + } + return ans; +} + +int main() { + int dist[] = {1, 3, 2}, dist_size = 3; + printf("%d\n", minSpeedOnTime(dist, dist_size, 6)); // expect: 1 + printf("%d\n", minSpeedOnTime(dist, dist_size, 2.7)); // expect: 6 + printf("%d\n", minSpeedOnTime(dist, dist_size, 1.9)); // expect: -1 +} diff --git a/min_speed_arrive_time.cpp b/min_speed_arrive_time.cpp new file mode 100644 index 0000000..55cfa98 --- /dev/null +++ b/min_speed_arrive_time.cpp @@ -0,0 +1,47 @@ +// 1870. Minimum Speed to Arrive on Time +#include "leetcode.h" + +/* + * given a floating point number 'hour', representing the amount of time you + * have to reach the office. to commute to the office, you must take 'n' trains + * in sequential order. you are also given an integer array 'dist' of length 'n' + * where 'dist[i]' describes the distance in kilometres of the i'th train ride. + * each train can only depart at an integer hour, so you may need to wait in + * between each ride. return the minimum number speed in km/h that all the + * trains must travel at for you to reach the office on time, or '-1' if it is + * possible to be on time. + */ + +class Solution { + bool can_reach_on_time(vector<int> &dist, double hour, int speed) { + double time = 0; + for (int i = 0; i < dist.size() - 1; ++i) + time += ((dist[i] + speed - 1) / speed); + time += ((double)dist.back()) / speed; + return time <= hour; + } + +public: + int minSpeedOnTime(vector<int> dist, double hour) { + int n = dist.size(); + if (hour <= n - 1) + return -1; + int low = 1, high = 1e7, mid; + while (low < high) { + mid = (low + high) / 2; + if (can_reach_on_time(dist, hour, mid)) + high = mid; + else + low = mid + 1; + } + return high; + } +}; + +int main() { + Solution obj; + vector<int> dist = {1, 3, 2}; + printf("%d\n", obj.minSpeedOnTime(dist, 6)); // expect: 1 + printf("%d\n", obj.minSpeedOnTime(dist, 2.7)); // expect: 3 + printf("%d\n", obj.minSpeedOnTime(dist, 1.9)); // expect: -1 +} diff --git a/min_stack.cpp b/min_stack.cpp new file mode 100644 index 0000000..745c537 --- /dev/null +++ b/min_stack.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class MinStack { +public: + stack<int> st; + int min = INT_MAX; + void push(int val) { + if (min >= val) { + st.push(min); + min = val; + } + st.push(val); + } + void pop() { + if (min == st.top()) { + st.pop(); + min = st.top(); + } + st.pop(); + } + int top() { return st.top(); } + int getMin() { return min; } +}; diff --git a/min_swap_group_1.c b/min_swap_group_1.c new file mode 100644 index 0000000..4fa2384 --- /dev/null +++ b/min_swap_group_1.c @@ -0,0 +1,53 @@ +// 2134. Minimum Swaps to Group All 1's Together II +#include <math.h> +#include <stdio.h> +#pragma GCC optimize("-O3") + +/* + * a swap is defined as taking two distinct position in an array and swapping + * the values in them. a circular array is defined as an array where we consider + * the first element and the last element to adjacent. given a binary circular + * array 'nums', return the minimum number of swaps required to group all 1's + * preent in the array together at any location. + */ + +int minSwaps(int *nums, int nums_size) { + int ones = 0, n = nums_size; + for (int i = 0; i < n; i++) + if (nums[i] == 1) + ones++; + int cnt = 0; + for (int i = 0; i < ones; i++) + if (nums[i] == 1) + cnt++; + if (cnt == ones) + return 0; + int max = cnt; + for (int i = ones; i < n; i++) { + if (nums[i] == 1) + cnt++; + if (nums[i - ones] == 1) + cnt--; + if (cnt == ones) + return 0; + max = fmax(max, cnt); + } + for (int i = n; i < n + ones; i++) { + if (nums[i % n] == 1) + cnt++; + if (nums[i - ones] == 1) + cnt--; + if (cnt == ones) + return 0; + max = fmax(max, cnt); + } + return ones - max; +} + +int main() { + int n1[] = {0, 1, 0, 1, 1, 0, 0}, n2[] = {0, 1, 1, 1, 0, 0, 1, 1, 0}, + n3[] = {1, 1, 0, 0, 1}; + printf("%d\n", minSwaps(n1, 7)); // expect: 1 + printf("%d\n", minSwaps(n2, 9)); // expect: 2 + printf("%d\n", minSwaps(n3, 5)); // expect: 0 +} diff --git a/min_swap_group_1.cpp b/min_swap_group_1.cpp new file mode 100644 index 0000000..89ab5dd --- /dev/null +++ b/min_swap_group_1.cpp @@ -0,0 +1,40 @@ +// 2134. Minimum Swaps to Group All 1's Together II +#include "leetcode.h" + +/* + * a swap is defined as taking two distinct position in an array and swapping + * the values in them. a circular array is defined as an array where we consider + * the first element and the last element to adjacent. given a binary circular + * array 'nums', return the minimum number of swaps required to group all 1's + * preent in the array together at any location. + */ + +class Solution { +public: + int minSwaps(vector<int> &nums) { + int n = nums.size(), k = 0; + for (int i = 0; i < n; i++) + k += (nums[i] == 1); + nums.insert(nums.end(), nums.begin(), nums.end()); + int ans = n, i = 0, j = 0, l = 0; + while (j < 2 * n) { + l += (nums[j] == 1); + if (j - i + 1 == k) { + ans = min(ans, k - l); + l -= (nums[i] == 1); + i++; + } + j++; + } + return ans == n ? 0 : ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {0, 1, 0, 1, 1, 0, 0}, n2 = {0, 1, 1, 1, 0, 0, 1, 1, 0}, + n3 = {1, 1, 0, 0, 1}; + printf("%d\n", obj.minSwaps(n1)); // expect: 1 + printf("%d\n", obj.minSwaps(n2)); // expect: 2 + printf("%d\n", obj.minSwaps(n3)); // expect: 0 +} diff --git a/min_taps_open_water.c b/min_taps_open_water.c new file mode 100644 index 0000000..77fcf1b --- /dev/null +++ b/min_taps_open_water.c @@ -0,0 +1,49 @@ +// 1326. Minimum Number of Taps to Open to Water a Garden +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * there is a one-dimensional garden on the x-axis. the garden starts at the + * point 0 and ends at the point 'n'. (ie. the length of the garden is 'n') + * there are 'n + q' taps located at points '[0, 1, ..., n]' in the garden. + * given an integer 'n' and an integer array 'ranges' of length 'n + 1' where + * 'ranges[i]' (0-indexed) means the i'th tap can water the area '[i - + * ranges[i], i + ranges[i]]' if it was open. return the minimum number of taps + * that should be open to water the whole garden. if the garden cannot be + * watered, return -1 + */ + +int minTaps(int n, int *ranges, int ranges_size) { + int i, j; + int *new_ranges = (int *)malloc(sizeof(int) * ranges_size); + for (i = 0; i < ranges_size; i++) + new_ranges[i] = ranges[i]; + for (i = ranges_size - 1; i >= 1; i--) + for (j = 1; j <= ranges[i]; j++) { + if (i - j == -1) + break; + new_ranges[i - j] = fmax(new_ranges[i - j], j + ranges[i]); + } + int min_jump; + int *dp = (int *)malloc(sizeof(int) * ranges_size); + dp[ranges_size - 1] = 0; + for (i = 0; i < ranges_size - 1; i++) + dp[i] = 999999; + for (i = ranges_size - 2; i >= 0; i--) { + min_jump = 999999; + for (j = 1; j <= ranges[i]; j++) { + if (i + j == ranges_size) + break; + min_jump = fmin(min_jump, dp[i + j]); + } + dp[i] = min_jump + 1; + } + return (dp[0] < 999999) ? dp[0] : -1; +} + +int main() { + int r1[] = {3, 4, 1, 1, 0, 0}, r2[] = {0, 0, 0, 0}; + printf("%d\n", 1); // expect: 1 + printf("%d\n", minTaps(3, r2, 4)); // expect: -1 +} diff --git a/min_time_apples_tree.cpp b/min_time_apples_tree.cpp new file mode 100644 index 0000000..9e9d4b4 --- /dev/null +++ b/min_time_apples_tree.cpp @@ -0,0 +1,39 @@ +#include "leetcode.h" + +class Solution { +public: + int minTime(int n, vvd(int) & edges, vector<bool> &hasApple) { + unordered_map<int, int> um; + int ans = 0; + sort(edges.begin(), edges.end()); + for (auto const &e : edges) { + if (um.count(e[1]) > 0) + um[e[0]] = e[1]; + else + um[e[1]] = e[0]; + } + for (int i = 0; i < hasApple.size(); ++i) { + if (!hasApple[i]) + continue; + int parent = i; + while (parent != 0 && um[parent] >= 0) { + auto tmp = um[parent]; + um[parent] = -1; + parent = tmp; + ans += 2; + } + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) edges = {{0, 1}, {0, 2}, {1, 4}, {1, 5}, {2, 3}, {2, 6}}; + vector<bool> hasApple1 = {false, false, true, false, true, true, false}, + hasApple2 = {false, false, true, false, false, true, false}, + hasApple3 = {false, false, false, false, false, false, false}; + cout << obj.minTime(7, edges, hasApple1) << endl; // expect: 8 + cout << obj.minTime(7, edges, hasApple2) << endl; // expect: 6 + cout << obj.minTime(7, edges, hasApple3) << endl; // expect: 0 +} diff --git a/min_time_apples_tree.rs b/min_time_apples_tree.rs new file mode 100644 index 0000000..537e5cc --- /dev/null +++ b/min_time_apples_tree.rs @@ -0,0 +1,47 @@ +use std::collections::HashSet; +struct Solution; + +impl Solution { + pub fn min_time(n: i32, edges: Vec<Vec<i32>>, has_apple: Vec<bool>) -> i32 { + let mut adj_list: Vec<Vec<i32>> = vec![vec![]; n as usize]; + for e in edges { + adj_list[e[0] as usize].push(e[1]); + adj_list[e[1] as usize].push(e[0]); + } + let mut total = 0i32; + let mut vis: HashSet<i32> = HashSet::new(); + Self::dfs(0, adj_list, &mut vis, has_apple, &mut total); + total + } + fn dfs(node: i32, adj_list: Vec<Vec<i32>>, vis: &mut HashSet<i32>, + has_apple: Vec<bool>, total: &mut i32) -> bool { + let mut res = false; + if has_apple[node as usize] { + res = true; + } + vis.insert(node); + for i in &adj_list[node as usize] { + if !vis.contains(&i) { + if Self::dfs(*i, adj_list, vis, has_apple, total) { + *total += 2; + res = true; + } + } + } + res + } +} + +fn main() { + let edges = vec![ + vec![0,1], vec![0,2], + vec![1,4], vec![1,5], + vec![2,3], vec![2,6] + ]; + let has_apple1 = vec![false,false,true,false,true,true,false]; + let has_apple2 = vec![false,false,true,false,false,true,false]; + let has_apple3 = vec![false,false,false,false,false,false,false]; + println!("{}", Solution::min_time(7, edges, has_apple1)); //expect: 8 + println!("{}", Solution::min_time(7, edges, has_apple2)); //expect: 6 + println!("{}", Solution::min_time(7, edges, has_apple3)); //expect: 0 +} diff --git a/min_time_collect_garbage.c b/min_time_collect_garbage.c new file mode 100644 index 0000000..82ca6ba --- /dev/null +++ b/min_time_collect_garbage.c @@ -0,0 +1,46 @@ +// 2391. Minimum Amount of Time to Collect Garbage +#include "leetcode.h" + +/* + * given a 0-indexed array of strings 'garbage' where 'garbage[i]' represents + * the assortment of garbage at the i'th house. 'garbage[i]' consists of only + * characters 'M, P, and G' representing one unit of metal, paper, and glass + * garbage respectively. picking up one unitof any type of garbage takes 1 + * minute. you are also given a 0-indexed integer array 'travel' where + * 'travel[i]' is the number of minutes needed to go from house 'i' to house 'i + * + 1'. there are three garbage trucks in the city, each responsible for + * picking up one type of garbage. each garbage truck starts at house 0 and must + * visit each house in order, however they do not need to visit every house. + * only one garbage truck may be used at any given moment. while one truck is + * driving or picking up garbage, the other two trucks cannot do anything. + * return the minimum number of minutes needed to pick up all the garbage. + */ + +int garbageCollection(char **garbage, int garbage_size, int *travel, + int travel_size) { + int total_bag = 0, len, ans = 0; + bool m = false, p = false, g = false; + for (int i = garbage_size - 1; i >= 0; i--) { + len = strlen(garbage[i]); + total_bag += len; + if (!m || !p || !g) { + for (int j = 0; j < len; j++) { + if (!m && garbage[i][j] == 'M') { + m = 1; + for (int k = i - 1; k >= 0; k--) + ans += travel[k]; + } else if (!p && garbage[i][j] == 'P') { + p = 1; + for (int k = i - 1; k >= 0; k--) + ans += travel[k]; + } else if (!g && garbage[i][j] == 'G') { + g = 1; + for (int k = i - 1; k >= 0; k--) + ans += travel[k]; + } + } + } + } + ans += total_bag; + return ans; +} diff --git a/min_time_collect_garbage.py b/min_time_collect_garbage.py new file mode 100644 index 0000000..75ffd9d --- /dev/null +++ b/min_time_collect_garbage.py @@ -0,0 +1,39 @@ +# 2391. Minimum Amount of Time to Collect Garbage +import itertools + +""" +given a 0-indexed array of strings 'garbage' where 'garbage[i]' represents +the assortment of garbage at the i'th house. 'garbage[i]' consists of only +characters 'M, P, and G' representing one unit of metal, paper, and glass +garbage respectively. picking up one unitof any type of garbage takes 1 +minute. you are also given a 0-indexed integer array 'travel' where +'travel[i]' is the number of minutes needed to go from house 'i' to house 'i ++ 1'. there are three garbage trucks in the city, each responsible for +picking up one type of garbage. each garbage truck starts at house 0 and must +visit each house in order, however they do not need to visit every house. +only one garbage truck may be used at any given moment. while one truck is +driving or picking up garbage, the other two trucks cannot do anything. +return the minimum number of minutes needed to pick up all the garbage. +""" + + +class Solution(object): + def garbageCollection(self, garbage, travel): + """ + :type garbage: List[str] + :type travel: List[int] + :rtype: int + """ + last = {c: i for i, pgm in enumerate(garbage) for c in pgm} + dist = list(itertools.accumulate(travel, initial=0)) + return sum(map(len, garbage)) + sum(dist[last.get(c, 0)] for c in "PGM") + + +if __name__ == "__main__": + obj = Solution() + print( + obj.garbageCollection(garbage=["G", "P", "GP", "GG"], travel=[2, 4, 3]) + ) # expect: 21 + print( + obj.garbageCollection(garbage=["MMM", "PGM", "GP"], travel=[3, 10]) + ) # expect: 37 diff --git a/min_time_complete_trip.c b/min_time_complete_trip.c new file mode 100644 index 0000000..f980b18 --- /dev/null +++ b/min_time_complete_trip.c @@ -0,0 +1,33 @@ +// 2187. Minimum Time to Complete Trips +#include <limits.h> +#include <stdio.h> + +/* + * given array 'time' where 'time[i]' denotes the time taken by the 'i'th bus to + * complete one trip. each bus can make multiple trips successively; that is, + * the next trip can start immediately after completing the current trip. also, + * each bus operates independently; that is, the trips of one bus do not + * influence the trips of any other bus. also given an integer 'totalTrips', + * which denotes the number of trips all buses should make in total. return the + * minimum time required to complete all trips. + */ + +long long minimumTime(int *time, int time_size, int total_trips) { + long long l = 0, r = LLONG_MAX / time_size; + while (l < r) { + long long m = (l + r) / 2, trips = 0; + for (int i = 0; i < time_size; i++) + trips += m / time[i]; + if (trips < total_trips) + l = m + 1; + else + r = m; + } + return l; +} + +int main() { + int t1[] = {1, 2, 3}, t2[] = {2}; + printf("%lld\n", minimumTime(t1, 3, 5)); // expect: 3 + printf("%lld\n", minimumTime(t2, 1, 1)); // expect: 2 +} diff --git a/min_time_complete_trip.cpp b/min_time_complete_trip.cpp new file mode 100644 index 0000000..2e325a2 --- /dev/null +++ b/min_time_complete_trip.cpp @@ -0,0 +1,36 @@ +// 2187. Minimum Time to Complete Trips +#include "leetcode.h" + +/* + * given array 'time' where 'time[i]' denotes the time taken by the 'i'th bus to + * complete one trip. each bus can make multiple trips successively; that is, + * the next trip can start immediately after completing the current trip. also, + * each bus operates independently; that is, the trips of one bus do not + * influence the trips of any other bus. also given an integer 'totalTrips', + * which denotes the number of trips all buses should make in total. return the + * minimum time required to complete all trips. + */ + +class Solution { +public: + long long minimumTime(vector<int> &time, int totalTrips) { + long long l = 0, r = LLONG_MAX / time.size(); + while (l < r) { + long long m = (l + r) / 2, trips = 0; + for (int t : time) + trips += m / t; + if (trips < totalTrips) + l = m + 1; + else + r = m; + } + return l; + } +}; + +int main() { + Solution obj; + vector<int> t1 = {1, 2, 3}, t2 = {2}; + printf("%lld\n", obj.minimumTime(t1, 5)); // expect: 3 + printf("%lld\n", obj.minimumTime(t2, 1)); // expect: 2 +} diff --git a/min_time_make_rope_colourful.c b/min_time_make_rope_colourful.c new file mode 100644 index 0000000..2c303d6 --- /dev/null +++ b/min_time_make_rope_colourful.c @@ -0,0 +1,50 @@ +// 1578. Minimum Time to Make Rope Colorful +#include "leetcode.h" + +/* + * alice has 'n' balloons arranged on a rope. you are given a 0-indexed string + * 'colours' where 'colours[i]' is the colour of the i'th balloon. alice wants + * the rope to be colourful. she does not want two consecutive balloons to be + * the of the same colour, so she asks bob for help. bob can remove some + * balloons from the rope to make it colourful. you are given a 0-indexed + * integer array 'needed_time' where 'needed_time[i]' is the time (in seconds) + * that bob needs to remove the i'th balloon from the rope. return the minimum + * time bob needs to make the rop colourful. + */ + +int calc_cost(int idx, int continue_len, int *needed_time) { + int max = needed_time[idx], sum = 0; + for (int i = idx; i < idx + continue_len; i++) { + sum += needed_time[i]; + if (i + 1 < idx + continue_len) + if (needed_time[i + 1] > max) + max = needed_time[i + 1]; + } + return sum - max; +} + +int minCost(char *colours, int *needed_time, int needed_time_size) { + int continue_len = 1, idx = 0, min_cost = 0, cost = 0; + for (int i = 0; i < needed_time_size; i++) { + if (colours[i] == colours[i + 1]) { + continue_len++; + idx = i - continue_len - 2; + } else { + if (continue_len != 1) { + cost = calc_cost(idx, continue_len, needed_time); + min_cost += cost; + cost = 0; + } + continue_len = 1; + } + } + return min_cost; +} + +int main() { + char *c1 = "abaac", *c2 = "abc", *c3 = "aabaa"; + int nt1[] = {1, 2, 3, 4, 5}, nt2[] = {1, 2, 3}, nt3[] = {1, 2, 3, 4, 1}; + printf("%d\n", minCost(c1, nt1, ARRAY_SIZE(nt1))); // expect: 3 + printf("%d\n", minCost(c2, nt2, ARRAY_SIZE(nt2))); // expect: 0 + printf("%d\n", minCost(c3, nt3, ARRAY_SIZE(nt3))); // expect: 2 +} diff --git a/min_time_make_rope_colourful.py b/min_time_make_rope_colourful.py new file mode 100644 index 0000000..9e7d099 --- /dev/null +++ b/min_time_make_rope_colourful.py @@ -0,0 +1,41 @@ +# 1578. Minimum Time to Make Rope Colorful + +""" +alice has 'n' balloons arranged on a rope. you are given a 0-indexed string +'colours' where 'colours[i]' is the colour of the i'th balloon. alice wants +the rope to be colourful. she does not want two consecutive balloons to be +the of the same colour, so she asks bob for help. bob can remove some +balloons from the rope to make it colourful. you are given a 0-indexed +integer array 'needed_time' where 'needed_time[i]' is the time (in seconds) +that bob needs to remove the i'th balloon from the rope. return the minimum +time bob needs to make the rop colourful. +""" + + +class Solution(object): + def minCost(self, colors, neededTime): + """ + :type colors: str + :type neededTime: List[int] + :rtype: int + """ + cost = 0 + i = 0 + j = 0 + while i < len(neededTime) and j < len(neededTime): + curr_cost = 0 + curr_max = 0 + while j < len(neededTime) and colors[i] == colors[j]: + curr_cost += neededTime[j] + curr_max = max(curr_max, neededTime[j]) + j += 1 + cost += curr_cost - curr_max + i = j + return cost + + +if __name__ == "__main__": + obj = Solution() + print(obj.minCost("abaac", [1, 2, 3, 4, 5])) # expect: 3 + print(obj.minCost("abc", [1, 2, 3])) # expect: 0 + print(obj.minCost("aabaa", [1, 2, 3, 4, 1])) # expect: 2 diff --git a/min_time_rope_colorful.cpp b/min_time_rope_colorful.cpp new file mode 100644 index 0000000..9e34c1c --- /dev/null +++ b/min_time_rope_colorful.cpp @@ -0,0 +1,25 @@ +#include "leetcode.h" + +class Solution { +public: + int minCost(string colors, vector<int> &neededTime) { + int ans = 0, maxCost = 0, sumCost = 0, n = colors.size(); + for (int i = 0; i < n; ++i) { + if (i > 0 && colors[i] != colors[i - 1]) { + ans += sumCost - maxCost; + sumCost = maxCost = 0; + } + sumCost += neededTime[i]; + maxCost = max(maxCost, neededTime[i]); + } + ans += sumCost - maxCost; + return ans; + } +}; + +int main() { + Solution obj; + string colors = "abaac"; + vector<int> neededTime = {1, 2, 3, 4, 5}; + cout << obj.minCost(colors, neededTime); +} diff --git a/min_window_substring.c b/min_window_substring.c new file mode 100644 index 0000000..efcd3a5 --- /dev/null +++ b/min_window_substring.c @@ -0,0 +1,67 @@ +// 76. Minimum Window Substring +#include "leetcode.h" + +/* + * given two strings 's' and 't' of length 'n' and 'm' respectively, return the + * minimum window substring of 's' such that every character in 't' (including + * duplicates) is included in the window. if there is no such substring, return + * the empty string. the testcases will be generated such that the answer is + * unique. + */ + +char *minWindow(char *s, char *t) { + int m = strlen(s), n = strlen(t), min = INT_MAX, l = -1, r, match = 0, + a_idx = -1, r_key, l_key; + int *alpha = calloc(52, sizeof(int)); + int *alpha_copy = calloc(52, sizeof(int)); + for (int i = 0; i < n; i++) + (t[i] >= 'a') ? alpha[t[i] - 'a']++ : alpha[t[i] - 'A' + 26]++; + + for (r = 0; r < m; r++) { + r_key = (s[r] >= 'a') ? r_key = s[r] - 'a' : s[r] - 'A' + 26; + + if (alpha[r_key]) { + if (l == -1) + l = r; + alpha_copy[r_key]++; + if (alpha_copy[r_key] <= alpha[r_key]) { + match++; + if (match == n) { + l_key = (s[l] >= 'a') ? s[l] - 'a' : s[l] - 'A' + 26; + while (match == n || !alpha[l_key]) { + if (alpha[l_key]) { + alpha_copy[l_key]--; + if (alpha_copy[l_key] < alpha[l_key]) { + if ((r - l + 1) < min) { + min = r - l + 1; + a_idx = l; + } + match--; + } + } + l++; + if (l < m) + l_key = (s[l] >= 'a') ? s[l] - 'a' : s[l] - 'A' + 26; + else + break; + } + } + } + } + } + if (a_idx == -1) + return ""; + char *ans = malloc((min + 1) * sizeof(char)); + ans[min] = '\0'; + strncpy(ans, &s[a_idx], min); + return ans; +} + +int main() { + char *s1 = "ADOBECODEBANC", *t1 = "ABC"; + char *s2 = "a", *t2 = "a"; + char *s3 = "a", *t3 = "aa"; + printf("%s\n", minWindow(s1, t1)); // expect: BANC + printf("%s\n", minWindow(s2, t2)); // expect: a + printf("%s\n", minWindow(s3, t3)); // expect: null +} diff --git a/min_window_substring.cpp b/min_window_substring.cpp new file mode 100644 index 0000000..c529687 --- /dev/null +++ b/min_window_substring.cpp @@ -0,0 +1,37 @@ +#include "leetcode.h" + +class Solution { +public: + string minWindow(string s, string t) { + unordered_map<char, int> m1, m2; + int check = INT_MAX; + string ans; + for (char &ch : t) + m1[ch]++; + int slow = 0, fast = 0, count = 0; + for (; fast < s.size(); fast++) { + char c = s[fast]; + if (m1.find(c) != m1.end()) { + m2[c]++; + if (m2[c] <= m1[c]) + count++; + } + if (count >= t.size()) { + while (m1.find(s[slow]) == m1.end() || m2[s[slow]] > m1[s[slow]]) { + m2[s[slow]]--; + slow++; + } + if (fast - slow + 1 < check) { + check = fast - slow + 1; + ans = s.substr(slow, check); + } + } + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.minWindow("ADOBECODEBANC", "ABC"); +} diff --git a/min_window_substring.py b/min_window_substring.py new file mode 100644 index 0000000..9ea7da1 --- /dev/null +++ b/min_window_substring.py @@ -0,0 +1,53 @@ +# 76. Minimum Window Substring +from collections import defaultdict + +""" +given two strings 's' and 't' of length 'n' and 'm' respectively, return the +minimum window substring of 's' such that every character in 't' (including +duplicates) is included in the window. if there is no such substring, return +the empty string. the testcases will be generated such that the answer is +unique. +""" + + +class Solution(object): + def minWindow(self, s, t): + """ + :type s: str + :type t: str + :rtype: str + """ + if not s or not t: + return "" + dict_t = defaultdict(int) + for c in t: + dict_t[c] += 1 + required = len(dict_t) + l, r = 0, 0 + formed = 0 + windowCounts = defaultdict(int) + ans = [-1, 0, 0] + while r < len(s): + c = s[r] + windowCounts[c] += 1 + if c in dict_t and windowCounts[c] == dict_t[c]: + formed += 1 + while l <= r and formed == required: + c = s[l] + if ans[0] == -1 or r - l + 1 < ans[0]: + ans[0] = r - l + 1 + ans[1] = l + ans[2] = r + windowCounts[c] -= 1 + if c in dict_t and windowCounts[c] < dict_t[c]: + formed -= 1 + l += 1 + r += 1 + return "" if ans[0] == -1 else s[ans[1] : ans[2] + 1] + + +if __name__ == "__main__": + obj = Solution() + print(obj.minWindow(s="ADOBECODEBANC", t="ABC")) + print(obj.minWindow(s="a", t="a")) + print(obj.minWindow(s="a", t="aa")) diff --git a/min_window_substring.rs b/min_window_substring.rs new file mode 100644 index 0000000..f23402b --- /dev/null +++ b/min_window_substring.rs @@ -0,0 +1,43 @@ +struct Solution; + +impl Solution { + pub fn min_window(s: String, t: String) -> String { + let mut state = [0 as isize; (b'z' - b'A' + 1) as usize]; + let mut target = [0 as isize; (b'z' - b'A' + 1) as usize]; + for b in t.bytes() { + target[(b - b'A') as usize] += 1; + } + let (target, string, mut best_from, mut best_to, mut from, mut to, mut chars_found, chars_expected) = + (target, s.as_bytes(), 0, 0, 0, 0, 0, target.iter().filter(|&&ch| ch > 0).count()); + while to < string.len() { + let ch = (string[to] - b'A') as usize; + if target[ch] > 0 { + if state[ch] + 1 == target[ch] { + chars_found += 1; + } + state[ch] += 1; + } + if chars_found == chars_expected { + let mut fch = (string[from] - b'A') as usize; + while target[fch] == 0 || state[fch] > target[fch] { + if state[fch] > 0 { + state[fch] -= 1; + } + from += 1; + fch = (string[from] - b'A') as usize; + } + if to - from < best_to - best_from || best_to == 0 { + best_from = from; + best_to = to + 1; + } + } + to += 1; + } + s[best_from..best_to].to_string() + } +} + +fn main() { + let (s, t) = (String::from("ADOBECODEBANC"), String::from("ABC")); + print!("{}", Solution::min_window(s, t)); +} diff --git a/minimise_xor.c b/minimise_xor.c new file mode 100644 index 0000000..6dc2a41 --- /dev/null +++ b/minimise_xor.c @@ -0,0 +1,35 @@ +// 2429. Minimize XOR +#include "leetcode.h" + +/* + * given two positive integers 'num1' and 'num2', find the positive integer 'x' + * such that 'x' has the same number of set bits as 'num2', and the value 'x ^ + * num1' is minimal. note that 'xor' is the bitwise xor operator. return the + * integer 'x'. the test cases are generated such that 'x' is uniqueley + * determined. the number of set bits of an integer is the number of 1's in its + * binary representation + */ + +int minimizeXor(int num1, int num2) { + int bit1 = __builtin_popcount(num1); + int bit2 = __builtin_popcount(num2); + if (bit1 == bit2) + return num1; + int ans = num1; + for (int i = 0; i < 32; i++) { + if (!(((uint32_t)1 << i) & num1) && bit2 > bit1) { + ans ^= 1 << i; + bit1++; + } + if ((((uint32_t)1 << i) & num1) && bit2 < bit1) { + ans ^= 1 << i; + bit1--; + } + } + return ans; +} + +int main() { + printf("%d\n", minimizeXor(3, 5)); // expect: 3 + printf("%d\n", minimizeXor(1, 12)); // expect: 3 +} diff --git a/minimise_xor.py b/minimise_xor.py new file mode 100644 index 0000000..d8645f6 --- /dev/null +++ b/minimise_xor.py @@ -0,0 +1,35 @@ +# 2429. Minimize XOR + +""" +given two positive integers 'num1' and 'num2', find the positive integer 'x' +such that 'x' has the same number of set bits as 'num2', and the value 'x ^ +num1' is minimal. note that 'xor' is the bitwise xor operator. return the +integer 'x'. the test cases are generated such that 'x' is uniqueley +determined. the number of set bits of an integer is the number of 1's in its +binary representation +""" + +class Solution(object): + def minimizeXor(self, num1, num2): + """ + :type num1: int + :type num2: int + :rtype: int + """ + a, b = num1.bit_count(), num2.bit_count() + ans = num1 + for i in range(32): + if a > b and (1 << i) & num1 > 0: + ans ^= 1 << i + a -= 1 + if a < b and (1 << i) & num1 == 0: + ans ^= 1 << i + a += 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.minimizeXor(3, 5)) # expect: 3 + print(obj.minimizeXor(1, 12)) # expect: 3 + diff --git a/mirror_reflection.cpp b/mirror_reflection.cpp new file mode 100644 index 0000000..447ce5e --- /dev/null +++ b/mirror_reflection.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + int mirrorReflection(int p, int q) { + while ((p % 2 == 0) && (q % 2 == 0)) { + p /= 2; + q /= 2; + } + if ((p % 2) == 0 && (q % 2) != 0) + return 2; + if ((p % 2) != 0 && (q % 2) != 0) + return 1; + return 0; + } +}; + +int main() { + Solution obj; + cout << obj.mirrorReflection(2, 1); +} diff --git a/missing_number.cpp b/missing_number.cpp new file mode 100644 index 0000000..03dd331 --- /dev/null +++ b/missing_number.cpp @@ -0,0 +1,18 @@ +#include "leetcode.h" + +class Solution { +public: + int missingNumber(vector<int> &nums) { + int sum = 0, n = nums.size(); + int total = n * (n + 1) / 2; + for (auto number : nums) + sum += number; + return total - sum; + } +}; + +int main() { + Solution obj; + vector<int> nums = {9, 6, 4, 2, 3, 5, 7, 0, 1}; + cout << obj.missingNumber(nums); +} diff --git a/monotonic_array.c b/monotonic_array.c new file mode 100644 index 0000000..d6044ff --- /dev/null +++ b/monotonic_array.c @@ -0,0 +1,38 @@ +// 896. Monotonic Array +#include <stdbool.h> +#include <stdio.h> + +/* + * an array is monotonic if it is either monotone increasing or monotone + * decreasing. an array 'nums' is monotone increasing if for all 'i <= j, + * nums[i] <= nums[j]'. an array 'nums' is monotone decreasing if for all 'i <= + * j, nums[i] >= nums[j]'. given an integer array 'nums', return 'true' if the + * given array is monotonic, or 'false' otherwise. + */ + +bool isMonotonic(int *nums, int nums_size) { + int idx = 1; + while (idx + 1 < nums_size) { + if (nums[idx - 1] < nums[idx]) { + while (idx + 1 < nums_size && nums[idx] == nums[idx + 1]) + idx++; + if (idx + 1 < nums_size && nums[idx] > nums[idx + 1]) + return false; + } + if (nums[idx - 1] > nums[idx]) { + while (idx + 1 < nums_size && nums[idx] == nums[idx + 1]) + idx++; + if (idx + 1 < nums_size && nums[idx] < nums[idx + 1]) + return false; + } + idx++; + } + return true; +} + +int main() { + int n1[] = {1, 2, 2, 3}, n2[] = {6, 5, 4, 4}, n3[] = {1, 3, 2}; + printf("%d\n", isMonotonic(n1, 4)); // expect: 1 + printf("%d\n", isMonotonic(n2, 4)); // expect: 1 + printf("%d\n", isMonotonic(n3, 3)); // expect: 0 +} diff --git a/monotonic_array.py b/monotonic_array.py new file mode 100644 index 0000000..82444ad --- /dev/null +++ b/monotonic_array.py @@ -0,0 +1,28 @@ +# 896. Monotonic Array + +""" +an array is monotonic if it is either monotone increasing or monotone +decreasing. an array 'nums' is monotone increasing if for all 'i <= j, +nums[i] <= nums[j]'. an array 'nums' is monotone decreasing if for all 'i <= +j, nums[i] >= nums[j]'. given an integer array 'nums', return 'true' if the +given array is monotonic, or 'false' otherwise. +""" + + +class Solution(object): + def isMonotonic(self, nums): + increasing = True + decreasing = True + for i in range(1, len(nums)): + if nums[i] > nums[i - 1]: + decreasing = False + elif nums[i] < nums[i - 1]: + increasing = False + return increasing or decreasing + + +if __name__ == "__main__": + obj = Solution() + print(obj.isMonotonic([1, 2, 2, 3])) # expect: True + print(obj.isMonotonic([6, 5, 4, 4])) # expect: True + print(obj.isMonotonic([1, 3, 2])) # expect: False diff --git a/montone_increasing_digit.c b/montone_increasing_digit.c new file mode 100644 index 0000000..843db35 --- /dev/null +++ b/montone_increasing_digit.c @@ -0,0 +1,53 @@ +// 738. Monotone Increasing Digits +#include "leetcode.h" + +/* + * an integer has monotone increasing digits if and only if each pair of + * adjacent digts 'x' and 'y' satisfy 'x <= y'. given an integer 'n', return the + * largest number that is less than or equal to 'n' with monotone inccreasing + * digits + */ + +char *int_to_str(int n) { + char *res = malloc(11); + int val = n, idx = 0; + while (val) { + res[idx] = val % 10 + '0'; + val /= 10; + idx++; + } + res[idx] = '\0'; + for (int i = 0; i < idx / 2; i++) { + char tmp = res[i]; + res[i] = res[idx - 1 - i]; + res[idx - 1 - i] = tmp; + } + return res; +} + +int str_to_int(char *s) { + int n = strlen(s), val = 0; + for (int i = 0; i < n; i++) + val *= 10 + s[i] - '0'; + return val; +} + +int monotoneIncreasingDigits(int n) { + char *s = int_to_str(n); + int j = strlen(s), k = j; + for (int i = k - 1; i; i--) { + if (s[i] >= s[i - 1]) + continue; + s[i - 1]--; + j = i; + } + for (int i = j; i < k; i++) + s[i] = '9'; + return str_to_int(s); +} + +int main() { + printf("%d\n", monotoneIncreasingDigits(10)); // expect: 9 + printf("%d\n", monotoneIncreasingDigits(1234)); // expect: 1234 + printf("%d\n", monotoneIncreasingDigits(332)); // expect: 299 +} diff --git a/montone_increasing_digit.py b/montone_increasing_digit.py new file mode 100644 index 0000000..ee9682a --- /dev/null +++ b/montone_increasing_digit.py @@ -0,0 +1,36 @@ +# 738. Monotone Increasing Digits + +""" +an integer has monotone increasing digits if and only if each pair of +adjacent digts 'x' and 'y' satisfy 'x <= y'. given an integer 'n', return the +largest number that is less than or equal to 'n' with monotone inccreasing +digits +""" + + +class Solution(object): + def monotoneIncreasingDigits(self, n): + """ + :type n: int + :rtype: int + """ + if n < 10: + return n + k, idx = n, -1 + num = [int(d) for d in str(k)[::-1]] + for i in range(1, len(num)): + if num[i] > num[i - 1] or (idx != -1 and num[idx] == num[i]): + idx = i + if idx == -1: + return n + for i in range(idx): + num[i] = 9 + num[idx] -= 1 + return int("".join([str(i) for i in num[::-1]])) + + +if __name__ == "__main__": + obj = Solution() + print(obj.monotoneIncreasingDigits(10)) + print(obj.monotoneIncreasingDigits(1234)) + print(obj.monotoneIncreasingDigits(332)) diff --git a/most_profit_assigning_work.c b/most_profit_assigning_work.c new file mode 100644 index 0000000..c6e5567 --- /dev/null +++ b/most_profit_assigning_work.c @@ -0,0 +1,69 @@ +// 826. Most Profit Assigning Work +#include "leetcode.h" + +/* + * you have n jobs and m workers. you are given three arrays: difficulty, + * profit, and worker where difficulty and pofit are the difficulty and profit + * of the i'th job and worker is the ability of the jth worker. every worker can + * be assigned at most one job, but one job can be completed multiple times. + * return the maximum profit we can achieve after assigning the workers to the + * jobs. + */ + +int cmp(const void **a, const void **b) { + int *a1 = *(int **)a; + int *b1 = *(int **)b; + return a1[0] == b1[0] ? a1[1] - b1[1] : a1[0] - b1[0]; +} + +int find_profit_idx(int **set, int difficulty_size, int capability) { + int left = 0, right = difficulty_size - 1, mid; + while (left + 1 < right) { + mid = (left + right) / 2; + if (set[mid][0] <= capability) + left = mid; + else + right = mid - 1; + } + if (set[right][0] <= capability) + return right; + else if (set[left][0] <= capability) + return left; + else + return -1; +} + +int maxProfitAssignment(int *difficulty, int difficultySize, int *profit, + int profitSize, int *worker, int workerSize) { + int i, j; + int **set = (int **)malloc(difficultySize * sizeof(int *)); + for (int i = 0; i < difficultySize; i++) { + set[i] = malloc(2 * sizeof(int)); + set[i][0] = difficulty[i]; + set[i][1] = profit[i]; + } + qsort(set, difficultySize, sizeof(int *), cmp); + int *dp = malloc(difficultySize * sizeof(int)); + dp[0] = set[0][1]; + for (int i = 1; i < difficultySize; i++) + dp[i] = set[i][1] > dp[i - 1] ? set[i][1] : dp[i - 1]; + int ans = 0, idx; + for (int i = 0; i < workerSize; i++) { + idx = find_profit_idx(set, difficultySize, worker[i]); + if (idx != -1) + ans += dp[idx]; + } + for (int i = 0; i < difficultySize; i++) + free(set[i]); + free(set), free(dp); + return ans; +} + +int main() { + int d1[] = {2, 4, 6, 8, 10}, p1[] = {10, 20, 30, 40, 50}, w1[] = {4, 5, 6, 7}; + int d2[] = {85, 47, 57}, p2[] = {24, 66, 99}, w2[] = {40, 25, 25}; + printf("%d\n", maxProfitAssignment(d1, ARRAY_SIZE(d1), p1, ARRAY_SIZE(p1), w1, + ARRAY_SIZE(w1))); // expect: 100 + printf("%d\n", maxProfitAssignment(d2, ARRAY_SIZE(d2), p2, ARRAY_SIZE(p2), w2, + ARRAY_SIZE(w2))); // expect: 0 +} diff --git a/most_profit_assigning_work.py b/most_profit_assigning_work.py new file mode 100644 index 0000000..7fb258b --- /dev/null +++ b/most_profit_assigning_work.py @@ -0,0 +1,62 @@ +# 826. Most Profit Assigning Work + +""" +you have n jobs and m workers. you are given three arrays: difficulty, +profit, and worker where difficulty and pofit are the difficulty and profit +of the i'th job and worker is the ability of the jth worker. every worker can +be assigned at most one job, but one job can be completed multiple times. +return the maximum profit we can achieve after assigning the workers to the +jobs. +""" + + +class Solution(object): + def maxProfitAssignment(self, difficulty, profit, worker): + """ + :type difficulty: List[int] + :type profit: List[int] + :type worker: List[int] + :rtype: int + """ + max_profit_difficulty = [] + info = list(zip(difficulty, profit)) + info.sort(key=lambda x: x[0]) + max_p = 0 + for i in info: + d, p = i + max_p = max(max_p, p) + max_profit_difficulty.append((d, max_p)) + + def bin_search(l, upperbound): + i, j = 0, len(l) - 1 + while i < j: + mid = (i + j) // 2 + 1 + if l[mid][0] <= upperbound: + i = mid + else: + j = mid - 1 + return i + + total_profit = 0 + for w in worker: + idx = bin_search(max_profit_difficulty, w) + d, p = max_profit_difficulty[idx] + if w >= d: + total_profit += p + return total_profit + + +if __name__ == "__main__": + obj = Solution() + print( + obj.maxProfitAssignment( + difficulty=[2, 4, 6, 8, 10], + profit=[10, 20, 30, 40, 50], + worker=[4, 5, 6, 7], + ) + ) + print( + obj.maxProfitAssignment( + difficulty=[85, 47, 57], profit=[24, 66, 99], worker=[40, 25, 25] + ) + ) diff --git a/most_stones_remove.cpp b/most_stones_remove.cpp new file mode 100644 index 0000000..5283383 --- /dev/null +++ b/most_stones_remove.cpp @@ -0,0 +1,35 @@ +#include "leetcode.h" + +class Solution { +public: + int removeStones(vvd(int) & stones) { + int n = stones.size(), c = 0; + unordered_map<int, vector<int>> rows, cols; + for (int i = 0; i < n; ++i) { + rows[stones[i][0]].push_back(i); + cols[stones[i][1]].push_back(i); + } + unordered_set<int> seen; + function<int(int)> dfs; + dfs = [&](int i) -> int { + if (seen.count(i)) + return 0; + seen.insert(i); + int j = stones[i][0], k = stones[i][1]; + for (auto r : rows[j]) + dfs(r); + for (auto c : cols[k]) + dfs(c); + return 1; + }; + for (int i = 0; i < n; ++i) + c += dfs(i); + return n - c; + } +}; + +int main() { + Solution obj; + vvd(int) stones = {{0, 0}, {0, 1}, {1, 0}, {1, 2}, {2, 1}, {2, 2}}; + cout << obj.removeStones(stones); +} diff --git a/most_stones_remove.rs b/most_stones_remove.rs new file mode 100644 index 0000000..8dc890d --- /dev/null +++ b/most_stones_remove.rs @@ -0,0 +1,49 @@ +use std::collections::HashMap; +struct Solution; + +impl Solution { + pub fn remove_stones(stones: Vec<Vec<i32>>) -> i32 { + let mut ans = 0; + let mut parent: Vec<usize> = (0..stones.len()).collect(); + let mut rows: HashMap<i32, usize> = HashMap::new(); + let mut cols: HashMap<i32, usize> = HashMap::new(); + for (i, v) in stones.iter().enumerate() { + match rows.get(&v[0]) { + Some(&j) => if Self::union_stone(i, j, &mut parent) { + ans += 1; + } + None => { rows.insert(v[0], i); } + } + match cols.get(&v[1]) { + Some(&j) => if Self::union_stone(i, j, &mut parent) { + ans += 1; + } + None => { cols.insert(v[1], i); } + } + } + ans + } + fn union_stone(i: usize, j: usize, parent: &mut Vec<usize>) -> bool { + let i_root = Self::find_set(i, parent); + let j_root = Self::find_set(j, parent); + parent[i_root] = j_root; + i_root != j_root + } + fn find_set(x: usize, parent: &mut Vec<usize>) -> usize { + if x != parent[x] { + parent[x] = Self::find_set(parent[x], parent); + } + parent[x] + } +} + +fn main() { + let stones = vec![ + vec![0,0], + vec![0,1], + vec![1,0], + vec![1,2], + vec![2,1], + vec![2,2]]; + print!("{}", Solution::remove_stones(stones)); +} diff --git a/most_water.cpp b/most_water.cpp new file mode 100644 index 0000000..89d4e19 --- /dev/null +++ b/most_water.cpp @@ -0,0 +1,21 @@ +#include <bits/stdc++.h> +using namespace std; + +class Solution { +public: + int maxArea(vector<int> &height) { + int start = 0, max = 0, end = height.size() - 1; + while (start < end) { + int x = end - start; + int y = height[start] > height[end] ? height[end] : height[start]; + max = (x * y) > max ? (x * y) : max; + if (height[start] > height[end]) + end--; + else + start++; + } + return max; + } +}; + +int main() {} diff --git a/multiply_strings.cpp b/multiply_strings.cpp new file mode 100644 index 0000000..115b85c --- /dev/null +++ b/multiply_strings.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + string multiply(string num1, string num2) { + if (num1 == "0" || num2 == "0") + return "0"; + vector<int> res(num1.size() + num2.size(), 0); + for (int i = num1.size() - 1; i >= 0; i--) { + for (int j = num2.size() - 1; j >= 0; j--) { + res[i + j + 1] += (num1[i] - '0') * (num2[j] - '0'); + res[i + j] += res[i + j + 1] / 10; + res[i + j + 1] %= 10; + } + } + int i = 0; + string ans = ""; + while (res[i] == 0) + i++; + while (i < res.size()) + ans += to_string(res[i++]); + return ans; + } +}; + +int main() {} diff --git a/my_calendar.cpp b/my_calendar.cpp new file mode 100644 index 0000000..7666e1e --- /dev/null +++ b/my_calendar.cpp @@ -0,0 +1,38 @@ +#include "leetcode.h" + +struct lNode { +public: + int start, end; + lNode *next; + lNode(int s, int e, lNode *n) { + start = s; + end = e; + next = n; + } +}; + +class MyCalendar { +public: + MyCalendar() { + lNode *tail = new lNode(INT_MAX, INT_MAX, nullptr); + calendar = new lNode(-1, -1, tail); + } + bool book(int start, int end) { + lNode *curr = calendar, *last = curr; + while (start >= curr->end) + last = curr, curr = curr->next; + if (curr->start < end) + return false; + last->next = new lNode(start, end, curr); + return true; + } + +private: + lNode *calendar; +}; + +int main() { + int start, end; + MyCalendar *obj = new MyCalendar(); + bool param_1 = obj->book(start, end); +} diff --git a/my_calendar2.cpp b/my_calendar2.cpp new file mode 100644 index 0000000..a9ada1e --- /dev/null +++ b/my_calendar2.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class MyCalendarTwo { +public: + map<int, int> m; + MyCalendarTwo() {} + bool book(int start, int end) { + m[start]++; + m[end]--; + int booked = 0; + for (auto it = m.begin(); it != m.end(); it++) { + booked += it->second; + if (booked == 3) { + m[start]--; + m[end]++; + return false; + } + } + return true; + } +}; + +int main() { + int start, end; + MyCalendarTwo *obj = new MyCalendarTwo(); + bool param_1 = obj->book(start, end); + if (param_1) + cout << "true"; + else + cout << "false"; +} diff --git a/my_calendar3.cpp b/my_calendar3.cpp new file mode 100644 index 0000000..25de075 --- /dev/null +++ b/my_calendar3.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class MyCalendarThree { +public: + map<int, int> count = {{-1, 0}}; + int ans = 0; + MyCalendarThree() {} + int book(int start, int end) { + auto s = count.emplace(start, (--count.upper_bound(start))->second); + auto e = count.emplace(end, (--count.upper_bound(end))->second); + for (auto i = s.first; i != e.first; ++i) + ans = max(ans, ++(i->second)); + return ans; + } +}; + +int main() { + int start, end; + MyCalendarThree *obj = new MyCalendarThree(); + int param_1 = obj->book(start, end); +} diff --git a/n_ary_tree_traverse.cpp b/n_ary_tree_traverse.cpp new file mode 100644 index 0000000..d6cbebd --- /dev/null +++ b/n_ary_tree_traverse.cpp @@ -0,0 +1,25 @@ +#include "leetcode.h" + +class Solution { +public: + vvd(int) levelOrder(Node *root) { + vvd(int) ans; + if (!root) + return ans; + queue<Node *> q; + q.push(root); + while (!q.empty()) { + int n = q.size(); + vector<int> v; + while (n--) { + auto curr = q.front(); + q.pop(); + v.push_back(curr->val); + for (auto it : curr->children) + q.push(it); + } + ans.push_back(v); + } + return ans; + } +}; diff --git a/n_queens.cpp b/n_queens.cpp new file mode 100644 index 0000000..df2457e --- /dev/null +++ b/n_queens.cpp @@ -0,0 +1,43 @@ +#include "leetcode.h" + +class Solution { +public: + vector<vector<string>> solveNQueens(int n) { + vector<vector<string>> ans; + vector<string> nQueens(n, string(n, '.')); + solve(ans, nQueens, 0, n); + return ans; + } + +private: + void solve(vector<vector<string>> &ans, vector<string> &nQueens, int row, + int &n) { + if (row == n) { + ans.push_back(nQueens); + return; + } + for (int col = 0; col != n; ++col) + if (isValid(nQueens, row, col, n)) { + nQueens[row][col] = 'Q'; + solve(ans, nQueens, row + 1, n); + nQueens[row][col] = '.'; + } + } + bool isValid(vector<string> &nQueens, int row, int col, int &n) { + // check if col had queen + for (int i = 0; i != row; ++i) + if (nQueens[i][col] == 'Q') + return false; + // check if 45deg diagonal had queen + for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; --i, --j) + if (nQueens[i][j] == 'Q') + return false; + // check if 135deg diagonal had queen + for (int i = row - 1, j = col + 1; i >= 0 && j < n; --i, ++j) + if (nQueens[i][j] == 'Q') + return false; + return true; + } +}; + +int main() {} diff --git a/n_queens2.cpp b/n_queens2.cpp new file mode 100644 index 0000000..2af1bcd --- /dev/null +++ b/n_queens2.cpp @@ -0,0 +1,35 @@ +#include "leetcode.h" + +class Solution { +public: + int totalNQueens(int n) { + vector<bool> col(n, true); + vector<bool> anti(2 * n - 1, true); + vector<bool> main(2 * n - 1, true); + vector<int> row(n, 0); + int count = 0; + helper(0, row, col, main, anti, count); + return count; + } + +private: + void helper(int i, vector<int> &row, vector<bool> &col, vector<bool> &main, + vector<bool> &anti, int &count) { + if (i == row.size()) { + count++; + return; + } + for (int j = 0; j < col.size(); j++) + if (col[j] && main[i + j] && anti[i + col.size() - 1 - j]) { + row[i] = j; + col[j] = main[i + j] = anti[i + col.size() - 1 - j] = false; + helper(i + 1, row, col, main, anti, count); + col[j] = main[i + j] = anti[i + col.size() - 1 - j] = true; + } + } +}; + +int main() { + Solution obj; + cout << obj.totalNQueens(4); +} diff --git a/naming_company.cpp b/naming_company.cpp new file mode 100644 index 0000000..24de89f --- /dev/null +++ b/naming_company.cpp @@ -0,0 +1,37 @@ +// 2306. Naming a Company +#include "leetcode.h" + +/* + * you are given an array of strings 'ideas' that represents a list of names to + * be used in the process o naming a company. the process of naming a company is + * as follows: chose 2 distinct names from 'ideas', call them 'ideaa, ideab'. + * swap the first letters of 'ideaa & ideab' with each other. + * if both the new names are not found in the original 'ideas', then the name + * 'ideaa ideab' (concatenated, separated by space) is a valid company name. + */ + +class Solution { +public: + long long distinctNames(vector<string> &ideas) { + long long ans = 0, cnt[26][26] = {}; + unordered_set<string> us[26]; + for (auto &i : ideas) + us[i[0] - 'a'].insert(i.substr(1)); + for (int i = 0; i < 26; ++i) + for (auto &suffix : us[i]) + for (int j = 0; j < 26; ++j) + cnt[i][j] += us[j].count(suffix) == 0; + for (int i = 0; i < 26; ++i) + for (int j = 0; j < 26; ++j) + ans += cnt[i][j] * cnt[j][i]; + return ans; + } +}; + +int main() { + Solution obj; + vector<string> ideas1 = {"coffee", "donuts", "time", "toffee"}, + ideas2 = {"lack", "back"}; + cout << obj.distinctNames(ideas1) << endl; // expect: 6 + cout << obj.distinctNames(ideas2) << endl; // expect: 0 +} diff --git a/nearest_exit_maze.cpp b/nearest_exit_maze.cpp new file mode 100644 index 0000000..2e0a4cf --- /dev/null +++ b/nearest_exit_maze.cpp @@ -0,0 +1,37 @@ +#include "leetcode.h" + +class Solution { +public: + int nearestExit(vvd(char) & maze, vector<int> &entrance) { + int m = maze.size(), n = maze[0].size(); + int dirs[5] = {0, -1, 0, 1, 0}; + auto isExit = [&](int i, int j) -> int { + return (i != entrance[0] || j != entrance[1]) && + (i * j == 0 || i == m - 1 || j == n - 1); + }; + deque<array<int, 3>> dqa = {{entrance[0], entrance[1], 0}}; + while (!dqa.empty()) { + auto [i, j, s] = dqa.front(); + dqa.pop_front(); + for (int d = 0; d < 4; ++d) { + int i2 = i + dirs[d]; + int j2 = j + dirs[d + 1]; + if (i2 < 0 || i2 >= m || j2 < 0 || j2 >= n || maze[i2][j2] == '+') + continue; + maze[i2][j2] = '+'; + if (isExit(i2, j2)) + return s + 1; + dqa.push_back({i2, j2, s + 1}); + } + } + return -1; + } +}; + +int main() { + Solution obj; + vvd(char) + maze = {{'+', '+', '.', '+'}, {'.', '.', '.', '+'}, {'+', '+', '+', '.'}}; + vector<int> entrance = {1, 2}; + cout << obj.nearestExit(maze, entrance); +} diff --git a/nearest_exit_maze.rs b/nearest_exit_maze.rs new file mode 100644 index 0000000..3f314f2 --- /dev/null +++ b/nearest_exit_maze.rs @@ -0,0 +1,37 @@ +use std::collections::VecDeque; +use std::collections::HashSet; +struct Solution; + +impl Solution { + pub fn nearest_exit(maze: Vec<Vec<char>>, entrance: Vec<i32>) -> i32 { + let (mut dq, mut visited) = (VecDeque::new(), HashSet::new()); + dq.push_back((entrance[0] as usize, entrance[1] as usize, 0)); + while !dq.is_empty() { + while let Some((i, j, c)) = dq.pop_front() { + if !visited.insert((i, j)) { + continue; + } + if i == 0 || i == maze.len() - 1 || j == 0 || j == maze[0].len() - 1 { + if i != entrance[0] as usize || j != entrance[1] as usize { + return c; + } + } + if maze[i][j] == '.' { + if i > 0 && maze[i - 1][j] == '.' { + dq.push_back((i - 1, j, c + 1)); + } + if i < maze.len() - 1 && maze[i + 1][j] == '.' { + dq.push_back((i + 1, j, c + 1)); + } + if j > 0 && maze[i][j - 1] == '.' { + dq.push_back((i, j - 1, c + 1)); + } + if j < maze[0].len() - 1 && maze[i][j + 1] == '.' { + dq.push_back((i, j + 1, c + 1)); + } + } + } + } + -1 + } +} diff --git a/network_delay_time.cpp b/network_delay_time.cpp new file mode 100644 index 0000000..7d46995 --- /dev/null +++ b/network_delay_time.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + int networkDelayTime(vector<vector<int>> ×, int n, int k) { + vector<int> dist(n + 1, INT_MAX); + dist[k] = 0; + for (int i = 0; i < n; i++) { + for (vector<int> e : times) { + int u = e[0], v = e[1], w = e[2]; + if (dist[u] != INT_MAX && dist[v] > dist[u] + w) + dist[v] = dist[u] + w; + } + } + int maxWait = 0; + for (int i = 1; i <= n; i++) + maxWait = max(maxWait, dist[i]); + return maxWait == INT_MAX ? -1 : maxWait; + } +}; + +int main() {} diff --git a/new_21_game.c b/new_21_game.c new file mode 100644 index 0000000..4076f33 --- /dev/null +++ b/new_21_game.c @@ -0,0 +1,38 @@ +// 837. New 21 Game +#include <stdio.h> +#include <stdlib.h> + +/* + * alice plays the following game, loosely based on the card game "21". alice + * starts with 0 points and draws numbers while she has less than 'k' points. + * during each draw, she gains an integer number of points randomly from range + * '[1, max_pts]', where 'max_pts' is an integer. each draw is independent and + * the outcomes have equal posibilities. alice stops drawing numbers when she + * gets 'k' or more points. return the probability that alice has 'n' or fewer + * points. answers within 10^-5 of the actual answer are considered accepted + */ + +double new21Game(int n, int k, int max_pts) { + if (!k || n >= k + max_pts) + return 1.0; + double *dp = malloc((n + 1) * sizeof(double)); + dp[0] = 1.0; + double sum = 1.0, ans = 0.0; + for (int i = 1; i <= n; ++i) { + dp[i] = sum / max_pts; + if (i < k) + sum += dp[i]; + else + ans += dp[i]; + if (i - max_pts >= 0) + sum -= dp[i - max_pts]; + } + return ans; +} + +int main() { + // new21Game(21,17,10); + printf("%f\n", new21Game(10, 1, 10)); // expect: 1.00000 + printf("%f\n", new21Game(6, 1, 10)); // expect: 0.60000 + printf("%f\n", new21Game(21, 17, 10)); // expect: 0.73278 +} diff --git a/new_21_game.cpp b/new_21_game.cpp new file mode 100644 index 0000000..dc21609 --- /dev/null +++ b/new_21_game.cpp @@ -0,0 +1,40 @@ +// 837. New 21 Game +#include "leetcode.h" + +/* + * alice plays the following game, loosely based on the card game "21". alice + * starts with 0 points and draws numbers while she has less than 'k' points. + * during each draw, she gains an integer number of points randomly from range + * '[1, max_pts]', where 'max_pts' is an integer. each draw is independent and + * the outcomes have equal posibilities. alice stops drawing numbers when she + * gets 'k' or more points. return the probability that alice has 'n' or fewer + * points. answers within 10^-5 of the actual answer are considered accepted + */ + +class Solution { +public: + double new21Game(int n, int k, int max_pts) { + if (!k || n >= k + max_pts) + return 1.0; + vector<double> dp(n + 1); + dp[0] = 1.0; + double sum = 1.0, ans = 0.0; + for (int i = 1; i <= n; ++i) { + dp[i] = sum / max_pts; + if (i < k) + sum += dp[i]; + else + ans += dp[i]; + if (i - max_pts >= 0) + sum -= dp[i - max_pts]; + } + return ans; + } +}; + +int main() { + Solution obj; + printf("%f\n", obj.new21Game(10, 1, 10)); // expect: 1.00000 + printf("%f\n", obj.new21Game(6, 1, 10)); // expect: 0.60000 + printf("%f\n", obj.new21Game(21, 17, 10)); // expect: 0.73278 +} diff --git a/next_greater_element2.cpp b/next_greater_element2.cpp new file mode 100644 index 0000000..c6a8412 --- /dev/null +++ b/next_greater_element2.cpp @@ -0,0 +1,43 @@ +// 503. Next Greater Element II +#include "leetcode.h" + +/* + * given a circular integer array 'nums' (ie. the next element 'nums[nums.length + * - 1]' is 'nums[0]') return the next greater number for every element in + * 'nums'. the next greater number of a number 'x' is the first greater number + * to its traversing-order next in the array, which means you could search + * circularly to find its next greater number. if it doesn't exist, return -1 + */ + +class Solution { +public: + vector<int> nextGreatestElements(vector<int> &nums) { + int n = nums.size(); + nums.resize(n * 2); + for (int i = n; i < n * 2; i++) + nums[i] = nums[i - n]; + vector<int> ans(n, -1); + stack<int> s; + for (int i = 0; i < n * 2; i++) { + int elem = nums[i]; + while (!s.empty() && elem > nums[s.top()]) { + if (s.top() >= n) + s.top() = s.top() - n; + ans[s.top()] = elem; + s.pop(); + } + s.push(i); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 2, 1}, n2 = {1, 2, 3, 4, 3}; + for (auto i : obj.nextGreatestElements(n1)) + printf("%d ", i); // expect: 2 -1 2 + printf("\n"); + for (auto i : obj.nextGreatestElements(n2)) + printf("%d ", i); // expect: 2 3 4 -1 4 +} diff --git a/next_permutation.cpp b/next_permutation.cpp new file mode 100644 index 0000000..95e70f4 --- /dev/null +++ b/next_permutation.cpp @@ -0,0 +1,37 @@ +#include <bits/stdc++.h> +#include <vector> +using namespace std; + +class Solution { +public: + void nextPermutation(vector<int> &nums) { + int i = nums.size() - 2; + while (i >= 0 && nums[i + 1] <= nums[i]) + i--; + if (i >= 0) { + int j = nums.size() - 1; + while (nums[j] <= nums[i]) + j--; + swap(nums, i, j); + } + reverse(nums, i + 1); + } + +private: + void reverse(vector<int> &nums, int start) { + int i = start, j = nums.size() - 1; + while (i < j) { + swap(nums, i, j); + i++; + j--; + } + } + + void swap(vector<int> &nums, int i, int j) { + int temp = nums[i]; + nums[i] = nums[j]; + nums[j] = temp; + } +}; + +int main() {} diff --git a/non_decreasing_array.cpp b/non_decreasing_array.cpp new file mode 100644 index 0000000..6ea4280 --- /dev/null +++ b/non_decreasing_array.cpp @@ -0,0 +1,27 @@ +#include "leetcode.h" + +class Solution { +public: + bool checkPossibility(vector<int> &nums) { + for (int i = 0; i < nums.size() - 1; i++) { + if (nums[i] > nums[i + 1]) { + if (i - 1 >= 0 && nums[i - 1] > nums[i + 1]) + nums[i + 1] = nums[i]; + else + nums[i] = nums[i + 1]; + break; + } + } + for (int i = 0; i < nums.size() - 1; i++) { + if (nums[i] > nums[i + 1]) + return false; + } + return true; + } +}; + +int main() { + Solution obj; + vector<int> nums = {4, 2, 3}; + cout << obj.checkPossibility(nums); +} diff --git a/non_decreasing_subseq.c b/non_decreasing_subseq.c new file mode 100644 index 0000000..9f46243 --- /dev/null +++ b/non_decreasing_subseq.c @@ -0,0 +1,59 @@ +// 491. Non-decreasing Subsequences +#include <stdio.h> +#include <stdlib.h> + +/* + * given: integer array 'nums' + * return: all possible different non-decreasing subsequences + * of given array with at least two elements. return value can be in any order + * + * returns an array of arrays of size '*returnSize' + * sizes of the arrays are returned as '*returnColumnSizes' array + * note: both returned array and '*columnSizes' array must be malloc'd + * (assume caller free()'s) + */ + +int **ans, ansTop, *path, pathTop, *len; + +int findUsed(int *uset, int usetSize, int key) { + for (int i = 0; i < usetSize; i++) + if (uset[i] == key) + return 1; + return 0; +} + +void backtracking(int *nums, int numsSize, int startIdx) { + if (pathTop >= 2) { + int *tmp = malloc(sizeof(int) * pathTop); + for (int i = 0; i < pathTop; i++) + tmp[i] = path[i]; + len[ansTop] = pathTop; + ans[ansTop++] = tmp; + } + int *uset = malloc(sizeof(int) * numsSize), usetTop = 0; + for (int i = startIdx; i < numsSize; i++) { + if (pathTop > 0 && nums[i] < path[pathTop - 1] || + findUsed(uset, usetTop, nums[i])) + continue; + uset[usetTop++] = nums[i]; + path[pathTop++] = nums[i]; + backtracking(nums, numsSize, i + 1); + pathTop--; + } +} + +int **findSubsequences(int *nums, int numsSize, int *returnSize, + int **returnColumnSizes) { + ans = malloc(sizeof(int *) * 40000); + path = malloc(sizeof(int) * numsSize); + len = malloc(sizeof(int) * 40000); + pathTop = ansTop = 0; + backtracking(nums, numsSize, 0); + *returnSize = ansTop; + *returnColumnSizes = malloc(sizeof(int) * ansTop); + for (int i = 0; i < ansTop; i++) + (*returnColumnSizes)[i] = len[i]; + return ans; +} + +int main() { int nums1[] = {4, 6, 7, 7}, nums2[] = {4, 4, 3, 2, 1}; } diff --git a/non_decreasing_subseq.cpp b/non_decreasing_subseq.cpp new file mode 100644 index 0000000..0b45930 --- /dev/null +++ b/non_decreasing_subseq.cpp @@ -0,0 +1,43 @@ +// 491. Non-decreasing Subsequences +#include "leetcode.h" + +/* + * given: integer array 'nums' + * return: all possible different non-decreasing subsequences + * of given array with at least two elements. return value + * can be in any order + */ + +class Solution { +public: + vvd(int) findSubsequences(vector<int> &nums) { + set<vector<int>> seqs = {vector<int>(0)}; + for (int i = 0; i < nums.size(); i++) { + vvd(int) built(seqs.size()); + copy(seqs.begin(), seqs.end(), built.begin()); + for (auto s : built) { + if (s.empty() || nums[i] >= s.back()) { + s.push_back(nums[i]); + seqs.insert(s); + } + } + } + vvd(int) ans; + for (auto s : seqs) + if (s.size() > 1) + ans.push_back(s); + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums1 = {4, 6, 7, 7}, nums2 = {4, 4, 3, 2, 1}; + for (auto i : obj.findSubsequences(nums1)) + for (auto j : i) + cout << j << ' '; + cout << endl; + for (auto i : obj.findSubsequences(nums2)) + for (auto j : i) + cout << j << ' '; +} diff --git a/non_overlapping_interval.c b/non_overlapping_interval.c new file mode 100644 index 0000000..c9f0288 --- /dev/null +++ b/non_overlapping_interval.c @@ -0,0 +1,30 @@ +// 435. Non-overlapping Intervals +#include <stdbool.h> +#include <stdlib.h> + +/* + * given an array of intervals 'intervals' where 'intervals[i] = [start[i], + * end[i]]', return the minimum number of intervals you need to remove to make + * the rest of the intervals non-overlapping + */ + +int cmp(const void **a, const void **b) { + int *a1 = *(int **)a; + int *b1 = *(int **)b; + if (a1[1] == b1[1]) + return a1[0] - b1[0]; + return a1[1] - b1[1]; +} + +int eraseOverlapIntervals(int **intervals, int intervals_size, + int *intervals_col_size) { + qsort(intervals, intervals_size, sizeof(int *), cmp); + int k = intervals[0][1], ans = 0; + for (int i = 1; i < intervals_size; i++) { + if (intervals[i][0] < k) + ans++; + else + k = intervals[i][1]; + } + return ans; +} diff --git a/non_overlapping_interval.cpp b/non_overlapping_interval.cpp new file mode 100644 index 0000000..3cadb8d --- /dev/null +++ b/non_overlapping_interval.cpp @@ -0,0 +1,38 @@ +// 435. Non-overlapping Intervals +#include "leetcode.h" + +/* + * given an array of intervals 'intervals' where 'intervals[i] = [start[i], + * end[i]]', return the minimum number of intervals you need to remove to make + * the rest of the intervals non-overlapping + */ + +class Solution { + static bool cmp(vector<int> &a, vector<int> &b) { return a[1] < b[1]; } + +public: + int eraseOverlapIntervals(vvd(int) & intervals) { + int ans = -1; + if (!intervals.size()) + return 0; + sort(intervals.begin(), intervals.end(), cmp); + vector<int> prev = intervals[0]; + for (vector<int> i : intervals) { + if (prev[1] > i[0]) + ans++; + else + prev = i; + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) i1 = {{1, 2}, {2, 3}, {3, 4}, {1, 3}}; + vvd(int) i2 = {{1, 2}, {1, 2}, {1, 2}}; + vvd(int) i3 = {{1, 2}, {2, 3}}; + printf("%d\n", obj.eraseOverlapIntervals(i1)); // expect: 1 + printf("%d\n", obj.eraseOverlapIntervals(i2)); // expect: 2 + printf("%d\n", obj.eraseOverlapIntervals(i3)); // expect: 0 +} diff --git a/nth_tribonacci_number.c b/nth_tribonacci_number.c new file mode 100644 index 0000000..06b374a --- /dev/null +++ b/nth_tribonacci_number.c @@ -0,0 +1,31 @@ +// 1137. N-th Tribonacci Number +#include "leetcode.h" + +/* + * the tribonacci sequence t^n is defined as follows + * t0 = 0, t1 = 1, t2 = 1, & tn+3 = tn + tn+1 + tn+2 for n >= 0 + * given n, return value of tn + * eg. + * n = 4, output: 4 + * t3 = 0 + 1 + 1 = 2 + * t4 = 1 + 1 + 2 = 4 + */ + +int tribonacci(int n) { + if (n == 0) + return 0; + if (n == 1 || n == 2) + return 1; + int *tmp = malloc(sizeof(int) * (n + 1)); + tmp[0] = 0; + tmp[1] = 1; + tmp[2] = 1; + for (int i = 3; i <= n; i++) + tmp[i] = tmp[i - 1] + tmp[i - 2] + tmp[i - 3]; + return tmp[n]; +} + +int main() { + printf("%d\n", tribonacci(4)); // expect: 4 + printf("%d\n", tribonacci(25)); // expect: 1389537 +} diff --git a/nth_tribonacci_number.cpp b/nth_tribonacci_number.cpp new file mode 100644 index 0000000..cabdb39 --- /dev/null +++ b/nth_tribonacci_number.cpp @@ -0,0 +1,61 @@ +// 1137. N-th Tribonacci Number +#include "leetcode.h" + +/* + * the tribonacci sequence t^n is defined as follows + * t0 = 0, t1 = 1, t2 = 1, & tn+3 = tn + tn+1 + tn+2 for n >= 0 + * given n, return value of tn + * eg. + * n = 4, output: 4 + * t3 = 0 + 1 + 1 = 2 + * t4 = 1 + 1 + 2 = 4 + */ + +typedef long long ll; +struct Matrix { + vvd(ll) a; + int rows, cols; + Matrix(int rows = 0, int cols = 0) : rows(rows), cols(cols) { + a.resize(rows); + for (int i = 0; i < rows; ++i) + a[i].assign(cols, 0); + } + Matrix(const vvd(ll) & matrix) + : a(matrix), rows(matrix.size()), cols(matrix[0].size()) {} +}; + +Matrix operator*(const Matrix &a, const Matrix &b) { + Matrix res(a.rows, b.cols); + for (int i = 0; i < a.rows; ++i) + for (int j = 0; j < b.cols; ++j) + for (int k = 0; k < a.cols; ++k) + res.a[i][j] += a.a[i][k] * b.a[k][j]; + return res; +} + +Matrix fastPow(const Matrix &matrix, int pow) { + if (pow == 1) + return matrix; + Matrix half = fastPow(matrix, pow / 2); + if (pow & 1) + return half * half * matrix; + return half * half; +} + +class Solution { +public: + int tribonacci(int n) { + if (n == 0) + return 0; + Matrix m({{0, 1, 0}, {0, 0, 1}, {1, 1, 1}}); + Matrix m0({{0}, {1}, {1}}); + Matrix mn = fastPow(m, n) * m0; + return mn.a[0][0]; + } +}; + +int main() { + Solution obj; + cout << obj.tribonacci(4) << endl; // expect: 4 + cout << obj.tribonacci(25) << endl; // expect: 1389537 +} diff --git a/nth_tribonacci_number.py b/nth_tribonacci_number.py new file mode 100644 index 0000000..c647286 --- /dev/null +++ b/nth_tribonacci_number.py @@ -0,0 +1,29 @@ +# 1137. N-th Tribonacci Number + +""" +the tribonacci sequence t^n is defined as follows +t0 = 0, t1 = 1, t2 = 1, & tn+3 = tn + tn+1 + tn+2 for n >= 0 +given n, return value of tn +eg. +n = 4, output: 4 +t3 = 0 + 1 + 1 = 2 +t4 = 1 + 1 + 2 = 4 +""" + + +class Solution(object): + def tribonacci(self, n): + """ + :type n: int + :rtype: int + """ + a, b, c = 1, 0, 0 + for _ in range(n): + a, b, c = b, c, a + b + c + return c + + +if __name__ == "__main__": + obj = Solution() + print(obj.tribonacci(4)) + print(obj.tribonacci(25)) diff --git a/num_bad_pairs.cpp b/num_bad_pairs.cpp new file mode 100644 index 0000000..75ea430 --- /dev/null +++ b/num_bad_pairs.cpp @@ -0,0 +1,27 @@ +#include "leetcode.h" + +/* + * given: 0-indexed integer array + * bad pair: (i, j) if + * i < j && j - i != nums[j] - nums[i] + */ + +class Solution { +public: + long long countBadPairs(vector<int> &nums) { + long long ans = 0; + unordered_map<int, int> um; + for (int i = 0; i < nums.size(); ++i) { + ans += (long long)i - um[nums[i] - i]; + ++um[nums[i] - i]; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums1 = {4, 1, 3, 3}, nums2 = {1, 2, 3, 4, 5}; + cout << obj.countBadPairs(nums1) << endl; // expect: 5 + cout << obj.countBadPairs(nums2) << endl; // expect: 0 +} diff --git a/num_bad_pairs.rs b/num_bad_pairs.rs new file mode 100644 index 0000000..8e1e7dd --- /dev/null +++ b/num_bad_pairs.rs @@ -0,0 +1,29 @@ +use std::collections::HashMap; +struct Solution; + +/* + * given: 0-indexed integer array + * bad pair: (i, j) if + * i < j && j - i != nums[j] - nums[i] + */ + +impl Solution { + pub fn count_bad_pairs(nums: Vec<i32>) -> i64 { + let mut hm: HashMap<i32, i32> = HashMap::with_capacity(nums.len()); + let mut ans = 0; + nums.iter().zip(0..).for_each(|(&x, i)| { + let delta = x - i; + let e = hm.entry(delta).or_default(); + ans += (i - *e) as i64; + *e += 1; + }); + ans + } +} + +fn main() { + let nums1 = vec![4,1,3,3]; + let nums2 = vec![1,2,3,4,5]; + println!("{}", Solution::count_bad_pairs(nums1)); //expect: 5 + println!("{}", Solution::count_bad_pairs(nums2)); //expect: 0 +} diff --git a/num_beautiful_subset.c b/num_beautiful_subset.c new file mode 100644 index 0000000..f61a6b5 --- /dev/null +++ b/num_beautiful_subset.c @@ -0,0 +1,36 @@ +// 2597. The Number of Beautiful Subsets +#include "leetcode.h" + +/* + * given an array 'nums' of positive integers and a positive integer 'k'. a + * subset of 'nums' is beautiful if it does not contain integers with an + * absolute difference equal to 'k'. return the number of non empty beautiful + * subsets of the array 'nums'. a subset of 'nums' is an array that can be + * obtained by deleting some elements from 'nums'. two subsets are different iff + * the chosen indices to delete are different. + */ + +int beautifulSubsets(int *nums, int numsSize, int k) { + int n = 1 << numsSize, cnt = 0; + for (int i = 1; i < n; i++) { + int *store = (int *)malloc(numsSize * sizeof(int)); + bool flag = true; + for (int j = 0, l = 0; j < numsSize && flag; j++) + if (i & (1 << j)) { + for (int m = 0; m < l && flag; m++) + if (abs(store[m] - nums[j]) == k) + flag = false; + store[l++] = nums[j]; + } + if (flag) + cnt++; + free(store); + } + return cnt; +} + +int main() { + int n1[] = {2, 4, 6}, n2[] = {1}; + printf("%d\n", beautifulSubsets(n1, ARRAY_SIZE(n1), 2)); // expect: 4 + printf("%d\n", beautifulSubsets(n2, ARRAY_SIZE(n2), 1)); // expect: 1 +} diff --git a/num_beautiful_subset.py b/num_beautiful_subset.py new file mode 100644 index 0000000..7b1a9a0 --- /dev/null +++ b/num_beautiful_subset.py @@ -0,0 +1,40 @@ +# 2597. The Number of Beautiful Subsets +import collections + +""" +given an array 'nums' of positive integers and a positive integer 'k'. a +subset of 'nums' is beautiful if it does not contain integers with an +absolute difference equal to 'k'. return the number of non empty beautiful +subsets of the array 'nums'. a subset of 'nums' is an array that can be +obtained by deleting some elements from 'nums'. two subsets are different iff +the chosen indices to delete are different. +""" + + +class Solution(object): + def beautifulSubsets(self, nums, k): + """ + :type nums: List[int] + :type k: int + :rtype: int + """ + ans = 1 + freq = collections.defaultdict(collections.Counter) + for i in nums: + freq[i % k][i] += 1 + for i in freq.values(): + prev_num, curr, prev1, prev2 = -k, 1, 1, 0 + for n in sorted(i): + skip = prev1 + take = (2 ** i[n] - 1) * (prev2 if n - prev_num == k else prev1) + curr = skip + take + prev2, prev1 = prev1, curr + prev_num = n + ans *= curr + return ans - 1 + + +if __name__ == "__main__": + obj = Solution() + print(obj.beautifulSubsets(nums=[2, 4, 6], k=2)) + print(obj.beautifulSubsets(nums=[1], k=1)) diff --git a/num_closed_islands.c b/num_closed_islands.c new file mode 100644 index 0000000..3f84ee3 --- /dev/null +++ b/num_closed_islands.c @@ -0,0 +1,49 @@ +// 1254. Number of Closed Islands +#include <stdbool.h> +#include <stdio.h> + +/* + * given 2d 'grid' consists of 0's (land) and 1's (water). an island is a + * maximal four directionally connected group of 0's and a closed island is an + * island totally (all left, top, right, bottom) surrouned by 1's. return the + * number of closed islands. + */ + +bool dfs(int **grid, int i, int j, int row, int col) { + if (i < 0 || i >= row || j < 0 || j >= col) + return false; + if (grid[i][j]) + return true; + grid[i][j] = 1; + bool up = dfs(grid, i - 1, j, row, col); + bool down = dfs(grid, i + 1, j, row, col); + bool left = dfs(grid, i, j - 1, row, col); + bool right = dfs(grid, i, j + 1, row, col); + return up && down && left && right; +} + +int closedIslands(int **grid, int grid_size, int *grid_col_size) { + int row = grid_size, col = grid_col_size[0], ans = 0; + for (int i = 0; i < row; i++) + for (int j = 0; j < col; j++) + if (!grid[i][j] && dfs(grid, i, j, row, col)) + ans++; + return ans; +} + +int main() { + int g1[4][8] = {{1, 1, 1, 1, 1, 1, 1, 0}, + {1, 0, 0, 0, 0, 1, 1, 0}, + {1, 0, 0, 0, 0, 1, 0, 1}, + {1, 1, 1, 1, 1, 1, 1, 0}}, + gcs1[] = {8, 8, 8, 8}, gs1 = 4; + int g2[2][5] = {{0, 0, 1, 0, 0}, {0, 1, 0, 1, 0}}, gcs2[] = {5, 5}, gs2 = 2; + int g3[7][7] = {{1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 1}, + {1, 0, 1, 1, 1, 0, 1}, {1, 0, 1, 0, 1, 0, 1}, + {1, 0, 1, 1, 1, 0, 1}, {1, 0, 0, 0, 0, 0, 1}, + {1, 1, 1, 1, 1, 1, 1}}, + gcs3[] = {7, 7, 7, 7, 7, 7, 7}, gs3 = 7; + printf("%d\n", closedIslands(g1, gs1, gcs1)); // expect: 2 + printf("%d\n", closedIslands(g2, gs2, gcs2)); // expect: 1 + printf("%d\n", closedIslands(g3, gs3, gcs3)); // expect: 2 +} diff --git a/num_closed_islands.cpp b/num_closed_islands.cpp new file mode 100644 index 0000000..b6a4a9e --- /dev/null +++ b/num_closed_islands.cpp @@ -0,0 +1,61 @@ +// 1254. Number of Closed Islands +#include "leetcode.h" + +/* + * given 2d 'grid' consists of 0's (land) and 1's (water). an island is a + * maximal four directionally connected group of 0's and a closed island is an + * island totally (all left, top, right, bottom) surrouned by 1's. return the + * number of closed islands. + */ + +class Solution { + int dx[4] = {0, 0, -1, 1}, dy[4] = {1, -1, 0, 0}; + bool is_valid(vvd(int) & grid, int i, int j, int r, int c) { + if (i >= 0 && i < r && j >= 0 && j < c && grid[i][j] == 0) + return true; + else + return false; + } + void dfs(vvd(int) & grid, int i, int j, int r, int c) { + grid[i][j] = 1; + for (int x = 0; x < 4; ++x) { + int new_x = i + dx[x]; + int new_y = i + dy[x]; + if (is_valid(grid, new_x, new_y, r, c)) + dfs(grid, new_x, new_y, r, c); + } + } + +public: + int closedIsland(vvd(int) & grid) { + int r = grid.size(), c = grid[0].size(), ans = 0; + for (int i = 0; i < r; ++i) + for (int j = 0; j < c; ++j) + if (i * j == 0 || i == r - 1 || j == c - 1) + if (grid[i][j] == 0) + dfs(grid, i, j, r, c); + for (int i = 0; i < r; ++i) + for (int j = 0; j < c; ++j) + if (grid[i][j] == 0) { + ans++; + dfs(grid, i, j, r, c); + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) g1 = {{1, 1, 1, 1, 1, 1, 1, 0}, + {1, 0, 0, 0, 0, 1, 1, 0}, + {1, 0, 0, 0, 0, 1, 0, 1}, + {1, 1, 1, 1, 1, 1, 1, 0}}; + vvd(int) g2 = {{0, 0, 1, 0, 0}, {0, 1, 0, 1, 0}}; + vvd(int) + g3 = {{1, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 1}, {1, 0, 1, 1, 1, 0, 1}, + {1, 0, 1, 0, 1, 0, 1}, {1, 0, 1, 1, 1, 0, 1}, {1, 0, 0, 0, 0, 0, 1}, + {1, 1, 1, 1, 1, 1, 1}}; + printf("%d\n", obj.closedIsland(g1)); // expect: 2 + printf("%d\n", obj.closedIsland(g2)); // expect: 1 + printf("%d\n", obj.closedIsland(g3)); // expect: 2 +} diff --git a/num_cut_pizza.c b/num_cut_pizza.c new file mode 100644 index 0000000..1a3bfd6 --- /dev/null +++ b/num_cut_pizza.c @@ -0,0 +1,21 @@ +// 1444. Number of Ways of Cutting a Pizza +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given rectangular pizza represented as a rows x cols matrix containing the + * following characters 'A' an apple and '.' empty cell, and given integer 'k'. + * you have to cut the pizza into 'k' pieces using 'k - 1' cuts. + */ + +int ways(char **pizza, int pizza_size, int k) {} + +int main() { + char p1[][3] = {{"A.."}, {"AAA"}, {"..."}}; + char p2[][3] = {{"A.."}, {"AA."}, {"..."}}; + char p3[][3] = {{"A.."}, {"A.."}, {"..."}}; + printf("%d\n", ways(p1, 3, 3)); // expect: 3 + printf("%d\n", ways(p2, 3, 3)); // expect: 1 + printf("%d\n", ways(p3, 3, 1)); // expect: 1 +} diff --git a/num_cut_pizza.cpp b/num_cut_pizza.cpp new file mode 100644 index 0000000..4f3afd7 --- /dev/null +++ b/num_cut_pizza.cpp @@ -0,0 +1,58 @@ +// 1444. Number of Ways of Cutting a Pizza +#include "leetcode.h" + +/* + * given rectangular pizza represented as a rows x cols matrix containing the + * following characters 'A' an apple and '.' empty cell, and given integer 'k'. + * you have to cut the pizza into 'k' pieces using 'k - 1' cuts. + */ + +class Solution { + void add(long &a, long &b) { a = (a + b) % ((int)1e9 + 7); } + +public: + int ways(vector<string> &pizza, int k) { + int m = pizza.size(), n = pizza[0].size(); + vvd(int) cnt(m + 1, vector<int>(n + 1)); + for (int i = m - 1; i >= 0; --i) { + int s = 0; + for (int j = n - 1; j >= 0; --j) { + s += pizza[i][j] == 'A'; + cnt[i][j] = cnt[i + 1][j] + s; + } + } + vvd(vector<long>) dp(m + 1, vvd(long)(n + 1, vector<long>(k + 1))); + for (int i = m - 1; i >= 0; --i) { + for (int j = n - 1; j >= 0; --j) { + dp[i][j][1] = cnt[i][j] > 0; + for (int p = 2; p <= k; ++p) { + for (int q = i + 1; q < m; ++q) { + if (cnt[i][j] == cnt[q][j]) + continue; + if (cnt[q][j] == 0) + break; + add(dp[i][j][p], dp[q][j][p - 1]); + } + for (int q = j + 1; q < n; ++q) { + if (cnt[i][j] == cnt[i][q]) + continue; + if (cnt[i][q] == 0) + break; + add(dp[i][j][p], dp[i][q][p - 1]); + } + } + } + } + return dp[0][0][k]; + } +}; + +int main() { + Solution obj; + vector<string> p1 = {"A..", "AAA", "..."}; + vector<string> p2 = {"A..", "AA.", "..."}; + vector<string> p3 = {"A..", "A..", "..."}; + printf("%d\n", obj.ways(p1, 3)); // expect: 3 + printf("%d\n", obj.ways(p2, 3)); // expect: 1 + printf("%d\n", obj.ways(p3, 1)); // expect: 1 +} diff --git a/num_dice_roll_target_sum.c b/num_dice_roll_target_sum.c new file mode 100644 index 0000000..df19cbf --- /dev/null +++ b/num_dice_roll_target_sum.c @@ -0,0 +1,40 @@ +// 1155. Number of Dice Rolls With Target Sum +#include "leetcode.h" + +/* + * you have 'n' dice and die has 'k' faces numbered 1 to 'k'. given three + * integers 'n', 'k', and 'target', return the number of possible ways to roll + * the dice so the sum of the face up numbers equals 'target'. since the answer + * may be too large, return it modulo 10e9+7 + */ + +int numRollsToTarget(int n, int k, int target) { + int mod = 1e9 + 7; + int **dp = malloc((n + 1) * sizeof(int *)); + for (int i = 0; i <= n; i++) + dp[i] = calloc(target + 1, sizeof(int)); + for (int i = 1; i <= target; i++) { + if (i > k) + break; + dp[1][i] = 1; + } + for (int i = 2; i <= n; i++) + for (int j = i; j <= target; j++) { + if (j > i * k) + break; + int sum = 0; + for (int m = 1; m <= k; m++) { + if (j - m < 0) + break; + sum = (sum + dp[i - 1][j - m] % mod); + } + dp[i][j] = sum; + } + return dp[n][target]; +} + +int main() { + printf("%d\n", numRollsToTarget(1, 6, 3)); // expect: 1 + printf("%d\n", numRollsToTarget(2, 6, 7)); // expect: 6 + printf("%d\n", numRollsToTarget(30, 30, 500)); // expect: 222616187 +} diff --git a/num_dice_roll_target_sum.cpp b/num_dice_roll_target_sum.cpp new file mode 100644 index 0000000..3fd3672 --- /dev/null +++ b/num_dice_roll_target_sum.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + int numRollsToTarget(int n, int k, int target) { + int mod = 1000000007; + vvd(int) dp(n + 1, vector<int>(target + 1, 0)); + dp[0][0] = 1; + for (int i = 1; i <= n; i++) + for (int j = 1; j <= target; j++) + for (int x = 1; x <= k; x++) + if (x <= j) + dp[i][j] = ((dp[i][j] % mod) + (dp[i - 1][j - x] % mod)) % mod; + return dp[n][target]; + } +}; + +int main() { + Solution obj; + cout << obj.numRollsToTarget(1, 6, 3); +} diff --git a/num_dice_roll_target_sum.py b/num_dice_roll_target_sum.py new file mode 100644 index 0000000..42bf247 --- /dev/null +++ b/num_dice_roll_target_sum.py @@ -0,0 +1,37 @@ +# 1155. Number of Dice Rolls With Target Sum + +""" +you have 'n' dice and die has 'k' faces numbered 1 to 'k'. given three +integers 'n', 'k', and 'target', return the number of possible ways to roll +the dice so the sum of the face up numbers equals 'target'. since the answer +may be too large, return it modulo 10e9+7 +""" + + +class Solution(object): + def numRollsToTarget(self, n, k, target): + """ + :type n: int + :type k: int + :type target: int + :rtype: int + """ + mod = 10**9 + 7 + prev = [0] * (target + 1) + curr = [0] * (target + 1) + for i in range(1, n + 1): + for j in range(1, target + 1): + ans = 0 + for x in range(1, k + 1): + if j - x >= 0: + ans += prev[j - x] % mod + curr[j] = ans + prev = curr[:] + return int(prev[target] % mod) + + +if __name__ == "__main__": + obj = Solution() + print(obj.numRollsToTarget(1, 6, 3)) + print(obj.numRollsToTarget(2, 6, 7)) + print(obj.numRollsToTarget(30, 30, 500)) diff --git a/num_digit_one.c b/num_digit_one.c new file mode 100644 index 0000000..f2888cd --- /dev/null +++ b/num_digit_one.c @@ -0,0 +1,34 @@ +// 233. Number of Digit One +#include "leetcode.h" + +/* + * given an integer 'n', count the total number of digit 1 appearing in all + * non-negative integers less than or equal to n + */ + +int countDigitOne(int n) { + if (n <= 0) + return 0; + if (n < 10) + return 1; + long ctx = 10, ctx_cnt = 1; + while (n >= ctx * 10) { + ctx_cnt *= 10 + ctx; + ctx *= 10; + } + int ans = ctx_cnt; + if (n >= 2 * ctx) { + ans += ans * 2 + ans * (n / ctx - 2) + ctx - ans; + int low_n = countDigitOne(n % ctx); + ans += low_n; + } else { + int low_n = countDigitOne(n - ctx); + ans += low_n * 2 + (n - (ctx - 1)) - low_n; + } + return ans; +} + +int main() { + printf("%d\n", countDigitOne(13)); // expect: 6 + printf("%d\n", countDigitOne(0)); // expect: 0 +} diff --git a/num_digit_one.py b/num_digit_one.py new file mode 100644 index 0000000..f73670e --- /dev/null +++ b/num_digit_one.py @@ -0,0 +1,27 @@ +# 233. Number of Digit One + +""" +given an integer 'n', count the total number of digit 1 appearing in all +non-negative integers less than or equal to n +""" + + +class Solution(object): + def countDigitOne(self, n): + """ + :type n: int + :rtype: int + """ + ones, m, r = 0, 1, 1 + while n > 0: + ones += (n + 8) / 10 * m + (n % 10 == 1) * r + r += n % 10 * m + m *= 10 + n /= 10 + return ones + + +if __name__ == "__main__": + obj = Solution() + print(obj.countDigitOne(13)) # expect: 6 + print(obj.countDigitOne(0)) # expect: 0 diff --git a/num_enclaves.c b/num_enclaves.c new file mode 100644 index 0000000..662d9ab --- /dev/null +++ b/num_enclaves.c @@ -0,0 +1,65 @@ +// 1020. Number of Enclaves +#include <stdbool.h> +#include <stdio.h> + +/* + * given an 'm * n' binary matrix grid, where 0 represents a sea + * cell and 1 represents a land cell. a move consists of walking + * from one land cell to another adjacent (4-directionally) land + * cell o walking off the boundary of the 'grid'. return number + * of land cells in 'grid' for which we cannot walk off the + * boundary of the grid in any number of moves. + */ + +int u_find(int *u, int val) { + if (u[val] == val) + return val; + return u_find(u, u[val]); +} + +bool u_set(int *u, int a, int b) { + int find_a = u_find(u, a), find_b = u_find(u, b); + if (find_a == find_b) + return false; + u[find_a] = u[find_b]; + return true; +} + +void bfs(int **grid, int row, int col, int i, int j) { + if (i < 0 || i >= row || j < 0 || j >= col) + return; + if (!grid[i][j]) + return; + grid[i][j] = 0; + bfs(grid, row, col, i - 1, j); + bfs(grid, row, col, i + 1, j); + bfs(grid, row, col, i, j - 1); + bfs(grid, row, col, i, j + 1); +} + +int numEnclaves(int **grid, int grid_size, int *grid_col_size) { + int row = grid_size, col = *grid_col_size; + for (int i = 0; i < col; i++) + bfs(grid, row, col, 0, i); + for (int i = 0; i < col; i++) + bfs(grid, row, col, row - 1, i); + for (int i = 0; i < row; i++) + bfs(grid, row, col, i, 0); + for (int i = 0; i < row; i++) + bfs(grid, row, col, i, col - 1); + int ans = 0; + for (int i = 0; i < row; i++) + for (int j = 0; j < col; j++) + if (grid[i][j]) + ans++; + return ans; +} + +int main() { + int g1[4][4] = {{0, 0, 0, 0}, {1, 0, 1, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}}; + int g2[4][4] = {{0, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 0, 0}}; + int grid_size = 4; + int grid_col_size[] = {4, 4, 4, 4}; + printf("%d\n", numEnclaves(g1, grid_size, grid_col_size)); // expect: 3 + printf("%d\n", numEnclaves(g2, grid_size, grid_col_size)); // expect: 3 +} diff --git a/num_enclaves.cpp b/num_enclaves.cpp new file mode 100644 index 0000000..3c8062e --- /dev/null +++ b/num_enclaves.cpp @@ -0,0 +1,45 @@ +// 1020. Number of Enclaves +#include "leetcode.h" + +/* + * given an 'm * n' binary matrix grid, where 0 represents a sea + * cell and 1 represents a land cell. a move consists of walking + * from one land cell to another adjacent (4-directionally) land + * cell o walking off the boundary of the 'grid'. return number + * of land cells in 'grid' for which we cannot walk off the + * boundary of the grid in any number of moves. + */ + +class Solution { + int dfs(vvd(int) & grid, int i, int j) { + if (i < 0 || j < 0 || i >= grid.size() || j >= grid[0].size() || + grid[i][j] == 0) + return 0; + grid[i][j] = 0; + return 1 + dfs(grid, i - 1, j) + dfs(grid, i + 1, j) + dfs(grid, i, j - 1) + + dfs(grid, i, j + 1); + } + +public: + int numEnclaves(vvd(int) & grid) { + int ones = 0, zeros = 0; + for (int i = 0; i < grid.size(); i++) + for (int j = 0; j < grid[0].size(); j++) + ones += grid[i][j]; + for (int i = 0; i < grid.size(); i++) + for (int j = 0; j < grid[0].size(); j++) + if ((i == 0 || j == 0 || i == grid.size() - 1 || + j == grid[0].size() - 1) && + grid[i][j] == 1) + zeros += dfs(grid, i, j); + return ones - zeros; + } +}; + +int main() { + Solution obj; + vvd(int) g1 = {{0, 0, 0, 0}, {1, 0, 1, 0}, {0, 1, 1, 0}, {0, 0, 0, 0}}; + vvd(int) g2 = {{0, 1, 1, 0}, {0, 0, 1, 0}, {0, 0, 1, 0}, {0, 0, 0, 0}}; + printf("%d\n", obj.numEnclaves(g1)); // expect: 3 + printf("%d\n", obj.numEnclaves(g2)); // expect: 0 +} diff --git a/num_even_nums.cpp b/num_even_nums.cpp new file mode 100644 index 0000000..5d5c240 --- /dev/null +++ b/num_even_nums.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +/* + * given array 'nums' of integers, return how + * many of them contain an even number of digits. + */ + +class Solution { +public: + int findNumbers(vector<int> &nums) { + int ans = 0; + // use auto to identify data type & iterate through array + for (auto i : nums) + /* + * log10 returns a decimal so convert it to int + * it also returns n - 1. eg. log10(100) = 2 + * use bitwise and to check if it's odd + */ + ans += (int)log10(i) & 1; + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums1 = {12, 345, 2, 6, 7896}, nums2 = {555, 901, 482, 1771}; + cout << obj.findNumbers(nums1) << endl; // expect: 2 + cout << obj.findNumbers(nums2) << endl; // expect: 1 +} diff --git a/num_flower_bloom.c b/num_flower_bloom.c new file mode 100644 index 0000000..16fc756 --- /dev/null +++ b/num_flower_bloom.c @@ -0,0 +1,55 @@ +// 2251. Number of Flowers in Full Bloom +#include <limits.h> +#include <stdlib.h> + +/* + * given a 0-indexed 2d integer array 'flowers', where 'flowers[i] = [start[i], + * end[i]]' means the i'th flower will be in full bloom from 'start[i]' to + * 'end[i]' (inclusive). you are also given a 0-indexed integer array 'people' + * of size 'n' where 'people[i]' is the time that the i'th person will arrive to + * see the flowers. return an integer array 'answer' of size 'n' where + * 'answer[i]' is the number of flowers that are in full bloom when the i'th + * person arrives. + */ + +struct pp { + int person; + int rank; +}; + +int cmp(const void *a, const void *b) { + return (*(struct pp *)a).person > (*(struct pp *)b).person ? 1 : -1; +} + +int *fullBloomFlowers(int **flowers, int flowers_size, int *flowers_col_size, + int *people, int people_size, int *return_size) { + *return_size = people_size; + int *ans = calloc(people_size, sizeof(int)), cnt = 0; + struct pp *list = malloc(sizeof(struct pp) * (people_size)); + struct pp *tree = malloc(sizeof(struct pp) * (flowers_size * 2 + 1)); + for (int i = 0; i < flowers_size; i++) { + tree[cnt].person = flowers[i][0]; + tree[cnt].rank = 1; + cnt++; + tree[cnt].person = flowers[i][1] + 1; + tree[cnt].rank = -1; + cnt++; + } + for (int i = 0; i < people_size; i++) { + list[i].person = people[i]; + list[i].rank = i; + } + qsort(tree, flowers_size * 2, sizeof(struct pp), cmp); + qsort(list, people_size, sizeof(struct pp), cmp); + tree[cnt].person = INT_MAX; + int now = 0, flower = 0; + for (int i = 0; i < people_size; i++) { + while (list[i].person >= tree[now].person) { + flower += tree[now].rank; + now++; + } + ans[list[i].rank] = flower; + } + free(list), free(tree); + return ans; +} diff --git a/num_flower_bloom.py b/num_flower_bloom.py new file mode 100644 index 0000000..9bbbe05 --- /dev/null +++ b/num_flower_bloom.py @@ -0,0 +1,21 @@ +# 2251. Number of Flowers in Full Bloom + +""" +given a 0-indexed 2d integer array 'flowers', where 'flowers[i] = [start[i], +end[i]]' means the i'th flower will be in full bloom from 'start[i]' to +'end[i]' (inclusive). you are also given a 0-indexed integer array 'people' +of size 'n' where 'people[i]' is the time that the i'th person will arrive to +see the flowers. return an integer array 'answer' of size 'n' where +'answer[i]' is the number of flowers that are in full bloom when the i'th +person arrives. +""" + + +class Solution(object): + def fullBloomFlowers(self, flowers, people): + diff = sortedcontainers.SortedDict({0: 0}) + for i, j in flowers: + diff[i] = diff.get(i, 0) + 1 + diff[j + 1] = diff.get(j + 1, 0) - 1 + cnt = list(accumulate(diff.values())) + return [cnt[diff.bisect(t) - 1] for t in persons] diff --git a/num_good_pair.c b/num_good_pair.c new file mode 100644 index 0000000..ceeac28 --- /dev/null +++ b/num_good_pair.c @@ -0,0 +1,31 @@ +// 1512. Number of Good Pairs +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array of integers 'nums', return the number of good pairs. a pair + * '(i, j)' is called good if 'nums[i] == nums[j]' and 'i < j' + */ + +int numIdenticalPairs(int *nums, int nums_size) { + int max = nums[0]; + for (int i = 0; i < nums_size; i++) + max = nums[i] > max ? nums[i] : max; + max++; + int *arr = (int *)calloc(max, sizeof(int)); + for (int i = 0; i < nums_size; i++) + arr[nums[i]]++; + int ans = 0; + for (int i = 0; i < max; i++) + if (arr[i] > 1) + ans += (arr[i] * (arr[i] - 1) / 2); + free(arr); + return ans; +} + +int main() { + int n1[] = {1, 2, 3, 1, 1, 3}, n2[] = {1, 1, 1, 1}, n3[] = {1, 2, 3}; + printf("%d\n", numIdenticalPairs(n1, 6)); // expect: 4 + printf("%d\n", numIdenticalPairs(n2, 4)); // expect: 6 + printf("%d\n", numIdenticalPairs(n3, 3)); // expect: 0 +} diff --git a/num_good_pair.py b/num_good_pair.py new file mode 100644 index 0000000..ea05f1b --- /dev/null +++ b/num_good_pair.py @@ -0,0 +1,22 @@ +# 1512. Number of Good Pairs + +""" +given an array of integers 'nums', return the number of good pairs. a pair +'(i, j)' is called good if 'nums[i] == nums[j]' and 'i < j' +""" + +class Solution(object): + def numIdenticalPairs(self, nums): + cnt = 0 + for i in range(len(nums)): + for j in range(i + 1, len(nums)): + if nums[i] == nums[j]: + cnt += 1 + return cnt + + +if __name__ == "__main__": + obj = Solution() + print(obj.numIdenticalPairs([1,2,3,1,1,3])) # expect: 4 + print(obj.numIdenticalPairs([1,1,1,1])) # expect: 6 + print(obj.numIdenticalPairs([1,2,3])) # expect: 0 diff --git a/num_good_path.c b/num_good_path.c new file mode 100644 index 0000000..57972fb --- /dev/null +++ b/num_good_path.c @@ -0,0 +1,84 @@ +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +int cmp(const void *a, const void *b) { + return (*(int **)a)[0] - (*(int **)b)[0]; +} + +int cmp1d(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int ufFind(int *class, int num) { + int res = num; + while (class[res] != res) + res = class[res]; + class[num] = res; + return res; +} + +void ufUnion(int *class, int a, int b) { + int numA = ufFind(class, a); + int numB = ufFind(class, b); + if (numA == numB) + return; + if (numA < numB) { + class[numB] = numA; + class[b] = numA; + } else { + class[numA] = numB; + class[a] = numB; + } +} + +int numberOfGoodPaths(int *vals, int valsSize, int **edges, int edgesSize, + int *edgesColSize) { + int ans = 0; + int **qData = malloc(valsSize * sizeof(int *)); + int *class = malloc(valsSize * sizeof(int)); + int *tmp = malloc(valsSize * sizeof(int)); + int **qEdges = malloc(edgesSize * sizeof(int *)); + for (int i = 0; i < valsSize; i++) { + qData[i] = malloc(2 * sizeof(int)); + class[i] = i; + qData[i][0] = vals[i]; + qData[i][1] = i; + } + for (int i = 0; i < edgesSize; i++) { + qEdges[i] = malloc(3 * sizeof(int)); + qEdges[i][0] = (vals[edges[i][0]] > vals[edges[i][1]]) ? vals[edges[i][0]] + : vals[edges[i][1]]; + qEdges[i][1] = edges[i][0]; + qEdges[i][2] = edges[i][1]; + } + qsort(qData, valsSize, sizeof(qData[0]), cmp); + qsort(qEdges, edgesSize, sizeof(qEdges[0]), cmp); + int edgesIdx = 0, left = 0, right = 0; + while (right < valsSize) { + while (edgesIdx < edgesSize && qEdges[edgesIdx][0] <= qData[right][0]) { + ufUnion(class, qEdges[edgesIdx][1], qEdges[edgesIdx][2]); + edgesIdx++; + } + left = right; + int tmpIdx = 0, cnt = 0; + while (right < valsSize && qData[left][0] == qData[right][0]) { + tmp[tmpIdx++] = class[qData[right][1]]; + right++; + } + qsort(tmp, tmpIdx, sizeof(tmp[0]), cmp1d); + for (int i = 0; i < tmpIdx; i++) { + if (tmp[i] == tmp[i - 1]) + cnt++; + else + cnt = 0; + ans += cnt; + } + } + return ans + valsSize; +} + +int main() { + int vals1[] = {1, 3, 2, 1, 3}, vals2[] = {1, 1, 2, 2, 3}, vals3[] = {1}; + int valsSize1 = 5, valsSize2 = 5, valsSize3 = 1; + int edges1[4][2] = {{0, 1}, {0, 2}, {2, 3}, {2, 4}}, + edges2[4][2] = {{0, 1}, {1, 2}, {2, 3}, {2, 4}}, edges3[0][0] = {}; +} diff --git a/num_good_path.cpp b/num_good_path.cpp new file mode 100644 index 0000000..45257a7 --- /dev/null +++ b/num_good_path.cpp @@ -0,0 +1,75 @@ +#include "leetcode.h" + +class UnionFind { +private: + vector<int> id, rank; + int cnt; + +public: + UnionFind(int cnt) : cnt(cnt) { + id = vector<int>(cnt); + rank = vector<int>(cnt, 0); + for (int i = 0; i < cnt; ++i) + id[i] = i; + } + int find(int p) { + if (id[p] == p) + return p; + return id[p] = find(id[p]); + } + bool connected(int p, int q) { return find(p) == find(q); } + void connect(int p, int q) { + int i = find(p), j = find(q); + if (i == j) + return; + if (rank[i] < rank[j]) + id[i] = j; + else { + id[j] = i; + if (rank[i] == rank[j]) + rank[j]++; + } + --cnt; + } +}; + +class Solution { +public: + int numberOfGoodPaths(vector<int> &vals, vvd(int) & edges) { + int n = vals.size(), goodPaths = 0; + vvd(int) adj(n); + map<int, vector<int>> sameVal; + for (int i = 0; i < n; i++) + sameVal[vals[i]].push_back(i); + for (auto &e : edges) { + int u = e[0], v = e[1]; + if (vals[u] >= vals[v]) + adj[u].push_back(v); + else if (vals[v] >= vals[u]) + adj[v].push_back(u); + } + UnionFind uf(n); + for (auto &[value, allNodes] : sameVal) { + for (int u : allNodes) + for (int v : adj[u]) + uf.connect(u, v); + unordered_map<int, int> group; + for (int u : allNodes) + group[uf.find(u)]++; + goodPaths += allNodes.size(); + for (auto &[_, size] : group) + goodPaths += (size * (size - 1) / 2); + } + return goodPaths; + } +}; + +int main() { + Solution obj; + vector<int> vals1 = {1, 3, 2, 1, 3}, vals2 = {1, 1, 2, 2, 3}, vals3 = {1}; + vvd(int) edges1 = {{0, 1}, {0, 2}, {2, 3}, {2, 4}}, + edges2 = {{0, 1}, {1, 2}, {2, 3}, {2, 4}}, edges3 = {}; + cout << obj.numberOfGoodPaths(vals1, edges1) << endl; // expect: 6 + cout << obj.numberOfGoodPaths(vals2, edges2) << endl; // expect: 7 + cout << obj.numberOfGoodPaths(vals3, edges3) << endl; // expect: 1 +} diff --git a/num_increasing_path.c b/num_increasing_path.c new file mode 100644 index 0000000..7cac3e9 --- /dev/null +++ b/num_increasing_path.c @@ -0,0 +1,49 @@ +// 2328. Number of Increasing Paths in a Grid +#include <stdio.h> +#include <stdlib.h> + +/* + * given an 'm x n' integer matrix 'grid' where you can move from a cell to any + * adjacent cell in all 4 directions. return th number of strictly increasing + * paths in the grid such that you can start from any cell and end at any cell. + * since the answer may be very large, return it modulo 10^9+7. two paths are + * considered different if they do not have exactly the same sequence of visited + * cells. + */ + +const int MOD = 1e9 + 7; +int dfs(int **grid, int grid_size, int *grid_col_size, int row, int col, + int prev, int *ans, int **seen) { + if (row < 0 || row >= grid_size || col < 0 || col >= *grid_col_size || + grid[row][col] <= prev) + return 0; + + if (seen[row][col]) + return seen[row][col]; + int tmp = 1; + tmp += dfs(grid, grid_size, grid_col_size, row + 1, col, grid[row][col], ans, + seen); + tmp += dfs(grid, grid_size, grid_col_size, row - 1, col, grid[row][col], ans, + seen); + tmp += dfs(grid, grid_size, grid_col_size, row, col + 1, grid[row][col], ans, + seen); + tmp += dfs(grid, grid_size, grid_col_size, row, col - 1, grid[row][col], ans, + seen); + tmp %= MOD; + seen[row][col] = tmp; + return seen[row][col]; +} +int countPaths(int **grid, int grid_size, int *grid_col_size) { + int **seen = (int **)malloc(sizeof(int *) * grid_size), ans = 0; + for (int i = 0; i < grid_size; i++) + seen[i] = calloc(*grid_col_size, sizeof(int)); + for (int i = 0; i < grid_size; i++) + for (int j = 0; j < *grid_col_size; j++) { + + if (seen[i][j] == 0) + seen[i][j] = dfs(grid, grid_size, grid_col_size, i, j, -1, &ans, seen); + + ans = (ans + seen[i][j]) % MOD; + } + return ans; +} diff --git a/num_increasing_path.cpp b/num_increasing_path.cpp new file mode 100644 index 0000000..4f60d46 --- /dev/null +++ b/num_increasing_path.cpp @@ -0,0 +1,54 @@ +// 2328. Number of Increasing Paths in a Grid +#include <stdio.h> +#include <vector> +using namespace std; + +/* + * given an 'm x n' integer matrix 'grid' where you can move from a cell to any + * adjacent cell in all 4 directions. return th number of strictly increasing + * paths in the grid such that you can start from any cell and end at any cell. + * since the answer may be very large, return it modulo 10^9+7. two paths are + * considered different if they do not have exactly the same sequence of visited + * cells. + */ + +class Solution { + int mod = 1e9 + 7; + int dfs(vector<vector<int>> &grid, int i, int j, vector<vector<int>> &dp, + int prev) { + if (i < 0 || j < 0 || i >= grid.size() || j >= grid[0].size() || + prev >= grid[i][j]) + return 0; + if (dp[i][j] != -1) + return dp[i][j]; + int top = dfs(grid, i - 1, j, dp, grid[i][j]); + int bottom = dfs(grid, i + 1, j, dp, grid[i][j]); + int right = dfs(grid, i, j + 1, dp, grid[i][j]); + int left = dfs(grid, i, j - 1, dp, grid[i][j]); + dp[i][j] = (1 + top + bottom + right + left) % mod; + return dp[i][j]; + } + +public: + int countPaths(vector<vector<int>> &grid) { + int m = grid.size(), n = grid[0].size(), ans = 0; + if (m == 1 && n == 1) + return 1; + vector<vector<int>> dp(m, vector<int>(n, -1)); + for (int i = 0; i < m; i++) + for (int j = 0; j < n; j++) { + if (dp[i][j] == -1) + ans = (ans + dfs(grid, i, j, dp, -1)) % mod; + else + ans = (ans + dp[i][j]) % mod; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<vector<int>> g1 = {{1, 1}, {3, 4}}, g2 = {{1}, {2}}; + printf("%d\n", obj.countPaths(g1)); // expect: 8 + printf("%d\n", obj.countPaths(g2)); // expect: 3 +} diff --git a/num_islands.c b/num_islands.c new file mode 100644 index 0000000..bbfa74c --- /dev/null +++ b/num_islands.c @@ -0,0 +1,35 @@ +// 200. Number of Islands +#include "leetcode.h" + +/* + * given an 'm * n' 2d binary grid 'grid' which represents a map of '1's (land) + * and '0's (water), return the number of islands present. an island + * issurrounded by water and is formed by connected adjacent lands horizontally + * or vertically. you may assume all four edges of the grid are all surrounded + * by water. + */ + +void visit(char **grid, int i, int j, int gridSize, int *gridColSize) { + if (i < 0 || j < 0 || i >= gridSize) + return; + if (j >= gridColSize[i]) + return; + if (grid[i][j] == '0') + return; + grid[i][j] = '0'; + visit(grid, i - 1, j, gridSize, gridColSize); + visit(grid, i + 1, j, gridSize, gridColSize); + visit(grid, i, j - 1, gridSize, gridColSize); + visit(grid, i, j + 1, gridSize, gridColSize); +} + +int numIslands(char **grid, int gridSize, int *gridColSize) { + int ans = 0; + for (int i = 0; i < gridSize; i++) + for (int j = 0; j < gridColSize[i]; j++) + if (grid[i][j] == '1') { + visit(grid, i, j, gridSize, gridColSize); + ans++; + } + return ans; +} diff --git a/num_islands.py b/num_islands.py new file mode 100644 index 0000000..93c2cff --- /dev/null +++ b/num_islands.py @@ -0,0 +1,59 @@ +# 200. Number of Islands + +""" +given an 'm n' 2d binary grid 'grid' which represents a map of '1's (land) +and '0's (water), return the number of islands present. an island +issurrounded by water and is formed by connected adjacent lands horizontally +or vertically. you may assume all four edges of the grid are all surrounded +by water. +""" + + +class Solution(object): + def numIslands(self, grid): + """ + :type grid: List[List[str]] + :rtype: int + """ + if not grid: + return 0 + ans = 0 + for i in range(len(grid)): + for j in range(len(grid[0])): + if grid[i][j] == "1": + self.dfs(grid, i, j) + ans += 1 + return ans + + def dfs(self, grid, i, j): + if i < 0 or j < 0 or i >= len(grid) or j >= len(grid[0]) or grid[i][j] != "1": + return + grid[i][j] = "#" + self.dfs(grid, i + 1, j) + self.dfs(grid, i - 1, j) + self.dfs(grid, i, j + 1) + self.dfs(grid, i, j - 1) + + +if __name__ == "__main__": + obj = Solution() + print( + obj.numIslands( + grid=[ + ["1", "1", "1", "1", "0"], + ["1", "1", "0", "1", "0"], + ["1", "1", "0", "0", "0"], + ["0", "0", "0", "0", "0"], + ] + ) + ) + print( + obj.numIslands( + grid=[ + ["1", "1", "0", "0", "0"], + ["1", "1", "0", "0", "0"], + ["0", "0", "1", "0", "0"], + ["0", "0", "0", "1", "1"], + ] + ) + ) diff --git a/num_laser_beams_bank.c b/num_laser_beams_bank.c new file mode 100644 index 0000000..1b0b476 --- /dev/null +++ b/num_laser_beams_bank.c @@ -0,0 +1,40 @@ +// 2125. Number of Laser Beams in a Bank +#include "leetcode.h" + +/* + * anti-theft security devices are activated inside a bank. you are given a + * 0-indexed binary string array 'bank' representing the floor plan of the bank, + * which is an 'm x n' 2d matrix. 'bank[i]' represents the i'th row, consisting + * of '0's and '1's. '0' means the cell is empty, while '1' means the cell has a + * security device. there is one laser beam between any two security devices if + * both conditions are met. the two devices are located on two different rows + * 'r1' and 'r2', where 'r1 < r2'. for each row 'i' where 'r1 < i < r2' there + * are no security devices in the i'th row. laser beams are independent. return + * the total number of laser beams in the bank. + */ + +int numberOfBeams(char **bank, int bank_size) { + int ans = 0, start = 0; + for (int i = 0; i < bank_size; i++) { + int n = 0; + for (int j = 0;; j++) { + if (!bank[i][j]) + break; + else if (bank[i][j] == '1') + n++; + } + if (n) { + if (start) + ans += start * n; + start = n; + } + } + return ans; +} + +int main() { + char **b1 = {"011001", "000000", "010100", "001000"}; + char **b2 = {"000", "111", "000"}; + printf("%d\n", numberOfBeams(b1, 4)); // expect: 8 + printf("%d\n", numberOfBeams(b2, 3)); // expect: 0 +} diff --git a/num_laser_beams_bank.py b/num_laser_beams_bank.py new file mode 100644 index 0000000..b99d67c --- /dev/null +++ b/num_laser_beams_bank.py @@ -0,0 +1,38 @@ +# 2125. Number of Laser Beams in a Bank + +""" +anti-theft security devices are activated inside a bank. you are given a +0-indexed binary string array 'bank' representing the floor plan of the bank, +which is an 'm x n' 2d matrix. 'bank[i]' represents the i'th row, consisting +of '0's and '1's. '0' means the cell is empty, while '1' means the cell has a +security device. there is one laser beam between any two security devices if +both conditions are met. the two devices are located on two different rows +'r1' and 'r2', where 'r1 < r2'. for each row 'i' where 'r1 < i < r2' there +are no security devices in the i'th row. laser beams are independent. return +the total number of laser beams in the bank. +""" + + +class Solution(object): + def numberOfBeams(self, bank): + """ + :type bank: List[str] + :rtype: int + """ + pre, tot = 0, 0 + for row in bank: + curr = self.calc(row) + if curr == 0: + continue + tot += curr * pre + pre = curr + return tot + + def calc(self, s): + return sum(int(c) for c in s) + + +if __name__ == "__main__": + obj = Solution() + print(obj.numberOfBeams(bank=["011001", "000000", "010100", "001000"])) # expect: 8 + print(obj.numberOfBeams(bank=["000", "111", "000"])) # expect: 0 diff --git a/num_lines_write_string.c b/num_lines_write_string.c new file mode 100644 index 0000000..66ee622 --- /dev/null +++ b/num_lines_write_string.c @@ -0,0 +1,48 @@ +// 806. Number of Lines To Write String +#include "leetcode.h" + +/* + * given a string 's' of lowercase english letters and an array 'widths' + * denoting how many pixels wide each lowercase english letter is. specifically, + * 'widths[0]' is the width of 'a', 'widths[1]' is the width of 'b', and so on. + * you are trying to write 's' across several lines, where each line is no + * longer than 100 pixels. starting at the beginning of 's', write as many + * letters on the first line such that the total width does not exceed 100 + * pixels. then from where you topped in 's', continue writing as many letters + * as you can on the second line. continue this process until you have written + * all of 's'. + */ + +int *numberOfLines(int *widths, int widthsSize, char *s, int *returnSize) { + int *ans = malloc(2 * sizeof(int)); + *returnSize = 2; + int n = strlen(s), pixels = 0, line = 0; + for (int i = 0; i < n; i++) { + pixels += widths[s[i] - 'a']; + if (pixels > 100) { + line++; + pixels = widths[s[i] - 'a']; + } + } + ans[0] = line + 1; + ans[1] = pixels; + return ans; +} + +int main() { + int w1[] = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}, + w2[] = {4, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10}; + char *s1 = "abcdefghijklmnopqrstuvwxyz", *s2 = "bbbcccdddaaa"; + int rs1 = 0, rs2 = 0; + int *nol1 = numberOfLines(w1, ARRAY_SIZE(w1), s1, &rs1); + int *nol2 = numberOfLines(w2, ARRAY_SIZE(w2), s2, &rs2); + for (int i = 0; i < rs1; i++) + printf("%d ", nol1[i]); // expect: 3 60 + printf("\n"); + for (int i = 0; i < rs2; i++) + printf("%d ", nol2[i]); // expect: 2 4 + printf("\n"); + free(nol1), free(nol2); +} diff --git a/num_lines_write_string.py b/num_lines_write_string.py new file mode 100644 index 0000000..1197bd6 --- /dev/null +++ b/num_lines_write_string.py @@ -0,0 +1,98 @@ +# 806. Number of Lines To Write String + +""" +given a string 's' of lowercase english letters and an array 'widths' +denoting how many pixels wide each lowercase english letter is. specifically, +'widths[0]' is the width of 'a', 'widths[1]' is the width of 'b', and so on. +you are trying to write 's' across several lines, where each line is no +longer than 100 pixels. starting at the beginning of 's', write as many +letters on the first line such that the total width does not exceed 100 +pixels. then from where you topped in 's', continue writing as many letters +as you can on the second line. continue this process until you have written +all of 's'. +""" + + +class Solution(object): + def numberOfLines(self, widths, s): + """ + :type widths: List[int] + :type s: str + :rtype: List[int] + """ + ans, curr = 1, 0 + for i in s: + width = widths[ord(i) - ord("a")] + ans += 1 if curr + width > 100 else 0 + curr = width if curr + width > 100 else curr + width + return [ans, curr] + + +if __name__ == "__main__": + obj = Solution() + print( + obj.numberOfLines( + widths=[ + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + ], + s="abcdefghijklmnopqrstuvwxyz", + ) + ) + print( + obj.numberOfLines( + widths=[ + 4, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + 10, + ], + s="bbbcccdddaaa", + ) + ) diff --git a/num_longest_incr_subseq.c b/num_longest_incr_subseq.c new file mode 100644 index 0000000..4788418 --- /dev/null +++ b/num_longest_incr_subseq.c @@ -0,0 +1,40 @@ +// 673. Number of Longest Increasing Subsequence +#include <stdio.h> + +/* + * given an integer array 'nums', return the number of longest increasing + * subsequences. notice that the sequence has to strictly increasing. + */ + +int findNumberOfLIS(int *nums, int nums_size) { + if (!nums_size) + return 0; + int sec_len[nums_size], sec_num[nums_size]; + int max_len = 0, max_num = 0; + for (int i = 0; i < nums_size; ++i) { + int num = 1, len = 0; + for (int j = 0; j < i; ++j) { + if (nums[j] < nums[i]) { + if (len < sec_len[j]) { + len = sec_len[j]; + num = sec_len[j]; + } else if (len == sec_len[j]) + num += sec_num[j]; + } + } + sec_len[i] = ++len; + sec_num[i] = num; + if (len >= max_len) + max_len = len; + } + for (int i = 0; i < nums_size; ++i) + if (max_len == sec_len[i]) + max_num += sec_num[i]; + return max_num; +} + +int main() { + int n1[] = {1, 3, 5, 4, 7}, n2[] = {2, 2, 2, 2, 2}; + printf("%d\n", findNumberOfLIS(n1, 5)); // expect: 2 + printf("%d\n", findNumberOfLIS(n2, 5)); // expect: 5 +} diff --git a/num_longest_incr_subseq.cpp b/num_longest_incr_subseq.cpp new file mode 100644 index 0000000..bf6529b --- /dev/null +++ b/num_longest_incr_subseq.cpp @@ -0,0 +1,53 @@ +// 673. Number of Longest Increasing Subsequence +#include "leetcode.h" + +/* + * given an integer array 'nums', return the number of longest increasing + * subsequences. notice that the sequence has to strictly increasing. + */ + +class Solution { +public: + int findNumberOfLIS(vector<int> &nums) { + if (nums.empty()) + return 0; + vector<vector<pair<int, int>>> dyn(nums.size() + 1); + int curr_max = 0; + for (int i = 0; i < nums.size(); ++i) { + int l = 0, r = curr_max; + while (l < r) { + int mid = l + (r - l) / 2; + if (dyn[mid].back().first < nums[i]) + l = mid + 1; + else + r = mid; + } + int options = 1, row = l - 1; + if (row >= 0) { + int l1 = 0, r1 = dyn[row].size(); + while (l1 < r1) { + int mid = l1 + (r1 - l1) / 2; + if (dyn[row][mid].first < nums[i]) + r1 = mid; + else + l1 = mid + 1; + } + options = dyn[row].back().second; + options -= !l1 ? 0 : dyn[row][l1 - 1].second; + } + dyn[l].push_back( + {nums[i], + (dyn[l].empty() ? options : dyn[l].back().second + options)}); + if (l == curr_max) + curr_max++; + } + return dyn[curr_max - 1].back().second; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 3, 5, 4, 7}, n2 = {2, 2, 2, 2, 2}; + printf("%d\n", obj.findNumberOfLIS(n1)); // expect: 2 + printf("%d\n", obj.findNumberOfLIS(n2)); // expect: 5 +} diff --git a/num_matching_subsequence.cpp b/num_matching_subsequence.cpp new file mode 100644 index 0000000..a97d464 --- /dev/null +++ b/num_matching_subsequence.cpp @@ -0,0 +1,34 @@ +#include "leetcode.h" + +class Solution { +public: + int numMatchingSubseq(string s, vector<string> &words) { + int ans = 0; + unordered_map<string, int> up; + for (int i = 0; i < words.size(); i++) + up[words[i]]++; + for (auto it = up.begin(); it != up.end(); it++) + if (helper(s, it->first)) + ans += it->second; + return ans; + } + +private: + int helper(string a, string b) { + int i = 0, j = 0, m = a.size(), n = b.size(); + while (i < m && j < n) { + if (a[i] == b[j]) + i++, j++; + else + i++; + } + return (j == n); + } +}; + +int main() { + Solution obj; + string s = "abcde"; + vector<string> words = {"a", "bb", "acd", "ace"}; + cout << obj.numMatchingSubseq(s, words); +} diff --git a/num_music_playlists.c b/num_music_playlists.c new file mode 100644 index 0000000..c06ee28 --- /dev/null +++ b/num_music_playlists.c @@ -0,0 +1,39 @@ +// 920. Number of Music Playlists +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * your music player contains 'n' different songs. you want to listen to 'goal' + * songs (not necessarily different) during your trip. to avoid boredom, you + * will create a playlist so that: + * - every song is played at least once + * - a song can only be played again only if 'k' other songs have been played + * given 'n, goal, k', return the number of possible playlists that you can + * create. since the answer can be very large, return it modulo 10^9+7 + */ + +int numMusicPlaylists(int n, int goal, int k) { + const int mod = 1e9 + 7; + long **dp = (long **)calloc(goal + 1, sizeof(long *)); + for (int i = 0; i < goal + 1; i++) + dp[i] = (long *)calloc(n + 1, sizeof(long)); + dp[0][0] = 1; + for (int i = 1; i <= goal; i++) + for (int j = 1; j <= n; j++) { + dp[i][j] += (dp[i - 1][j - 1] * (n - (j - 1))) % mod; + dp[i][j] += (dp[i - 1][j] * (long)fmax(0, j - k)) % mod; + dp[i][j] %= mod; + } + int ans = dp[goal][n]; + for (int i = 0; i < goal + 1; i++) + free(dp[i]); + free(dp); + return ans; +} + +int main() { + printf("%d\n", numMusicPlaylists(3, 3, 1)); // expect: 6 + printf("%d\n", numMusicPlaylists(2, 3, 0)); // expect: 6 + printf("%d\n", numMusicPlaylists(2, 3, 1)); // expect: 2 +} diff --git a/num_music_playlists.cpp b/num_music_playlists.cpp new file mode 100644 index 0000000..14e5b65 --- /dev/null +++ b/num_music_playlists.cpp @@ -0,0 +1,40 @@ +// 920. Number of Music Playlists +#include "leetcode.h" + +/* + * your music player contains 'n' different songs. you want to listen to 'goal' + * songs (not necessarily different) during your trip. to avoid boredom, you + * will create a playlist so that: + * - every song is played at least once + * - a song can only be played again only if 'k' other songs have been played + * given 'n, goal, k', return the number of possible playlists that you can + * create. since the answer can be very large, return it modulo 10^9+7 + */ + +class Solution { + const int mod = 1e9 + 7; + long long solve(int n, int goal, int k, vvd(int) & dp) { + if (!n && !goal) + return 1; + if (!n || !goal) + return 0; + if (dp[n][goal] != -1) + return dp[n][goal]; + long long pick = solve(n - 1, goal - 1, k, dp) * n; + long long skip = solve(n, goal - 1, k, dp) * max(n - k, 0); + return dp[n][goal] = (pick + skip) % mod; + } + +public: + int numMusicPlaylists(int n, int goal, int k) { + vvd(int) dp(n + 1, vector<int>(goal + 1, -1)); + return solve(n, goal, k, dp); + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.numMusicPlaylists(3, 3, 1)); // expect: 6 + printf("%d\n", obj.numMusicPlaylists(2, 3, 0)); // expect: 6 + printf("%d\n", obj.numMusicPlaylists(2, 3, 1)); // expect: 2 +} diff --git a/num_nodes_sub_tree.cpp b/num_nodes_sub_tree.cpp new file mode 100644 index 0000000..426c8e1 --- /dev/null +++ b/num_nodes_sub_tree.cpp @@ -0,0 +1,47 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> countSubTrees(int n, vvd(int) & edges, string labels) { + vector<int> ans(n); + int cnt[26] = {}; + vvd(int) i(n); + for (auto e : edges) { + i[e[0]].push_back(e[1]); + i[e[1]].push_back(e[0]); + } + dfs(0, labels, i, cnt, ans); + return ans; + } + +private: + void dfs(int i, string labels, vvd(int) & edges, int cnt[], + vector<int> &ans) { + if (ans[i] == 0) { + ans[i] = 1; + for (auto j : edges[i]) { + int cnt1[26] = {}; + dfs(j, labels, edges, cnt1, ans); + for (auto k = 0; k < 26; ++k) + cnt[k] += cnt1[k]; + } + ans[i] = ++cnt[labels[i] - 'a']; + } + } +}; + +int main() { + Solution obj; + vvd(int) edges1 = {{0, 1}, {0, 2}, {1, 4}, {1, 5}, {2, 3}, {2, 6}}, + edges2 = {{0, 1}, {1, 2}, {0, 3}}, + edges3 = {{0, 1}, {0, 2}, {1, 3}, {0, 4}}; + for (auto i : obj.countSubTrees(7, edges1, "abaedcd")) + cout << i << ' '; // expect: 2,1,1,1,1,1,1 + cout << endl; + for (auto i : obj.countSubTrees(4, edges2, "bbbb")) + cout << i << ' '; // expect: 4,2,1,1 + cout << endl; + for (auto i : obj.countSubTrees(5, edges3, "aabab")) + cout << i << ' '; // expect: 3,2,1,1,1 + cout << endl; +} diff --git a/num_nodes_sub_tree.rs b/num_nodes_sub_tree.rs new file mode 100644 index 0000000..ca52f7b --- /dev/null +++ b/num_nodes_sub_tree.rs @@ -0,0 +1,39 @@ +use std::collections::{HashMap, HashSet}; +struct Solution; + +impl Solution { + pub fn count_sub_trees(n: i32, edges: Vec<Vec<i32>>, labels: String) -> Vec<i32> { + let mut map = HashMap::<usize, Vec<usize>>::new(); + for e in &edges { + map.entry(e[0] as usize).or_default().push(e[1] as usize); + map.entry(e[1] as usize).or_default().push(e[0] as usize); + } + let mut visited = HashSet::<usize>::new(); + let mut ans = vec![0; n as usize]; + Self::dfs(n, &mut map, &labels, 0, &mut visited, &mut ans); + ans + } + fn dfs(n: i32, map: &mut HashMap<usize, Vec<usize>>, labels: &str, + x: usize, visited: &mut HashSet<usize>, ans: &mut Vec<i32>) -> [i32; 26] { + let mut vec = [0;26]; + if visited.insert(x) { + for e in map.entry(x).or_default().clone() { + let v = Self::dfs(n, map, labels, e, visited, ans); + for i in 0..26 { + vec[i] += v[i] + } + } + let ch = labels.as_bytes()[x]; + vec[(ch - b'a') as usize] += 1; + ans[x] = vec[(ch - b'a') as usize]; + } + vec + } +} + +fn main() { + let edges = vec![vec![0,1],vec![0,2],vec![1,4], + vec![1,5],vec![2,3],vec![2,6]]; + print!("{:?}", Solution::count_sub_trees(7, edges, String::from("abaedcd"))); + //expect: [2,1,1,1,1,1,1] +} diff --git a/num_op_connect_network.c b/num_op_connect_network.c new file mode 100644 index 0000000..55f7d70 --- /dev/null +++ b/num_op_connect_network.c @@ -0,0 +1,55 @@ +// 1319. Number of Operations to Make Network Connected +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +int union_find(int *u, int val) { + if (u[val] == val) + return val; + return union_find(u, u[val]); +} + +bool union_set(int *u, int *usize, int a, int b) { + int find_a = union_find(u, a); + int find_b = union_find(u, b); + if (find_a == find_b) + return false; + if (usize[find_a] > usize[find_b]) { + u[find_b] = u[find_a]; + usize[find_a] += usize[find_b]; + } else { + u[find_a] = u[find_b]; + usize[find_b] += usize[find_a]; + } + return true; +} + +int makeConnected(int n, int **connections, int connections_size, + int *connections_col_size) { + if (connections_size < n - 1) + return -1; + int *u = malloc(n * sizeof(int)); + int *usize = malloc(n * sizeof(int)); + for (int i = 0; i < n; i++) { + u[i] = i; + usize[i] = 1; + } + int ans = 0; + for (int i = 0; i < connections_size; i++) + if (union_set(u, usize, connections[i][0], connections[i][1]) == false) + ans++; + if (connections_size - ans >= n - 1) + return 0; + else + return (n - 1) - (connections_size - ans); +} + +int main() { + int c1[3][2] = {{0, 1}, {0, 2}, {1, 2}}; + int c2[5][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}}; + int c3[5][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}}; + int c1_c_s[] = {3}, c2_c_s[] = {5}, c3_c_s[] = {5}; + printf("%d\n", makeConnected(4, c1, 3, c1_c_s)); + printf("%d\n", makeConnected(6, c2, 5, c1_c_s)); + printf("%d\n", makeConnected(6, c3, 5, c1_c_s)); +} diff --git a/num_op_connect_network.cpp b/num_op_connect_network.cpp new file mode 100644 index 0000000..a519f66 --- /dev/null +++ b/num_op_connect_network.cpp @@ -0,0 +1,41 @@ +// 1319. Number of Operations to Make Network Connected +#include "leetcode.h" + +class Solution { +public: + int makeConnected(int n, vvd(int) & connections) { + if (connections.size() < n - 1) + return -1; + vvd(int) adj(n); + for (auto v : connections) { + adj[v[0]].push_back(v[1]); + adj[v[1]].push_back(v[0]); + } + vector<bool> visited(n, false); + int comp = 0; + for (int i = 0; i < n; i++) + if (!visited[i]) { + dfs(adj, visited, i); + comp++; + } + return comp - 1; + } + +private: + void dfs(vvd(int) & adj, vector<bool> &visited, int src) { + visited[src] = true; + for (int i : adj[src]) + if (!visited[i]) + dfs(adj, visited, i); + } +}; + +int main() { + Solution obj; + vvd(int) c1 = {{0, 1}, {0, 2}, {1, 2}}; + vvd(int) c2 = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}}; + vvd(int) c3 = {{0, 1}, {0, 2}, {0, 3}, {1, 2}}; + printf("%d\n", obj.makeConnected(4, c1)); + printf("%d\n", obj.makeConnected(6, c2)); + printf("%d\n", obj.makeConnected(6, c3)); +} diff --git a/num_people_aware_secret.cpp b/num_people_aware_secret.cpp new file mode 100644 index 0000000..80a4b91 --- /dev/null +++ b/num_people_aware_secret.cpp @@ -0,0 +1,27 @@ +#include "leetcode.h" + +class Solution { +public: + int peopleAwareOfSecret(int n, int delay, int forget) { + long long sharing = 0, mod = 1000000007; + deque<int> d{1}, f{1}; + while (--n > 0) { + if (d.size() >= delay) { + sharing = (sharing + d.front()) % mod; + d.pop_front(); + } + if (f.size() >= forget) { + sharing = (mod + sharing - f.front()) % mod; + f.pop_front(); + } + d.push_back(sharing); + f.push_back(sharing); + } + return accumulate(begin(f), end(f), 0LL) % mod; + } +}; + +int main() { + Solution obj; + cout << obj.peopleAwareOfSecret(6, 2, 4); +} diff --git a/num_same_consecutive_diff.cpp b/num_same_consecutive_diff.cpp new file mode 100644 index 0000000..0602ce1 --- /dev/null +++ b/num_same_consecutive_diff.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> numsSameConsecDiff(int n, int k) { + vector<int> ans; + for (int i = 1; i < 10; i++) + findNum(i, n, k, ans); + return ans; + } + +private: + int digits(int x) { + int count = 0; + while (x) { + count++; + x /= 10; + } + return count; + } + void findNum(int curr, int n, int k, vector<int> &ans) { + if (digits(curr) == n) { + ans.push_back(curr); + return; + } + for (int i = 0; i < 10; i++) { + int last = curr % 10; + if (abs(last - i) == k) + findNum((curr * 10 + i), n, k, ans); + } + } +}; diff --git a/num_smaller_num_self.cpp b/num_smaller_num_self.cpp new file mode 100644 index 0000000..49b3ed3 --- /dev/null +++ b/num_smaller_num_self.cpp @@ -0,0 +1,44 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> countSmaller(vector<int> &nums) { + int n = nums.size(); + vector<pair<int, int>> vp(n); + vector<int> count(n, 0); + for (int i = 0; i < n; i++) + vp[i] = make_pair(nums[i], i); + sort(count, vp, 0, n - 1); + return count; + } + +private: + void merge(vector<int> &count, vector<pair<int, int>> &vp, int left, int mid, + int right) { + vector<pair<int, int>> tmp(right - left + 1); + int i = left, j = mid + 1, k = 0; + while (i <= mid && j <= right) { + if (vp[i].first <= vp[j].first) + tmp[k++] = vp[j++]; + else { + count[vp[i].second] += right - j + 1; + tmp[k++] = vp[i++]; + } + } + while (i <= mid) + tmp[k++] = vp[i++]; + while (j <= right) + tmp[k++] = vp[j++]; + for (int i = left; i <= right; i++) + vp[i] = tmp[i - left]; + } + void sort(vector<int> &count, vector<pair<int, int>> &vp, int left, + int right) { + if (left >= right) + return; + int mid = left + (right - left) / 2; + sort(count, vp, left, mid); + sort(count, vp, mid + 1, right); + merge(count, vp, left, mid, right); + } +}; diff --git a/num_squareful_arrays.c b/num_squareful_arrays.c new file mode 100644 index 0000000..a468f37 --- /dev/null +++ b/num_squareful_arrays.c @@ -0,0 +1,68 @@ +// 996. Number of Squareful Arrays +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * an array is squareful if the sum of every pair of adjacent elements is a + * perfect square. given an intger array nums, return the number of permutations + * of 'nums' that are squareful. two permutations 'perm1' and 'perm2' are + * different if there is some index 'i' such that 'perm1[i] != perm2[i]'. + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +void process(int *idx, int *data, int pos, int *nums, int nums_size, + int *nums_cnt, int n) { + if (pos == n) { + (*idx)++; + return; + } + for (int i = 0; i < nums_size; i++) { + if (nums_cnt[i]) + if (pos) { + int sum = data[pos - 1] + nums[i]; + int sq = (int)sqrt(sum); + if (sum != sq * sq) + continue; + } + data[pos] = nums[i]; + pos++; + nums_cnt[i]--; + process(idx, data, pos, nums, nums_size, nums_cnt, n); + pos--; + nums_cnt[i]++; + } +} + +int numSquarefulPerms(int *nums, int nums_size) { + qsort(nums, nums_size, sizeof(int), cmp); + int *new_nums = malloc(nums_size * sizeof(int)); + int *nums_cnt = malloc(nums_size * sizeof(int)); + new_nums[0] = nums[0]; + nums_cnt[0] = 1; + int new_nums_size = 1; + for (int i = 1; i < nums_size; i++) { + if (nums[i] == nums[i - 1]) + nums_cnt[new_nums_size - 1]++; + else { + new_nums[new_nums_size] = nums[i]; + nums_cnt[new_nums_size] = 1; + new_nums_size++; + } + } + new_nums = realloc(new_nums, sizeof(int) * new_nums_size); + nums_cnt = realloc(nums_cnt, new_nums_size * sizeof(int)); + int *idx = calloc(1, sizeof(int)); + int *data = malloc(nums_size * sizeof(int)); + process(idx, data, 0, new_nums, new_nums_size, nums_cnt, nums_size); + int ans = *idx; + free(idx), free(data), free(new_nums), free(nums_cnt); + return ans; +} + +int main() { + int n1[] = {1, 17, 8}, n2[] = {2, 2, 2}; + printf("%d\n", numSquarefulPerms(n1, 3)); // expect: 2 + printf("%d\n", numSquarefulPerms(n2, 3)); // expect: 1 +} diff --git a/num_squareful_arrays.cpp b/num_squareful_arrays.cpp new file mode 100644 index 0000000..7d71da3 --- /dev/null +++ b/num_squareful_arrays.cpp @@ -0,0 +1,59 @@ +// 996. Number of Squareful Arrays +#include "leetcode.h" + +/* + * an array is squareful if the sum of every pair of adjacent elements is a + * perfect square. given an intger array nums, return the number of permutations + * of 'nums' that are squareful. two permutations 'perm1' and 'perm2' are + * different if there is some index 'i' such that 'perm1[i] != perm2[i]'. + */ + +class Solution { + bool is_square(int x) { + int t = sqrt(x); + return t * t == x; + } + int fact(int x) { + int t = 1; + for (int i = 2; i <= x; i++) + t *= i; + return t; + } + +public: + int numSquarefulPerms(vector<int> &nums) { + int n = nums.size(), cnt = 1; + sort(nums.begin(), nums.end()); + vector<int> s; + for (int i = 1; i < n; i++) { + if (nums[i] != nums[i - 1]) { + s.push_back(cnt); + cnt = 0; + } + cnt++; + } + s.push_back(cnt); + vvd(int) f(1 << n, vector<int>(n, 0)); + for (int i = 0; i < n; i++) + f[1 << i][i] = 1; + for (int S = 1; S < 1 << n; S++) + for (int i = 0; i < n; i++) + if (S & (1 << i)) + for (int j = 0; j < n; j++) + if (!(S & (1 << j)) && is_square(nums[i] + nums[j])) + f[S | (1 << j)][j] += f[S][i]; + int ans = 0; + for (int i = 0; i < n; i++) + ans += f[(1 << n) - 1][i]; + for (int i = 0; i < s.size(); i++) + ans /= fact(s[i]); + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 17, 8}, n2 = {2, 2, 2}; + printf("%d\n", obj.numSquarefulPerms(n1)); // expect: 2 + printf("%d\n", obj.numSquarefulPerms(n2)); // expect: 1 +} diff --git a/num_steps_reduct_num.c b/num_steps_reduct_num.c new file mode 100644 index 0000000..78bfb53 --- /dev/null +++ b/num_steps_reduct_num.c @@ -0,0 +1,47 @@ +// 1404. Number of Steps to Reduce a Number in Binary Representation to One +#include "leetcode.h" + +/* + * given the binary representation of an integer as a string 's', return the + * number of steps to reduce it to 1 under the following rules. if the current + * number is even, you have to divide it by 2. if the current number is odd, you + * have to add 1 to it. it is guaranteed that you can always reach one for all + * test cases. + */ + +int numSteps(char *s) { + int n = strlen(s), k = n / 2; + char *tmp = (char *)malloc((n + k + 1) * sizeof(char)); + for (int i = 0; i < k; i++) + tmp[i] = '0'; + strncpy(&tmp[k], s, n + 1); + int l = k, r = n + k - 1, step = 0; + while (l != r) { + if (tmp[r] == '0') + r--; + else if (tmp[r] == '1') { + tmp[r] = '0'; + int m = r - 1; + while (1) { + if (tmp[m] == '0') { + tmp[m] = '1'; + if (m < l) + l = m; + break; + } else { + tmp[m] = '0'; + } + m--; + } + } + step++; + } + return step; +} + +int main() { + char *s1 = "1101", *s2 = "10", *s3 = "1"; + printf("%d\n", numSteps(s1)); // expect: 6 + printf("%d\n", numSteps(s2)); // expect: 1 + printf("%d\n", numSteps(s3)); // expect: 0 +} diff --git a/num_steps_reduct_num.py b/num_steps_reduct_num.py new file mode 100644 index 0000000..6ff4efc --- /dev/null +++ b/num_steps_reduct_num.py @@ -0,0 +1,32 @@ +# 1404. Number of Steps to Reduce a Number in Binary Representation to One + +""" +given the binary representation of an integer as a string 's', return the +number of steps to reduce it to 1 under the following rules. if the current +number is even, you have to divide it by 2. if the current number is odd, you +have to add 1 to it. it is guaranteed that you can always reach one for all +test cases. +""" + + +class Solution(object): + def numSteps(self, s): + """ + :type s: str + :rtype: int + """ + ans, carry, n = 0, 0, len(s) + for i in range(n - 1, 0, -1): + if int(s[i]) + carry == 1: + carry = 1 + ans += 2 + else: + ans += 1 + return ans + carry + + +if __name__ == "__main__": + obj = Solution() + print(obj.numSteps("1101")) + print(obj.numSteps("10")) + print(obj.numSteps("1")) diff --git a/num_student_unable_eat.c b/num_student_unable_eat.c new file mode 100644 index 0000000..ebcd8fb --- /dev/null +++ b/num_student_unable_eat.c @@ -0,0 +1,41 @@ +// 1700. Number of Students Unable to Eat Lunch +#include "leetcode.h" + +/* + * the school cafeteria offers circular and square sandwiches at lunch break, + * referred to by numbers 0 and 1, respectively. all students stand in a queue. + * each student either prefers square or circular sandwiches. the number of + * sandwiches in the cafeteria is equal to the number of students. + */ + +int countStudents(int *students, int studentsSize, int *sandwiches, + int sandwichesSize) { + int n = studentsSize, one_cnt = 0, zero_cnt = 0; + for (int i = 0; i < n; i++) + if (students[i]) + one_cnt++; + zero_cnt = n - one_cnt; + for (int i = 0; i < n; i++) { + if (sandwiches[i]) { + if (one_cnt) + one_cnt--; + else + return n - i; + } else { + if (zero_cnt) + zero_cnt--; + else + return n - i; + } + } + return 0; +} + +int main() { + int st1[] = {1, 1, 0, 0}, sa1[] = {0, 1, 0, 1}, st2[] = {1, 1, 1, 0, 0, 1}, + sa2[] = {1, 0, 0, 0, 1, 1}; + printf("%d\n", countStudents(st1, ARRAY_SIZE(st1), sa1, + ARRAY_SIZE(sa1))); // expect: 0 + printf("%d\n", countStudents(st2, ARRAY_SIZE(st2), sa2, + ARRAY_SIZE(sa2))); // expect: 3 +} diff --git a/num_student_unable_eat.py b/num_student_unable_eat.py new file mode 100644 index 0000000..b641072 --- /dev/null +++ b/num_student_unable_eat.py @@ -0,0 +1,30 @@ +# 1700. Number of Students Unable to Eat Lunch +from collections import Counter + +""" +the school cafeteria offers circular and square sandwiches at lunch break, +referred to by numbers 0 and 1, respectively. all students stand in a queue. +each student either prefers square or circular sandwiches. the number of +sandwiches in the cafeteria is equal to the number of students. +""" + + +class Solution(object): + def countStudents(self, students, sandwiches): + """ + :type students: List[int] + :type sandwiches: List[int] + :rtype: int + """ + cnt = Counter(students) + n, k = len(students), 0 + while k < n and cnt[sandwiches[k]]: + cnt[sandwiches[k]] -= 1 + k += 1 + return n - k + + +if __name__ == "__main__": + obj = Solution() + print(obj.countStudents(students=[1, 1, 0, 0], sandwiches=[0, 1, 0, 1])) + print(obj.countStudents(students=[1, 1, 1, 0, 0, 1], sandwiches=[1, 0, 0, 0, 1, 1])) diff --git a/num_subarr_bounded_max.c b/num_subarr_bounded_max.c new file mode 100644 index 0000000..3f0ae26 --- /dev/null +++ b/num_subarr_bounded_max.c @@ -0,0 +1,43 @@ +// 795. Number of Subarrays with Bounded Maximum +#include "leetcode.h" + +/* + * given an integer array 'nums' and two integers 'left' and 'right', return the + * number of contiguous non empty subarrays such that the value of the maximum + * array element in that subarray is in the range '[left, right]'. the test + * cases are generated such that the answer will fit into a 32 bit integer. + */ + +int helper(int *nums, int n, int left) { + if (!n) + return 0; + long long res = (long long)(n + 1) * n / 2; + int cnt = 0; + for (int i = 0; i < n; i++) { + if (nums[i] < left) + cnt++; + else { + res -= (cnt + 1) * cnt / 2; + cnt = 0; + } + } + res -= (cnt + 1) * cnt / 2; + return res; +} + +int numSubarrayBoundedMax(int *nums, int numsSize, int left, int right) { + int ans = 0, prev = 0; + for (int i = 0; i < numsSize; i++) + if (nums[i] > right) { + ans += helper(&nums[prev], i - prev, left); + prev = i + 1; + } + ans += helper(&nums[prev], numsSize - prev, left); + return ans; +} + +int main() { + int n1[] = {2, 1, 4, 3}, n2[] = {2, 9, 2, 5, 6}; + printf("%d\n", numSubarrayBoundedMax(n1, ARRAY_SIZE(n1), 2, 3)); // expect: 3 + printf("%d\n", numSubarrayBoundedMax(n2, ARRAY_SIZE(n2), 2, 8)); // expect: 7 +} diff --git a/num_subarr_bounded_max.py b/num_subarr_bounded_max.py new file mode 100644 index 0000000..9bf8da6 --- /dev/null +++ b/num_subarr_bounded_max.py @@ -0,0 +1,35 @@ +# 795. Number of Subarrays with Bounded Maximum + +""" +given an integer array 'nums' and two integers 'left' and 'right', return the +number of contiguous non empty subarrays such that the value of the maximum +array element in that subarray is in the range '[left, right]'. the test +cases are generated such that the answer will fit into a 32 bit integer. +""" + + +class Solution(object): + def numSubarrayBoundedMax(self, nums, left, right): + """ + :type nums: List[int] + :type left: int + :type right: int + :rtype: int + """ + ans, prev, dp = 0, -1, 0 + for i in range(len(nums)): + if nums[i] < left and i > 0: + ans += dp + if nums[i] > right: + dp = 0 + prev = i + if left <= nums[i] <= right: + dp = i - prev + ans += dp + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.numSubarrayBoundedMax(nums=[2, 1, 4, 3], left=2, right=3)) + print(obj.numSubarrayBoundedMax(nums=[2, 9, 2, 5, 6], left=2, right=8)) diff --git a/num_submatrices_sum_target.c b/num_submatrices_sum_target.c new file mode 100644 index 0000000..06a3fe2 --- /dev/null +++ b/num_submatrices_sum_target.c @@ -0,0 +1,31 @@ +// 1074. Number of Submatrices That Sum to Target +#include "leetcode.h" + +/* + * given a 'matrix' and 'target', return the number of non-empty submatrices + * that sum to target. a submatrix 'x1, y1 x2, y2' is the set of all cells + * 'matrix[x][y]' with 'x1 <= x <= x2' and 'y1 <= y <= y2'. two submatrices are + * different if they have some coordinate that is different. for example if x1 + * != x1 + */ + +int numSubmatrixSumTarget(int **matrix, int matrix_size, int *matrix_col_size, + int target) { + int r_size = matrix_col_size[0], dp[r_size], ans = 0, y = 0; + while (y < matrix_size) { + memset(dp, 0, sizeof(int) * r_size); + for (int row = y; row < matrix_size; row++) + for (int col = 0; col < r_size; col++) + dp[col] += matrix[row][col]; + for (int col = 0; col < r_size; col++) { + int sum = 0; + for (int _col = col; _col < r_size; _col++) { + sum += dp[_col]; + if (sum == target) + ans++; + } + } + y++; + } + return ans; +} diff --git a/num_submatrices_sum_target.py b/num_submatrices_sum_target.py new file mode 100644 index 0000000..7f277f5 --- /dev/null +++ b/num_submatrices_sum_target.py @@ -0,0 +1,40 @@ +# 1074. Number of Submatrices That Sum to Target +from collections import defaultdict + +""" +given a 'matrix' and 'target', return the number of non-empty submatrices +that sum to target. a submatrix 'x1, y1 x2, y2' is the set of all cells +'matrix[x][y]' with 'x1 <= x <= x2' and 'y1 <= y <= y2'. two submatrices are +different if they have some coordinate that is different. for example if x1 +!= x1 +""" + + +class Solution(object): + def numSubmatrixSumTarget(self, matrix, target): + """ + :type matrix: List[List[int]] + :type target: int + :rtype: int + """ + m, n = len(matrix), len(matrix[0]) + for row in matrix: + for i in range(n - 1): + row[i + 1] += row[i] + ans = 0 + for i in range(n): + for j in range(i, n): + c = collections.defaultdict(int) + curr, c[0] = 0, 1 + for k in range(m): + curr += matrix[k][j] - (matrix[k][i - 1] if i > 0 else 0) + ans += c[curr - target] + c[curr] += 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.numSubmatrixSumTarget(matrix=[[0, 1, 0], [1, 1, 1], [0, 1, 0]], target=0)) + print(obj.numSubmatrixSumTarget(matrix=[[1, -1], [-1, 1]], target=0)) + print(obj.numSubmatrixSumTarget(matrix=[[904]], target=0)) diff --git a/num_subseq_satisfy.c b/num_subseq_satisfy.c new file mode 100644 index 0000000..d7570d0 --- /dev/null +++ b/num_subseq_satisfy.c @@ -0,0 +1,55 @@ +// 1498. Number of Subsequences That Satisfy the Given Sum Condition +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array of integers 'nums' and an integer 'target' + * return the numbe of non-empty subsequences of 'nums' such + * that the sum of the minimum and maximum element on it is + * less or equal to 'target'. return modulo 10^9+7 + */ + +#define MOD 1000000007 + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +long long _pow(long long a, int b) { + a %= MOD; + if (!b) + return 1; + if (b) + return a; + if (b % 2) + return a * _pow(a, b - 1) % MOD; + return _pow(a * a, b / 2) % MOD; +} + +int numSubseq(int *nums, int nums_size, int target) { + int n = nums_size; + qsort(nums, n, sizeof(int), cmp); + long long ans; + int j = n - 1; + for (int i = 0; i < n; i++) { + if (nums[i] * 2 > target) + break; + int rem = target - nums[i]; + while (i < j) { + if (nums[j] > rem) + j--; + else + break; + } + ans += _pow(2, j - i); + ans %= MOD; + } + return ans; +} + +int main() { + int n1[] = {3, 5, 6, 7}, ns1 = 4, t1 = 9; + int n2[] = {3, 3, 6, 8}, ns2 = 4, t2 = 10; + int n3[] = {2, 3, 3, 4, 6, 7}, ns3 = 6, t3 = 12; + printf("%d\n", numSubseq(n1, ns1, t1)); // expect: 4 + printf("%d\n", numSubseq(n2, ns2, t2)); // expect: 6 + printf("%d\n", numSubseq(n3, ns3, t3)); // expect: 61 +} diff --git a/num_subseq_satisfy.cpp b/num_subseq_satisfy.cpp new file mode 100644 index 0000000..6eb1a12 --- /dev/null +++ b/num_subseq_satisfy.cpp @@ -0,0 +1,34 @@ +// 1498. Number of Subsequences That Satisfy the Given Sum Condition +#include "leetcode.h" + +/* + * given an array of integers 'nums' and an integer 'target' + * return the numbe of non-empty subsequences of 'nums' such + * that the sum of the minimum and maximum element on it is + * less or equal to 'target'. return modulo 10^9+7 + */ + +class Solution { +public: + int numSubSeq(vector<int> &nums, int target) { + int ans = 0, mod = 1000000007; + vector<int> pre = {0, 1}; + for (auto i = pre.size(); i <= nums.size(); ++i) + pre.push_back((pre.back() << 1) % mod); + sort(nums.begin(), nums.end()); + for (int i = 0, j = nums.size() - 1; i <= j; ++i) { + while (i <= j && nums[i] + nums[j] > target) + --j; + ans = (ans + pre[j - i + 1]) % mod; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {3, 5, 6, 7}, n2 = {3, 3, 6, 8}, n3 = {2, 3, 3, 4, 6, 7}; + printf("%d\n", obj.numSubSeq(n1, 9)); // expect: 4 + printf("%d\n", obj.numSubSeq(n2, 10)); // expect: 6 + printf("%d\n", obj.numSubSeq(n3, 12)); // expect: 61 +} diff --git a/num_substrings_3_char.c b/num_substrings_3_char.c new file mode 100644 index 0000000..5a37858 --- /dev/null +++ b/num_substrings_3_char.c @@ -0,0 +1,30 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int helper(char *s, int k) { + int n = strlen(s), type = 0, left = 0, right = 0, res = 0; + int *cn = calloc(3, sizeof(int)); + for (int right = 0; right < n; right++) { + cn[s[right] - 'a']++; + if (cn[s[right] - 'a'] == 1) + type++; + while (type > k) { + cn[s[left] - 'a']--; + if (!cn[s[left] - 'a']) + type--; + left++; + } + res += right - left + 1; + } + return res; +} + +int numberOfSubstrings(char *s) { return helper(s, 3) - helper(s, 2); } + +int main() { + char s1[] = {"abcabc"}, s2[] = {"aaacb"}, s3[] = {"abc"}; + printf("%d\n", numberOfSubstrings(s1)); // expect: 10 + printf("%d\n", numberOfSubstrings(s2)); // expect: 3 + printf("%d\n", numberOfSubstrings(s3)); // expect: 1 +} diff --git a/num_substrings_only_1.c b/num_substrings_only_1.c new file mode 100644 index 0000000..2bb0698 --- /dev/null +++ b/num_substrings_only_1.c @@ -0,0 +1,34 @@ +// 1513. Number of Substrings With Only 1s +#include "leetcode.h" + +/* + * given a binary string 's', return the number of substrings with all + * characters 1's since the answer may be too large, return it modulo 1e9+7. + */ + +int numSub(char *s) { + int n = strlen(s), mod = 1e9 + 7, ans = 0, one_cnt = 0; + for (int i = 0; i < n; i++) { + if (s[i] == '1') + one_cnt++; + else { + if (one_cnt) { + long long val = (long long)(one_cnt + 1) * one_cnt / 2; + ans = (ans + val % mod) % mod; + } + one_cnt = 0; + } + } + if (one_cnt) { + long long val = (long long)(one_cnt + 1) * one_cnt / 2; + ans = (ans + val % mod) % mod; + } + return ans; +} + +int main() { + char *s1 = "0110111", *s2 = "101", *s3 = "11111"; + printf("%d\n", numSub(s1)); // expect: 9 + printf("%d\n", numSub(s2)); // expect: 2 + printf("%d\n", numSub(s3)); // expect: 21 +} diff --git a/num_substrings_only_1.py b/num_substrings_only_1.py new file mode 100644 index 0000000..a405c9c --- /dev/null +++ b/num_substrings_only_1.py @@ -0,0 +1,22 @@ +# 1513. Number of Substrings With Only 1s + +""" +given a binary string 's', return the number of substrings with all +characters 1's since the answer may be too large, return it modulo 1e9+7. +""" + + +class Solution(object): + def numSub(self, s): + """ + :type s: str + :rtype: int + """ + return sum(len(a) * (len(a) + 1) / 2 for a in s.split("0")) % (10**9 + 7) + + +if __name__ == "__main__": + obj = Solution() + print(obj.numSub("0110111")) + print(obj.numSub("101")) + print(obj.numSub("111111")) diff --git a/num_to_hex_binary.cpp b/num_to_hex_binary.cpp new file mode 100644 index 0000000..81470fd --- /dev/null +++ b/num_to_hex_binary.cpp @@ -0,0 +1,55 @@ +#include "leetcode.h" +#include <string> + +/* + * given integer 'num', return string representing hexidecimal value. + * for negative numbers, use two's complement method + */ + +class Solution { +public: + string toHex(int num) { + string ans; + while (num) { + int rem = num % 16; + if (rem > 9) + switch (rem) { + case 10: + ans = 'a' + ans; + break; + case 11: + ans = 'b' + ans; + break; + case 12: + ans = 'c' + ans; + break; + case 13: + ans = 'd' + ans; + break; + case 14: + ans = 'e' + ans; + break; + case 15: + ans = 'f' + ans; + break; + } + else + ans = char(rem + 48) + ans; + num /= 16; + } + return ans; + } + int toBinary(int num) { + int ans = 0; + return ans; + } +}; + +int main() { + Solution obj; + // obj.toHex(26); + cout << obj.toHex(26) << endl; // expect: "1a" + cout << obj.toHex(-1) << endl; // expect: "fffffff" + cout << obj.toBinary(26) << endl; // expect: 11010 + cout << obj.toBinary(-1) << endl; // expect: +} diff --git a/num_valid_words_puzzle.c b/num_valid_words_puzzle.c new file mode 100644 index 0000000..c423d60 --- /dev/null +++ b/num_valid_words_puzzle.c @@ -0,0 +1,61 @@ +// 1178. Number of Valid Words for Each Puzzle +#include "leetcode.h" + +/* + * with respect to a given puzzle string, a word is valid of both the following + * conditions are satisfied. word contains the first letter of puzzle. for each + * letter in word, that letter is in puzzle. invalid words are "beefed" (does + * not include "a") and "based" (includes "s" which is not in the puzzle). + * return an array where arr[i] is the number of words in the given word list + * words that is valid with respect to the puzzle + */ + +int *findNumOfValidWords(char **words, int wordsSize, char **puzzles, + int puzzlesSize, int *returnSize) { + int *ans = (int *)calloc(puzzlesSize, sizeof(int)); + int *freq = (int *)calloc(68000000, sizeof(int)); + for (int i = 0; i < wordsSize; i++) { + int tmp = 0, cnt = 0; + for (int j = 0; j < strlen(words[i]); j++) { + int bit = (1 << (int)(words[i][j] - 'a')); + if (tmp & bit) + continue; + cnt++; + if (cnt > 7) + break; + tmp |= (1 << (int)(words[i][j] - 'a')); + } + if (cnt > 7) + continue; + freq[tmp]++; + } + for (int i = 0; i < puzzlesSize; i++) + for (int j = 0; j < 64; j++) { + int tmp = (1 << (int)(puzzles[i][0] - 'a')); + for (int k = 0; k < 6; k++) + if (j & (1 << k)) + tmp |= (1 << (int)(puzzles[i][k + 1] - 'a')); + ans[i] += freq[tmp]; + } + *returnSize = puzzlesSize; + free(freq); + return ans; +} + +int main() { + char *w1[7][7] = { + {"aaaa", "asas", "able", "ability", "actt", "actor", "access"}}; + char *w2[3][6] = {{"apple", "pleas", "please"}}; + char *p1[6][7] = { + {"aboveyz", "abrodyz", "abslute", "absoryz", "actresz", "gaswxyz"}}; + char *p2[5][7] = {{"aelwxyz", "aelpxyz", "aelpsxy", "saelpxy", "xaelpsy"}}; + int rs1, rs2; + int *fnovw1 = findNumOfValidWords((char **)w1, 7, (char **)p1, 6, &rs1); + int *fnovw2 = findNumOfValidWords((char **)w2, 3, (char **)p2, 5, &rs2); + for (int i = 0; i < 6; i++) + printf("%d ", fnovw1[i]); // expect: 1 1 3 2 4 0 + printf("\n"); + for (int i = 0; i < 5; i++) + printf("%d ", fnovw2[i]); // expect: 0 1 3 2 0 + printf("\n"); +} diff --git a/num_valid_words_puzzle.cpp b/num_valid_words_puzzle.cpp new file mode 100644 index 0000000..9286280 --- /dev/null +++ b/num_valid_words_puzzle.cpp @@ -0,0 +1,40 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> findNumOfValidWords(vector<string> &words, + vector<string> &puzzles) { + unordered_map<int, int> um; + for (auto w : words) + um[(mask(w))]++; + vector<int> ans; + for (auto p : puzzles) { + int m = mask(p), s = m, first = (1 << p[0] - 'a'), curr = 0; + while (s) { + if (s & first) + curr += um[s]; + s = (s - 1) & m; + } + ans.push_back(curr); + } + return ans; + } + +private: + int mask(string word) { + int m = 0; + for (auto w : word) + m |= (1 << w - 'a'); + return m; + } +}; + +int main() { + Solution obj; + vector<string> words = {"aaaa", "asas", "able", "ability", + "actt", "actor", "access"}; + vector<string> puzzles = {"aboveyz", "abrodyz", "abslute", + "absoryz", "actresz", "gaswxyz"}; + for (const auto &i : obj.findNumOfValidWords(words, puzzles)) + cout << i << endl; +} diff --git a/num_valid_words_puzzle.py b/num_valid_words_puzzle.py new file mode 100644 index 0000000..7219825 --- /dev/null +++ b/num_valid_words_puzzle.py @@ -0,0 +1,61 @@ +# 1178. Number of Valid Words for Each Puzzle + +""" +with respect to a given puzzle string, a word is valid of both the following +conditions are satisfied. word contains the first letter of puzzle. for each +letter in word, that letter is in puzzle. invalid words are "beefed" (does +not include "a") and "based" (includes "s" which is not in the puzzle). +return an array where arr[i] is the number of words in the given word list +words that is valid with respect to the puzzle +""" + + +class Solution(object): + def get_mask(self, word): + mask = 0 + for c in word: + i = ord(c) - ord("a") + mask |= 1 << i + return mask + + def findNumOfValidWords(self, words, puzzles): + """ + :type words: List[str] + :type puzzles: List[str] + :rtype: List[int] + """ + freq = {} + for w in words: + mask = self.get_mask(w) + freq[mask] = freq.get(mask, 0) + 1 + ans = [0] * len(puzzles) + for i in range(len(puzzles)): + p = puzzles[i] + mask = self.get_mask(p) + sub_mask = mask + total = 0 + bit_idx = ord(p[0]) - ord("a") + while True: + if sub_mask >> bit_idx & 1: + total += freq.get(sub_mask, 0) + if not sub_mask: + break + sub_mask = (sub_mask - 1) & mask + ans[i] = total + return ans + + +if __name__ == "__main__": + obj = Solution() + print( + obj.findNumOfValidWords( + words=["aaaa", "asas", "able", "ability", "actt", "actor", "access"], + puzzles=["aboveyz", "abrodyz", "abslute", "absoryz", "actresz", "gaswxyz"], + ) + ) + print( + obj.findNumOfValidWords( + words=["apple", "pleas", "please"], + puzzles=["aelwxyz", "aelpxyz", "aelpsxy", "saelpxy", "xaelpsy"], + ) + ) diff --git a/num_ways_buy_pen.c b/num_ways_buy_pen.c new file mode 100644 index 0000000..212a910 --- /dev/null +++ b/num_ways_buy_pen.c @@ -0,0 +1,25 @@ +// 2240. Number of Ways to Buy Pens and Pencils +#include "leetcode.h" + +/* + * given an integer 'total' indicating the amount of money you have. you are + * also given two inegers 'cost1' and 'cost2' indicating the price of a pen and + * pencil respectively. you can spend part or all of your money to buy multiple + * quantities (or none) of each kind of writing utensil. return the number of + * distinct ways you can buy some number of pens and pencils + */ + +long long waysToBuyPensPencils(int total, int cost1, int cost2) { + long long ans = 0; + int val = total + cost1; + for (int i = 0; i <= total / cost1; i++) { + val -= cost1; + ans += (val / cost2 + 1); + } + return ans; +} + +int main() { + printf("%lld\n", waysToBuyPensPencils(20, 10, 5)); // expect: 9 + printf("%lld\n", waysToBuyPensPencils(5, 10, 10)); // expect: 1 +} diff --git a/num_ways_buy_pen.py b/num_ways_buy_pen.py new file mode 100644 index 0000000..d854160 --- /dev/null +++ b/num_ways_buy_pen.py @@ -0,0 +1,32 @@ +# 2240. Number of Ways to Buy Pens and Pencils + +""" +given an integer 'total' indicating the amount of money you have. you are +also given two inegers 'cost1' and 'cost2' indicating the price of a pen and +pencil respectively. you can spend part or all of your money to buy multiple +quantities (or none) of each kind of writing utensil. return the number of +distinct ways you can buy some number of pens and pencils +""" + + +class Solution(object): + def waysToBuyPensPencils(self, total, cost1, cost2): + """ + :type total: int + :type cost1: int + :type cost2: int + :rtype: int + """ + ways, pen_cost = 0, 0 + while pen_cost <= total: + remaining = total - pen_cost + pencils = remaining // cost2 + 1 + ways += pencils + pen_cost += cost1 + return ways + + +if __name__ == "__main__": + obj = Solution() + print(obj.waysToBuyPensPencils(20, 10, 5)) + print(obj.waysToBuyPensPencils(5, 10, 10)) diff --git a/num_ways_dict.c b/num_ways_dict.c new file mode 100644 index 0000000..cb712d0 --- /dev/null +++ b/num_ways_dict.c @@ -0,0 +1,27 @@ +// 1639. Number of Ways to Form a Target String Given a Dictionary +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define MOD 1000000007 + +int numWays(char **words, int words_size, char *target) { + int t_len = strlen(target), w_len = strlen(words[0]); + long *ans = (long *)calloc(t_len + 1, sizeof(long)); + ans[0] = 1; + for (int i = 0; i < w_len; i++) { + int cnt[26] = {0}; + for (int j = 0; j < words_size; j++) + cnt[words[i][j] - 'a']++; + for (int j = t_len - 1; j >= 0; j--) + ans[j + 1] += ans[j] * cnt[target[j] - 'a'] % MOD; + } + return ans[t_len] % MOD; +} + +int main() { + char w1[][] = {{"acca"}, {"bbbb"}, {"caca"}}, t1[] = {"aba"}; + char w2[][] = {{"abba"}, {"baab"}}, t2[] = {"bab"}; + printf("%d\n", numWays(w1, 3, t1)); // expect: 6 + printf("%d\n", numWays(w2, 2, t2)); // expect: 6 +} diff --git a/num_ways_dict.cpp b/num_ways_dict.cpp new file mode 100644 index 0000000..f047326 --- /dev/null +++ b/num_ways_dict.cpp @@ -0,0 +1,37 @@ +// 1639. Number of Ways to Form a Target String Given a Dictionary +#include "leetcode.h" + +class Solution { + int dp[1001][1001] = {}; + int dfs(vvd(int) cnt, string target, int i, int j) { + if (j >= target.size()) + return 1; + if (!dp[i][j]) { + dp[i][j] = 1; + for (int k = i; k + (target.size() - j) <= cnt.size(); ++k) + if (cnt[k][target[j] - 'a']) + dp[i][j] = + ((long)cnt[k][target[j] - 'a'] * dfs(cnt, target, k + 1, j + 1) + + dp[i][j]) % + 1000000007; + } + return dp[i][j] - 1; + } + +public: + int numWays(vector<string> &words, string target) { + vvd(int) cnt(words[0].size(), vector<int>(26)); + for (auto w : words) + for (auto i = 0; i < w.size(); ++i) + ++cnt[i][w[i] - 'a']; + return dfs(cnt, target, 0, 0); + } +}; + +int main() { + Solution obj; + vector<string> s1 = {"acca", "bbbb", "caca"}, s2 = {"abba", "baab"}; + string t1 = "aba", t2 = "bab"; + printf("%d\n", obj.numWays(s1, t1)); // expect: 6 + printf("%d\n", obj.numWays(s2, t2)); // expect: 4 +} diff --git a/num_ways_remain_place.cpp b/num_ways_remain_place.cpp new file mode 100644 index 0000000..eee14e5 --- /dev/null +++ b/num_ways_remain_place.cpp @@ -0,0 +1,32 @@ +// 1269. Number of Ways to Stay in the Same Place After Some Steps +#include "leetcode.h" + +/* + * you have a pointer at index 0 in an array of size 'arr_len'. at each step, + * you can move 1 position to the left, 1 position to the right in the array, or + * stay in the same plae. given two integers 'steps' and 'arr_len' return the + * number of ways such that your pointer is still at index 0 after exactly + * 'steps' steps. since the answer may be too large, return it modulo 10e9+7 + */ + +class Solution { +public: + int numWays(int steps, int arr_len) { + int n = min(steps / 2 + 1, arr_len); + vector<int> v1(n + 2), v2(n + 2); + v1[1] = 1; + while (steps--) { + for (auto i = 1; i <= n; ++i) + v2[i] = ((long)v1[i] + v1[i - 1] + v1[i + 1]) % 1000000007; + swap(v1, v2); + } + return v1[1]; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.numWays(3, 2)); // expect: 4 + printf("%d\n", obj.numWays(2, 4)); // expect: 2 + printf("%d\n", obj.numWays(4, 2)); // expect: 8 +} diff --git a/num_ways_remain_place.py b/num_ways_remain_place.py new file mode 100644 index 0000000..7204a3f --- /dev/null +++ b/num_ways_remain_place.py @@ -0,0 +1,34 @@ +# 1269. Number of Ways to Stay in the Same Place After Some Steps + +""" +you have a pointer at index 0 in an array of size 'arr_len'. at each step, +you can move 1 position to the left, 1 position to the right in the array, or +stay in the same plae. given two integers 'steps' and 'arr_len' return the +number of ways such that your pointer is still at index 0 after exactly +'steps' steps. since the answer may be too large, return it modulo 10e9+7 +""" + + +class Solution(object): + def dfs(self, steps, arr_len, pos): + if pos < 0 or pos >= arr_len: + return 0 + if steps == 0: + return 1 if pos == 0 else 0 + return ( + self.dfs(steps - 1, arr_len, pos - 1) + + self.dfs(steps - 1, arr_len, pos) + + self.dfs(steps - 1, arr_len, pos + 1) + ) + + def numWays(self, steps, arr_len): + if steps is None or steps < 0 or not arr_len: + return 0 + return self.dfs(steps, arr_len, 0) + + +if __name__ == "__main__": + obj = Solution() + print(obj.numWays(3, 2)) # expect: 4 + print(obj.numWays(2, 4)) # expect: 2 + print(obj.numWays(4, 2)) # expect: 8 diff --git a/num_ways_reorder_array.c b/num_ways_reorder_array.c new file mode 100644 index 0000000..ec110a1 --- /dev/null +++ b/num_ways_reorder_array.c @@ -0,0 +1,113 @@ +// 1569. Number of Ways to Reorder Array to Get Same BST +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array 'nums' that represents a permutation of integers from '1 to + * n'. we are going to construct a binary search tree (BST) by inserting the + * elements of 'nums' in order into an initially empty BST. find the number of + * different ways to reorder 'nums' so that the constructed BST is identical to + * that formed from the original array 'nums'. for example given 'nums = + * [2,1,3]', we will have 2 as the root, 1 as a left child, and three as a right + * child. the array [2,3,1] also yields the same BST, but '[3,2,1]' yields a + * different BST. return the number of ways to reorder 'nums' such that the BST + * formed is identical to the original BST formed from 'nums'. since the answer + * may be large, return it modulo 10^9+7 + */ + +long long factorial[1024], factorial_inv[1024], inv[1024]; +int mod = 1e9 + 7; + +typedef struct { + int val; + int left_cnt, right_cnt; + struct node *left, *right; +} node; + +void insert(node *root, int val) { + if (root->val > val) { + if (root->left == NULL) { + node *new = (node *)malloc(sizeof(node)); + new->val = val; + new->left = NULL; + new->right = NULL; + new->left_cnt = 0; + new->right_cnt = 0; + root->left = new; + root->left_cnt++; + return; + } else { + root->left_cnt++; + insert(root->left, val); + } + } else if (root->val < val) { + if (root->right == NULL) { + node *new = (node *)malloc(sizeof(node)); + new->val = val; + new->left = NULL; + new->right = NULL; + new->left_cnt = 0; + new->right_cnt = 0; + root->right = new; + root->right_cnt++; + return; + } else { + root->right_cnt++; + insert(root->right, val); + } + } +} + +void free_node(node *root) { + if (root->left) + free_node(root->left); + if (root->right) + free_node(root->right); + free(root); +} + +long long ways(node *root) { + if (!root) + return 1; + if (!root->left && !root->right) + return 1; + if (!root->left) + return ways(root->right) % mod; + if (!root->right) + return ways(root->left) % mod; + long long tmp = factorial[root->left_cnt + root->right_cnt]; + tmp = (tmp * factorial_inv[root->left_cnt]) % mod; + tmp = (tmp * factorial_inv[root->right_cnt]) % mod; + return ((tmp * ways(root->left) % mod) * ways(root->right)) % mod; +} + +int numOfWays(int *nums, int nums_size) { + factorial[0] = factorial[1] = 1; + factorial_inv[0] = factorial_inv[1] = 1; + inv[0] = inv[1] = 1; + for (int i = 2; i < 1024; i++) { + factorial[i] = (factorial[i - 1] * i) % mod; + inv[i] = mod - (mod / i * inv[mod % i]) % mod; + factorial_inv[i] = (factorial_inv[i - 1] * inv[i]) % mod; + } + node *root = (node *)malloc(sizeof(node)); + root->val = nums[0]; + root->left = NULL; + root->right = NULL; + root->left_cnt = 0; + root->right_cnt = 0; + for (int i = 1; i < nums_size; i++) + insert(root, nums[i]); + int ans = (int)ways(root) - 1; + free_node(root); + return ans; +} + +int main() { + int n1[] = {2, 1, 3}; + int n2[] = {3, 4, 5, 1, 2}; + int n3[] = {1, 2, 3}; + printf("%d\n", numOfWays(n1, 3)); // expect: 1 + printf("%d\n", numOfWays(n2, 5)); // expect: 5 + printf("%d\n", numOfWays(n3, 3)); // expect: 0 +} diff --git a/num_ways_reorder_array.cpp b/num_ways_reorder_array.cpp new file mode 100644 index 0000000..df5e538 --- /dev/null +++ b/num_ways_reorder_array.cpp @@ -0,0 +1,57 @@ +// 1569. Number of Ways to Reorder Array to Get Same BST +#include "leetcode.h" + +/* + * given an array 'nums' that represents a permutation of integers from '1 to + * n'. we are going to construct a binary search tree (BST) by inserting the + * elements of 'nums' in order into an initially empty BST. find the number of + * different ways to reorder 'nums' so that the constructed BST is identical to + * that formed from the original array 'nums'. for example given 'nums = + * [2,1,3]', we will have 2 as the root, 1 as a left child, and three as a right + * child. the array [2,3,1] also yields the same BST, but '[3,2,1]' yields a + * different BST. return the number of ways to reorder 'nums' such that the BST + * formed is identical to the original BST formed from 'nums'. since the answer + * may be large, return it modulo 10^9+7 + */ + +class Solution { + int mod = 1e+9 + 7; + long l[10001][10001] = {0}; + bool init = false; + long combination(int n, int r) { + if (init) + return l[n][r]; + l[0][0] = 1; + for (int i = 1; i < 1001; i++) { + l[i][0] = 1; + for (int j = 1; j < i + 1; j++) + l[i][j] = (l[i - 1][j - 1] + l[i - 1][j]) % mod; + } + init = true; + return l[n][r]; + } + long dfs(vector<int> &nums) { + if (nums.size() < 3) + return 1; + vector<int> l, r; + for (auto n : nums) { + if (n > nums[0]) + l.push_back(n); + if (n < nums[0]) + r.push_back(n); + } + long c = combination(l.size() + r.size(), l.size()); + return c * dfs(l) % mod * dfs(r) % mod; + } + +public: + int numOfWays(vector<int> &nums) { return (int)dfs(nums) - 1; } +}; + +int main() { + Solution obj; + vector<int> n1 = {2, 1, 3}, n2 = {3, 4, 5, 1, 2}, n3 = {1, 2, 3}; + printf("%d\n", obj.numOfWays(n1)); // expect: 1 + printf("%d\n", obj.numOfWays(n2)); // expect: 5 + printf("%d\n", obj.numOfWays(n3)); // expect: 0 +} diff --git a/num_weak_char_game.cpp b/num_weak_char_game.cpp new file mode 100644 index 0000000..f369a2a --- /dev/null +++ b/num_weak_char_game.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + int numberOfWeakCharacters(vvd(int) & properties) { + sort(properties.begin(), properties.end(), compare); + int currMax = INT_MIN, ans = 0; + for (auto p : properties) { + if (currMax > p[1]) + ans++; + else + currMax = p[1]; + } + return ans; + } + +private: + static bool compare(vector<int> &a, vector<int> &b) { + if (a[0] != b[0]) + return a[0] > b[0]; + return a[1] < b[1]; + } +}; diff --git a/num_wonderful_substr.c b/num_wonderful_substr.c new file mode 100644 index 0000000..15bca29 --- /dev/null +++ b/num_wonderful_substr.c @@ -0,0 +1,38 @@ +// 1915. Number of Wonderful Substrings +#include "leetcode.h" + +/* + * a wonderful string is a string where at most one letter appears an odd number + * of times. for example "ccjjc" and "abab" are wonderful, but "ab" is not. + * given a string 'word' that consists of the first ten lowercase letters ('a' + * through 'j') return the number of wonderful non-empty substrings in 'word'. + * if the same substring appears multiple times in 'word', then count each + * occurence separately. a substring is a contiguous sequence of character in a + * string. + */ + +long long wonderfulSubstrings(char *word) { + int n = strlen(word), state = 0; + int *cnt = (int *)calloc(1 << 10, sizeof(int)); + cnt[0] = 1; + long long ans = 0; + for (int i = 0; i < n; i++) { + int k = word[i] - 'a'; + state ^= (1 << k); + ans += cnt[state]; + for (int j = 0; j < 10; j++) { + int j_state = state ^ (1 << j); + ans += cnt[j_state]; + } + cnt[state]++; + } + free(cnt); + return ans; +} + +int main() { + char *w1 = "aba", *w2 = "aabb", *w3 = "he"; + printf("%lld\n", wonderfulSubstrings(w1)); // expect: 4 + printf("%lld\n", wonderfulSubstrings(w2)); // expect: 9 + printf("%lld\n", wonderfulSubstrings(w3)); // expect: 2 +} diff --git a/num_wonderful_substr.py b/num_wonderful_substr.py new file mode 100644 index 0000000..f4dd059 --- /dev/null +++ b/num_wonderful_substr.py @@ -0,0 +1,34 @@ +# 1915. Number of Wonderful Substrings + +""" +a wonderful string is a string where at most one letter appears an odd number +of times. for example "ccjjc" and "abab" are wonderful, but "ab" is not. +given a string 'word' that consists of the first ten lowercase letters ('a' +through 'j') return the number of wonderful non-empty substrings in 'word'. +if the same substring appears multiple times in 'word', then count each +occurence separately. a substring is a contiguous sequence of character in a +string. +""" + + +class Solution(object): + def wonderfulSubstrings(self, word): + """ + :type word: str + :rtype: int + """ + cnt = [1] + [0] * 1024 + ans, curr = 0,0 + for c in word: + curr ^= 1 << (ord(c) - ord('a')) + ans += cnt[curr] + ans += sum(cnt[curr ^ (1 << i)] for i in range(10)) + cnt[curr] += 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.wonderfulSubstrings("aba")) # expect: 4 + print(obj.wonderfulSubstrings("aabb")) # expect: 9 + print(obj.wonderfulSubstrings("he")) # expect: 2 diff --git a/num_zero_filled_subarr.c b/num_zero_filled_subarr.c new file mode 100644 index 0000000..b8fd33d --- /dev/null +++ b/num_zero_filled_subarr.c @@ -0,0 +1,24 @@ +// 2348. Number of Zero-Filled Subarrays +#include <stdio.h> + +// given integer array 'nums', return number of subarrays filled with zero. a +// subarray is a contiguous non-empty sequence of elements from within an array + +long long zeroFilledSubarray(int *nums, int nums_size) { + long long ans = 0; + for (int i = 0, j = 0; i < nums_size; ++i) { + if (nums[i] != 0) + j = i + 1; + ans += i - j + 1; + } + return ans; +} + +int main() { + int n1[] = {1, 3, 0, 0, 2, 0, 0, 4}; + int n2[] = {0, 0, 0, 2, 0, 0}; + int n3[] = {2, 10, 2019}; + printf("%lld\n", zeroFilledSubarray(n1, 8)); // expect: 6 + printf("%lld\n", zeroFilledSubarray(n2, 6)); // expect: 9 + printf("%lld\n", zeroFilledSubarray(n3, 3)); // expect: 0 +} diff --git a/num_zero_filled_subarr.cpp b/num_zero_filled_subarr.cpp new file mode 100644 index 0000000..8ba45f3 --- /dev/null +++ b/num_zero_filled_subarr.cpp @@ -0,0 +1,29 @@ +// 2348. Number of Zero-Filled Subarrays +#include "leetcode.h" + +// given integer array 'nums', return number of subarrays filled with zero. a +// subarray is a contiguous non-empty sequence of elements from within an array + +class Solution { +public: + long long zeroFilledSubarray(vector<int> &nums) { + long long ans = 0; + short n = nums.size(); + for (int i = 0, j = 0; i < n; ++i) { + if (nums[i] != 0) + j = i + 1; + ans += i - j + 1; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 3, 0, 0, 2, 0, 0, 4}; + vector<int> n2 = {0, 0, 0, 2, 0, 0}; + vector<int> n3 = {2, 10, 2019}; + printf("%lld\n", obj.zeroFilledSubarray(n1)); // expect: 6 + printf("%lld\n", obj.zeroFilledSubarray(n2)); // expect: 9 + printf("%lld\n", obj.zeroFilledSubarray(n3)); // expect: 0 +} diff --git a/number_1bits.c b/number_1bits.c new file mode 100644 index 0000000..c4a9e48 --- /dev/null +++ b/number_1bits.c @@ -0,0 +1,29 @@ +// 191. Number of 1 Bits +#include "leetcode.h" + +/* + * write a function that takes the binary representation of an unsigned integer + * and returns number of '1' bits (also known as hamming weight). note that in + * some languages, such as java, there is no unsigned integer type. in this + * case, the input will be given as a signed integer type. it should not affect + * your implementation as the integers binary representation is the same, wehter + * it is signed or unsigned. in java, the compiler represents the signed + * integers using 2's complement notation. therefore in example 3, the input + * represents the signed integer -3 + */ + +int hammingWeight(uint32_t n) { + int cnt = 0; + while (n) { + if (n & 1) + cnt++; + n >>= 1; + } + return cnt; +} + +int main() { + printf("%d\n", hammingWeight(00000000000000000000000000001011)); // expect: 3 + printf("%d\n", hammingWeight(00000000000000000000000010000000)); // expect: 3 + printf("%d\n", hammingWeight(11111111111111111111111111111101)); // expect: 31 +} diff --git a/number_1bits.cpp b/number_1bits.cpp new file mode 100644 index 0000000..c8e0ac3 --- /dev/null +++ b/number_1bits.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + int hammingWeight(uint32_t n) { + int count = 0; + while (n > 0) { + if ((n & 1) > 0) + ++count; + n = n >> 1; + } + return count; + } +}; + +int main() { + uint32_t n = 00000000000000000000000000001011; + Solution obj; + cout << obj.hammingWeight(n); +} diff --git a/number_1bits.py b/number_1bits.py new file mode 100644 index 0000000..d0f335f --- /dev/null +++ b/number_1bits.py @@ -0,0 +1,31 @@ +# 191. Number of 1 Bits + +""" +write a function that takes the binary representation of an unsigned integer +and returns number of '1' bits (also known as hamming weight). note that in +some languages, such as java, there is no unsigned integer type. in this +case, the input will be given as a signed integer type. it should not affect +your implementation as the integers binary representation is the same, wehter +it is signed or unsigned. in java, the compiler represents the signed +integers using 2's complement notation. therefore in example 3, the input +represents the signed integer -3 +""" + +class Solution(object): + def hammingWeight(self, n): + """ + :type n: int + :rtype: int + """ + cnt = 0 + while n: + n &= (n - 1) + cnt += 1 + return cnt + + +if __name__ == "__main__": + obj = Solutin() + print(obj.hammingWeight(00000000000000000000000000001011)) # expect: 3 + print(obj.hammingWeight(00000000000000000000000010000000)) # expect: 1 + print(obj.hammingWeight(11111111111111111111111111111101)) # expect: 31 diff --git a/number_islands.cpp b/number_islands.cpp new file mode 100644 index 0000000..96b8e0b --- /dev/null +++ b/number_islands.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + int numIslands(vector<vector<char>> &grid) { + int islands = 0; + for (int i = 0; i < grid.size(); i++) { + for (int j = 0; j < grid[0].size(); j++) { + if (grid[i][j] == '1') { + dfs(grid, i, j); + ++islands; + } + } + } + return islands; + } + +private: + void dfs(vector<vector<char>> &grid, int i, int j) { + if (i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size()) + return; + if (grid[i][j] == '2' || grid[i][j] == '0') + return; + grid[i][j] = '2'; + dfs(grid, i + 1, j); + dfs(grid, i, j + 1); + dfs(grid, i - 1, j); + dfs(grid, i, j + 1); + } +}; diff --git a/number_provinces.c b/number_provinces.c new file mode 100644 index 0000000..f2cf499 --- /dev/null +++ b/number_provinces.c @@ -0,0 +1,48 @@ +// 547. Number of Provinces +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * dthere are 'n' cities. some of them are connected, while some are not. if + * city 'a' is connected directly with city 'b', and city 'b' is connected + * directly with city 'c', then city 'a' is connected indirectly with city 'c'. + * a province is a group of directly or indirectly connected cities and no other + * cities outside of the group. given an 'n x n' matrix 'is_connected' where + * 'is_connected[i][j] = 1' if the i'th city and the j'th city are directly + * connected, and 'is_connected[i][j] = 0' otherwise. return the total number of + * provinces + */ + +void dfs(int **is_connected, bool *vis, int n, int i) { + for (int j = 0; j < n; j++) { + if (is_connected[i][j] && !vis[j]) { + is_connected[i][j] = 0; + vis[j] = true; + dfs(is_connected, vis, n, j); + } + } +} + +int findCircleNum(int **is_connected, int is_connected_size, + int *is_connected_col_size) { + int ans = 0; + bool *vis = calloc(is_connected_size, sizeof(bool)); + for (int i = 0; i < is_connected_size; i++) { + if (is_connected[i][i] && !vis[i]) { + ans++; + vis[i] = true; + is_connected[i][i] = 0; + dfs(is_connected, vis, is_connected_size, i); + } + } + free(vis); + return ans; +} + +int main() { + int ic1[3][3] = {{1, 1, 0}, {1, 1, 0}, {0, 0, 1}}, ics1 = 3, *iccs1; + int ic2[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, ics2 = 3, *iccs2; + printf("%d\n", findCircleNum(ic1, ics1, iccs1)); // expect: 2 + printf("%d\n", findCircleNum(ic2, ics2, iccs2)); // expect: 3 +} diff --git a/number_provinces.cpp b/number_provinces.cpp new file mode 100644 index 0000000..e267854 --- /dev/null +++ b/number_provinces.cpp @@ -0,0 +1,41 @@ +// 547. Number of Provinces +#include "leetcode.h" + +/* + * dthere are 'n' cities. some of them are connected, while some are not. if + * city 'a' is connected directly with city 'b', and city 'b' is connected + * directly with city 'c', then city 'a' is connected indirectly with city 'c'. + * a province is a group of directly or indirectly connected cities and no other + * cities outside of the group. given an 'n x n' matrix 'is_connected' where + * 'is_connected[i][j] = 1' if the i'th city and the j'th city are directly + * connected, and 'is_connected[i][j] = 0' otherwise. return the total number of + * provinces + */ + +class Solution { + void dfs(int i, vvd(int) & is_connected, vector<bool> &vis) { + vis[i] = true; + for (int j = 0; j < vis.size(); j++) + if (i != j && is_connected[i][j] && !vis[j]) + dfs(j, is_connected, vis); + } + +public: + int findCircleNum(vvd(int) & is_connected) { + if (is_connected.empty()) + return 0; + int n = is_connected.size(), groups = 0; + vector<bool> vis(n, false); + for (int i = 0; i < vis.size(); i++) + groups += !vis[i] ? dfs(i, is_connected, vis), 1 : 0; + return groups; + } +}; + +int main() { + Solution obj; + vvd(int) ic1 = {{1, 1, 0}, {1, 1, 0}, {0, 0, 1}}; + vvd(int) ic2 = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + printf("%d\n", obj.findCircleNum(ic1)); // expect: 2 + printf("%d\n", obj.findCircleNum(ic2)); // expect: 3 +} diff --git a/number_steps_to_0.cpp b/number_steps_to_0.cpp new file mode 100644 index 0000000..2683dca --- /dev/null +++ b/number_steps_to_0.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + int numberOfSteps(int num) { + int steps = 0; + while (num) { + if (num % 2 == 0) + num /= 2, steps++; + else + num--, steps++; + } + return steps; + } +}; + +int main() { + Solution obj; + cout << obj.numberOfSteps(1043); +} diff --git a/number_submatrices_sum_target.cpp b/number_submatrices_sum_target.cpp new file mode 100644 index 0000000..db5a84f --- /dev/null +++ b/number_submatrices_sum_target.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + int numSubmatrixSumTarget(vector<vector<int>> &matrix, int target) { + int xLen = matrix[0].size(), yLen = matrix.size(), ans = 0; + unordered_map<int, int> res; + for (int i = 0; i < yLen; i++) + for (int j = 1; j < xLen; j++) + matrix[i][j] += matrix[i][j - 1]; + for (int j = 0; j < xLen; j++) + for (int k = j; k < xLen; k++) { + res.clear(); + res[0] = 1; + int cSum = 0; + for (int i = 0; i < yLen; i++) { + cSum += matrix[i][k] - (j ? matrix[i][j - 1] : 0); + ans += res.find(cSum - target) != res.end() ? res[cSum - target] : 0; + res[cSum]++; + } + } + return ans; + } +}; diff --git a/nums_same_consec_diff.c b/nums_same_consec_diff.c new file mode 100644 index 0000000..3098cf7 --- /dev/null +++ b/nums_same_consec_diff.c @@ -0,0 +1,55 @@ +// 967. Numbers With Same Consecutive Differences +#include "leetcode.h" + +/* + * given two integers 'n' and 'k' return an array of all the integers of length + * 'n' where the difference between every two consecutive digits is 'k'. you may + * return the answer in any order. note that the integers should not have + * leading zeros. integers as 02 and 043 are not allowed. + */ + +void dfs(int *res, int *idx, int val, int digit, int k) { + if (!digit) { + res[*idx] = val; + (*idx)++; + return; + } + if (val % 10 + k < 10) + dfs(res, idx, val * 10 + (val % 10 + k), digit - 1, k); + if ((val % 10) - k >= 0) + dfs(res, idx, val * 10 + (val % 10 - k), digit - 1, k); +} + +int *numsSameConsecDiff(int n, int k, int *returnSize) { + if (!k) { + int *ans = (int *)malloc(9 * sizeof(int)); + for (int i = 1; i <= 9; i++) { + int val = i; + for (int j = 0; j < n - 1; j++) + val = val * 10 + i; + ans[i - 1] = val; + } + *returnSize = 9; + return ans; + } + int *ans = (int *)malloc(9 * pow(2, n) * sizeof(int)), idx = 0; + for (int i = 1; i <= 9; i++) + dfs(ans, &idx, i, n - 1, k); + *returnSize = idx; + return ans; +} + +int main() { + int rs1, rs2; + int *nscd1 = numsSameConsecDiff(3, 7, &rs1); + int *nscd2 = numsSameConsecDiff(2, 1, &rs2); + for (int i = 0; i < rs1; i++) + printf("%d ", nscd1[i]); // expect: 181 292 707 818 929 + printf("\n"); + for (int i = 0; i < rs2; i++) + printf( + "%d ", + nscd2[i]); // expect: 10,12,21,23,32,34,43,45,54,56,65,67,76,78,87,89,98 + printf("\n"); + free(nscd1), free(nscd2); +} diff --git a/nums_same_consec_diff.py b/nums_same_consec_diff.py new file mode 100644 index 0000000..bb4646c --- /dev/null +++ b/nums_same_consec_diff.py @@ -0,0 +1,32 @@ +# 967. numbers With Same Consecutive Differences + +""" +given two integers 'n' and 'k' return an array of all the integers of length +'n' where the difference between every two consecutive digits is 'k'. you may +return the answer in any order. note that the integers should not have +leading zeros. integers as 02 and 043 are not allowed. +""" + + +class Solution(object): + def numsSameConsecDiff(self, n, k): + """ + :type n: int + :type k: int + :rtype: List[int] + """ + curr = range(1, 10) + for i in range(n - 1): + curr = { + x * 10 + y + for x in curr + for y in [x % 10 + k, x % 10 - k] + if 0 <= y <= 9 + } + return list(curr) + + +if __name__ == "__main__": + obj = Solution() + print(obj.numsSameConsecDiff(3, 7)) + print(obj.numsSameConsecDiff(2, 1)) diff --git a/odd_even_linke_list.cpp b/odd_even_linke_list.cpp new file mode 100644 index 0000000..4ee4bac --- /dev/null +++ b/odd_even_linke_list.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + ListNode *oddEvenList(ListNode *head) { + ListNode *odd = NULL, *headOdd = NULL, *even = NULL, *headEven = NULL; + if (!head || !head->next || !head->next->next) + return head; + odd = head; + headOdd = odd; + even = head->next; + headEven = even; + while (even && even->next) { + odd->next = odd->next->next; + even->next = even->next->next; + odd = odd->next; + even = even->next; + } + odd->next = headEven; + return headOdd; + } +}; diff --git a/odd_even_linke_list.rs b/odd_even_linke_list.rs new file mode 100644 index 0000000..89e96c1 --- /dev/null +++ b/odd_even_linke_list.rs @@ -0,0 +1,38 @@ +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct ListNode { + pub val: i32, + pub next: Option<Box<ListNode>> +} + +impl ListNode { + #[inline] + fn new(val: i32) -> Self { + ListNode { + next: None, + val + } + } +} + +impl Solution { + pub fn odd_even_list(mut head: Option<Box<ListNode>>) -> Option<Box<ListNode>> { + let mut odd_dummy_head = ListNode::new(-1); + let mut even_dummy_head = ListNode::new(-1); + let mut odd_curr = &mut odd_dummy_head; + let mut even_curr = &mut even_dummy_head; + let mut is_even = false; + while let Some(mut node) = head { + head = std::mem::replace(&mut node.next, None); + if is_even { + even_curr.next = Some(node); + even_curr = even_curr.next.as_mut().unwrap(); + } else { + odd_curr.next = Some(node); + odd_curr = odd_curr.next.as_mut().unwrap(); + } + is_even = !is_even; + } + odd_curr.next = even_dummy_head.next; + odd_dummy_head.next + } +} diff --git a/ones_and_zeroes.cpp b/ones_and_zeroes.cpp new file mode 100644 index 0000000..851f1e8 --- /dev/null +++ b/ones_and_zeroes.cpp @@ -0,0 +1,36 @@ +#include "leetcode.h" +#include <vector> + +class Solution { +public: + int findMaxForm(vector<string> &strs, int m, int n) { + vector<pair<int, int>> vp; + for (auto i : strs) { + int one = 0, zero = 0; + for (auto j : i) + (j == '1') ? one++ : zero++; + vp.push_back({one, zero}); + } + return helper(vp, 0, m, n); + } + +private: + int helper(vector<pair<int, int>> &vp, int idx, int m, int n) { + int j = vp.size(); + if (idx == j || (m == 0 && n == 0)) + return 0; + if (vp[idx].first > n || vp[idx].second > m) + return helper(vp, idx + 1, m, n); + int include = + 1 + helper(vp, idx + 1, n - vp[idx].first, m - vp[idx].second); + int exclude = helper(vp, idx + 1, m, n); + return max(include, exclude); + } +}; + +int main() { + Solution obj; + vector<string> strs = {"10", "0001", "111001", "1", "0"}; + int m = 5, n = 3; + cout << obj.findMaxForm(strs, m, n); +} diff --git a/online_stock_span.cpp b/online_stock_span.cpp new file mode 100644 index 0000000..6d56038 --- /dev/null +++ b/online_stock_span.cpp @@ -0,0 +1,25 @@ +#include "leetcode.h" + +class StockSpanner { +public: + stack<pair<int, int>> storage; + int idx = 0; + int next(int price) { + if (storage.empty()) { + storage.push({price, idx++}); + return 1; + } else { + while (!storage.empty() && price >= storage.top().first) + storage.pop(); + int ans = 0; + ans = storage.empty() ? idx + 1 : idx - storage.top().second; + storage.push({price, idx++}); + return ans; + } + } +}; + +int main() { + StockSpanner *obj = new StockSpanner(); + int param_1 = obj->next(price); +} diff --git a/online_stock_span.rs b/online_stock_span.rs new file mode 100644 index 0000000..a1818ff --- /dev/null +++ b/online_stock_span.rs @@ -0,0 +1,34 @@ +struct Span { + price: i32, + days: i32 +} + +struct StockSpanner { + spans: Vec<Span> +} + +impl StockSpanner { + fn new() -> Self { + StockSpanner { + spans: Vec::new() + } + } + fn next(&mut self, price: i32) -> i32 { + let mut days = 1; + while let Some(span) = self.spans.last() { + if span.price <= price { + days += span.days; + self.spans.pop(); + } else { + break; + } + } + self.spans.push(Span{price, days}); + days + } +} + +fn main() { + let obj = StockSpanner::new(); + let ret_1: i32 = obj.next(price); +} diff --git a/oob_path.c b/oob_path.c new file mode 100644 index 0000000..fb33dfa --- /dev/null +++ b/oob_path.c @@ -0,0 +1,59 @@ +// 576. Out of Boundary Paths +#include "leetcode.h" + +/* + * there is an 'm * n' grid with a ball. the ball is initially at the position + * '[start_row, start_column]'. you are allowed to move the ball to one of the + * four adjacent cells in the grid (possible out of the grid crossing the grid + * boundary). you can apply at most 'max_move' moves to the ball. given the give + * integers, 'm', 'n', 'max_move', 'start_row', 'and start_column', return the + * number of paths to move the ball out of the grid boundary. since the answer + * can be very large, return it modulo 10^9+7 + */ + +void dfs(int m, int n, int max, int x, int y, int k, long *cnt, long ***cache) { + if (x >= m || x < 0 || y >= n || y < 0) { + (*cnt)++; + (*cnt) %= 1000000007; + return; + } + if (cache[x][y][k] != -1) { + (*cnt) = cache[x][y][k]; + return; + } + if (k == max) + return; + long a = 0, b = 0, c = 0, d = 0; + dfs(m, n, max, x + 1, y, k + 1, &a, cache); + dfs(m, n, max, x - 1, y, k + 1, &b, cache); + dfs(m, n, max, x, y + 1, k + 1, &c, cache); + dfs(m, n, max, x, y - 1, k + 1, &d, cache); + cache[x][y][k] = a + b + c + d; + cache[x][y][k] %= 1000000007; + (*cnt) = cache[x][y][k]; +} + +int findPaths(int m, int n, int max_move, int start_row, int start_column) { + if (!max_move) + return 0; + long ***cache = (long ***)malloc(m * sizeof(long **)); + for (int i = 0; i < m; i++) { + cache[i] = (long **)malloc(n * sizeof(long *)); + for (int j = 0; j < n; j++) { + cache[i][j] = (long *)malloc((max_move + 1) * sizeof(long)); + memset(cache[i][j], -1, (max_move + 1) * sizeof(long)); + } + } + long cnt = 0; + dfs(m, n, max_move, start_row, start_column, 0, &cnt, cache); + for (int i = 0; i < m; i++) + for (int j = 0; j < n; j++) + free(cache[i][j]); + free(cache); + return cnt; +} + +int main() { + printf("%d\n", findPaths(2, 2, 2, 0, 0)); // expect: 6 + printf("%d\n", findPaths(1, 3, 3, 0, 1)); // expect: 12 +} diff --git a/oob_path.py b/oob_path.py new file mode 100644 index 0000000..63a9641 --- /dev/null +++ b/oob_path.py @@ -0,0 +1,46 @@ +# 576. Out of Boundary Paths + +""" +there is an 'm n' grid with a ball. the ball is initially at the position +'[start_row, start_column]'. you are allowed to move the ball to one of the +four adjacent cells in the grid (possible out of the grid crossing the grid +boundary). you can apply at most 'max_move' moves to the ball. given the give +integers, 'm', 'n', 'max_move', 'start_row', 'and start_column', return the +number of paths to move the ball out of the grid boundary. since the answer +can be very large, return it modulo 10^9+7 +""" + + +class Solution(object): + def findPaths(self, m, n, maxMove, startRow, startColumn): + """ + :type m: int + :type n: int + :type maxMove: int + :type startRow: int + :type startColumn: int + :rtype: int + """ + dp = [[[-1] * (maxMove + 1) for _ in range(n + 1)] for _ in range(m + 1)] + + def solve(i, j, maxMove): + if maxMove < 0: + return 0 + if i < 0 or i >= m or j < 0 or j >= n: + return 1 + if dp[i][j][maxMove] != -1: + return dp[i][j][maxMove] + a = solve(i - 1, j, maxMove - 1) + b = solve(i + 1, j, maxMove - 1) + c = solve(i, j - 1, maxMove - 1) + d = solve(i, j + 1, maxMove - 1) + dp[i][j][maxMove] = a + b + c + d + return dp[i][j][maxMove] + + return solve(startRow, startColumn, maxMove) % 1000000007 + + +if __name__ == "__main__": + obj = Solution() + print(obj.findPaths(m=2, n=2, maxMove=2, startRow=0, startColumn=0)) # expect: 6 + print(obj.findPaths(m=1, n=3, maxMove=3, startRow=0, startColumn=1)) # expect: 12 diff --git a/open_the_lock.c b/open_the_lock.c new file mode 100644 index 0000000..311d1fd --- /dev/null +++ b/open_the_lock.c @@ -0,0 +1,97 @@ +// 752. Open the Lock +#include "leetcode.h" + +/* + * you have a lock in front of you with 4 circular wheels. each wheel has 10 + * slots 0-9. the wheels can rotate freely and wrap around. the lock initially + * starts at 0000, a sting representing the state of the 4 wheels. given a list + * of 'deadends', meaning the lock displays any of these codes, the wheels of + * the lock will stop turning and you will be unable to open it. given 'target' + * representing the value of the wheels that will unlock the lock, return the + * minimum total number of turns required to open the lock, or -1 if it is + * impossible + */ + +#define SIZE 10000 +char queue[SIZE][4] = {0}; +int front = -1; +int tail = -1; + +int is_empty() { return (tail == front) ? 1 : 0; } + +void enqueue(char *wheel) { + front++; + if (front == SIZE) + front = 0; + memcpy(&queue[front][0], wheel, sizeof(char) * 4); +} + +char *dequeue() { + if (is_empty() == 1) + return NULL; + tail++; + if (tail == SIZE) + tail = 0; + return &queue[tail][0]; +} + +int convert_wheels_to_int(char *wheels) { + return (wheels[3] - '0') + (wheels[2] - '0') * 10 + (wheels[1] - '0') * 100 + + (wheels[0] - '0') * 1000; +} + +int openLock(char **deadends, int deadendsSIZE, char *target) { + if (!convert_wheels_to_int(target)) + return 0; + int visited[SIZE] = {0}; + int hop[SIZE] = {0}; + int deadends_int; + front = -1; + tail = -1; + for (int d = 0; d < deadendsSIZE; d++) { + deadends_int = convert_wheels_to_int(deadends[d]); + if (!deadends_int) + return -1; + else + visited[deadends_int] = 1; + } + int target_int = convert_wheels_to_int(target); + enqueue("0000"); + hop[0] = 0; + visited[0] = 1; + hop[target_int] = -1; + int current_wheel_int; + char *current_wheel; + char neighbour[4]; + while (is_empty() != 1) { + if (hop[target_int] != -1) + return hop[target_int]; + current_wheel = dequeue(); + current_wheel_int = convert_wheels_to_int(current_wheel); + for (int i = 0; i < 4; i++) { + memcpy(&neighbour[0], current_wheel, sizeof(char) * 4); + neighbour[i] = neighbour[i] == '9' ? '0' : neighbour[i] + 1; + if (visited[convert_wheels_to_int(neighbour)] == 0) { + enqueue(neighbour); + hop[convert_wheels_to_int(neighbour)] = hop[current_wheel_int] + 1; + visited[convert_wheels_to_int(neighbour)] = 1; + } + memcpy(&neighbour[0], current_wheel, sizeof(char) * 4); + neighbour[i] = neighbour[i] == '0' ? '9' : neighbour[i] - 1; + if (visited[convert_wheels_to_int(neighbour)] == 0) { + enqueue(neighbour); + hop[convert_wheels_to_int(neighbour)] = hop[current_wheel_int] + 1; + visited[convert_wheels_to_int(neighbour)] = 1; + } + } + } + return hop[target_int]; +} +int main() { + char *d1[5][4] = {"0201", "0101", "0102", "1212", "2002"}; + char *d2[8][4] = {"8887", "8889", "8878", "8898", + "8788", "8988", "7888", "9888"}; + char *t1 = "0202", *t2 = "8888"; + printf("%d\n", openLock((char **)d1, 5, t1)); // expect: 6 + printf("%d\n", openLock((char **)d2, 8, t2)); // expect: -1 +} diff --git a/open_the_lock.py b/open_the_lock.py new file mode 100644 index 0000000..2a0fc2b --- /dev/null +++ b/open_the_lock.py @@ -0,0 +1,60 @@ +# 752. Open the Lock +from collections import deque + +""" +you have a lock in front of you with 4 circular wheels. each wheel has 10 +slots 0-9. the wheels can rotate freely and wrap around. the lock initially +starts at 0000, a sting representing the state of the 4 wheels. given a list +of 'deadends', meaning the lock displays any of these codes, the wheels of +the lock will stop turning and you will be unable to open it. given 'target' +representing the value of the wheels that will unlock the lock, return the +minimum total number of turns required to open the lock, or -1 if it is +impossible +""" + + +class Solution(object): + def neighbours(self, code): + for i in range(4): + x = int(code[i]) + for diff in (-1, 1): + y = (x + diff + 10) % 10 + yield code[:i] + str(y) + code[i + 1 :] + + def openLock(self, deadends, target): + """ + :type deadends: List[str] + :type target: str + :rtype: int + """ + dead_set = set(deadends) + if "0000" in dead_set: + return -1 + q = deque(["0000"]) + steps = 0 + while q: + for _ in range(len(q)): + curr = q.popleft() + if curr == target: + return steps + for i in self.neighbours(curr): + if i in dead_set: + continue + dead_set.add(i) + q.append(i) + steps += 1 + return -1 + + +if __name__ == "__main__": + obj = Solution() + print( + obj.openLock(deadends=["0201", "0101", "0102", "1212", "2002"], target="0202") + ) + print(obj.openLock(deadends=["8888"], target="0009")) + print( + obj.openLock( + deadends=["8887", "8889", "8878", "8898", "8788", "8988", "7888", "9888"], + target="8888", + ) + ) diff --git a/optimal_partition_string.c b/optimal_partition_string.c new file mode 100644 index 0000000..755574d --- /dev/null +++ b/optimal_partition_string.c @@ -0,0 +1,37 @@ +// 2405. Optimal Partition of String +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a string 's', partition the string into one or more substrings such + * that the characters in each substring are unique. that is, no letter appears + * in a single substring more than once. return the minimum number of substrings + * in such a partition note that each character should belong to exactly one + * substring in a partition + */ + +int partitionString(char *s) { + int n = strlen(s), ans = 0; + int *post = malloc(26 * sizeof(int)); + for (int i = 0; i < 26; i++) + post[i] = -1; + int start = 0, last = 0; + for (int i = 0; i < n; i++) { + if (post[s[i] - 'a'] == -1 || post[s[i] - 'a'] < start) + last++; + else { + ans++; + start = i; + last = i; + } + post[s[i] - 'a'] = i; + } + return ans + 1; +} + +int main() { + char s1[] = {"abacaba"}, s2[] = {"ssssss"}; + printf("%d\n", partitionString(s1)); // expect: 4 + printf("%d\n", partitionString(s2)); // expect: 6 +} diff --git a/optimal_partition_string.cpp b/optimal_partition_string.cpp new file mode 100644 index 0000000..e39bd62 --- /dev/null +++ b/optimal_partition_string.cpp @@ -0,0 +1,31 @@ +// 2405. Optimal Partition of String +#include "leetcode.h" + +/* + * given a string 's', partition the string into one or more substrings such + * that the characters in each substring are unique. that is, no letter appears + * in a single substring more than once. return the minimum number of substrings + * in such a partition note that each character should belong to exactly one + * substring in a partition + */ + +class Solution { +public: + int partitionString(string s) { + int cnt[26] = {}, ans = 1; + for (int i = 0; i < s.size(); ++i) { + if (cnt[s[i] - 'a']) { + ++ans; + fill(begin(cnt), end(cnt), 0); + } + ++cnt[s[i] - 'a']; + } + return ans; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.partitionString("abacaba")); // expect: 4 + printf("%d\n", obj.partitionString("ssssss")); // expect: 6 +} diff --git a/orderly_queue.cpp b/orderly_queue.cpp new file mode 100644 index 0000000..23053d2 --- /dev/null +++ b/orderly_queue.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + string orderlyQueue(string s, int k) { + if (k > 1) { + sort(s.begin(), s.end()); + return s; + } + string ans = s; + for (int i = 1; i < s.size(); i++) + ans = min(ans, s.substr(i) + s.substr(0, i)); + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.orderlyQueue("cba", 1); +} diff --git a/orderly_queue.rs b/orderly_queue.rs new file mode 100644 index 0000000..0931d7b --- /dev/null +++ b/orderly_queue.rs @@ -0,0 +1,22 @@ +struct Solution; + +impl Solution { + pub fn orderly_queue(s: String, k: i32) -> String { + if k == 1 { + let ss = s.chars().chain(s.chars()).collect::<Vec<_>>(); + let mut v = ss.windows(s.len()).collect::<Vec<_>>(); + v.sort(); + v[0].iter().copied().collect() + } else { + let mut v = s.chars().collect::<Vec<_>>(); + v.sort(); + v.iter().collect() + } + } +} + +fn main() { + let s = String::from("cba"); + let k = 1; + print!("{}", Solution::orderly_queue(s, k)); +} diff --git a/out_of_bounds_paths.cpp b/out_of_bounds_paths.cpp new file mode 100644 index 0000000..fa19333 --- /dev/null +++ b/out_of_bounds_paths.cpp @@ -0,0 +1,35 @@ +#include "leetcode.h" + +class Solution { +public: + int findPaths(int m, int n, int maxMove, int startRow, int startColumn) { + if (!maxMove) + return 0; + vector<vector<int>> curr(m + 2, vector<int>(n + 2)); + vector<vector<int>> last(m + 2, vector<int>(n + 2)); + for (int i = 1; i <= m; i++) { + curr[i][1]++; + curr[i][n]++; + } + for (int j = 1; j <= n; j++) { + curr[1][j]++; + curr[m][j]++; + } + int ans = curr[startRow + 1][startColumn + 1]; + for (int d = 1; d < maxMove; d++) { + curr.swap(last); + for (int i = 1; i <= m; i++) + for (int j = 1; j <= n; j++) + curr[i][j] = (int)(((long)last[i - 1][j] + last[i + 1][j] + + last[i][j - 1] + last[i][j + 1]) % + 1000000007L); + ans = (ans + curr[startRow + 1][startColumn + 1]) % 1000000007L; + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.findPaths(2, 2, 2, 0, 0); +} diff --git a/pacific_atlantic_water_flow.cpp b/pacific_atlantic_water_flow.cpp new file mode 100644 index 0000000..1bfc673 --- /dev/null +++ b/pacific_atlantic_water_flow.cpp @@ -0,0 +1,38 @@ +#include "leetcode.h" + +class Solution { +public: + vvd(int) pacificAtlantic(vvd(int) & heights) { + n = heights.size(); + m = heights[0].size(); + vvd(bool) flag1(n, vector<bool>(m)), flag2(n, vector<bool>(m)); + vvd(int) ans; + for (int i = 0; i < n; i++) + dfs(heights, flag1, i, 0); + for (int i = 1; i < m; i++) + dfs(heights, flag1, 0, i); + for (int i = 0; i < n; i++) + dfs(heights, flag2, i, m - 1); + for (int i = 0; i < m - 1; i++) + dfs(heights, flag2, n - 1, i); + for (int i = 0; i < n; i++) + for (int j = 0; j < m; j++) + if (flag1[i][j] && flag2[i][j]) + ans.push_back({i, j}); + return ans; + } + +private: + int n, m; + void dfs(vvd(int) & grid, vvd(bool) & flag, int x, int y) { + flag[x][y] = true; + if (x - 1 >= 0 && !flag[x - 1][y] && grid[x - 1][y] >= grid[x][y]) + dfs(grid, flag, x - 1, y); + if (x + 1 < n && !flag[x + 1][y] && grid[x + 1][y] >= grid[x][y]) + dfs(grid, flag, x + 1, y); + if (y - 1 >= 0 && !flag[x][y - 1] && grid[x][y - 1] >= grid[x][y]) + dfs(grid, flag, x, y - 1); + if (y + 1 < m && !flag[x][y + 1] && grid[x][y + 1] >= grid[x][y]) + dfs(grid, flag, x, y + 1); + } +}; diff --git a/paint_house3.cpp b/paint_house3.cpp new file mode 100644 index 0000000..1185109 --- /dev/null +++ b/paint_house3.cpp @@ -0,0 +1,34 @@ +#include "leetcode.h" + +class Solution { +public: + int minCost(vector<int> &houses, vector<vector<int>> &cost, int m, int n, + int target) { + int INF = 1000000; + vector<vector<vector<int>>> dp( + m, vector<vector<int>>(target + 1, vector<int>(n, INF))); + for (int i = 1; i <= n; i++) { + if (houses[0] == i) + dp[0][1][i - 1] = 0; + else if (!houses[0]) + dp[0][1][i - 1] = cost[0][i - 1]; + } + for (int i = 1; i < m; i++) { + for (int k = 1; k <= min(target, i + 1); k++) { + for (int j = 1; j <= n; j++) { + if (houses[i] && j != houses[i]) + continue; + int same = dp[i - 1][k][j - 1]; + int diff = INF; + for (int r = 1; r <= n; r++) + if (r != j) + diff = min(diff, dp[i - 1][k - 1][r - 1]); + int paintCost = cost[i][j - 1] * int(!houses[i]); + dp[i][k][j - 1] = min(same, diff) + paintCost; + } + } + } + int ans = *min_element(dp.back().back().begin(), dp.back().back().end()); + return (ans < INF) ? ans : -1; + } +}; diff --git a/painting_grid_three_colour.cpp b/painting_grid_three_colour.cpp new file mode 100644 index 0000000..11fb014 --- /dev/null +++ b/painting_grid_three_colour.cpp @@ -0,0 +1,58 @@ +// 1931. Painting a Grid With Three Different Colors +#include "leetcode.h" + +/* + * given two integers 'm' and 'n'. consider an 'm x n' grid where each cell is + * initially white. you can painteach cell red, green, or blue. all cells must + * be painted. return the number of ways to colour the grid with no two adjacent + * cells having the same colour. + */ + +class Solution { + int memo[1000][1024] = {}; + vector<int> nei_memo[1024] = {}; + int m, n, mod = 1e9 + 7; + int dp(int c, int prev) { + if (c == n) + return 1; + if (memo[c][prev]) + return memo[c][prev]; + int res = 0; + for (int nei : neighbours(prev)) + res = (res + dp(c + 1, nei)) % mod; + return memo[c][prev] = res; + } + vector<int> neighbours(int prev) { + if (!nei_memo[prev].empty()) + return nei_memo[prev]; + dfs(0, prev, 0, nei_memo[prev]); + return nei_memo[prev]; + } + void dfs(int r, int prev, int curr, vector<int> &out) { + if (r == m) { + out.push_back(curr); + return; + } + for (int i = 0; i <= 3; i++) + if (get_colour(prev, r) != i && (!r || get_colour(curr, r - 1) != i)) + dfs(r + 1, prev, set_colour(curr, r, i), out); + } + int get_colour(int mask, int pos) { return (mask >> (2 * pos)) & 3; } + int set_colour(int mask, int pos, int colour) { + return mask | (colour << (2 * pos)); + } + +public: + int colorTheGrid(int m, int n) { + this->m = m; + this->n = n; + return dp(0, 0); + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.colorTheGrid(1, 1)); // expect: 3 + printf("%d\n", obj.colorTheGrid(1, 2)); // expect: 6 + printf("%d\n", obj.colorTheGrid(5, 5)); // expect: 580986 +} diff --git a/painting_walls.cpp b/painting_walls.cpp new file mode 100644 index 0000000..adcd32b --- /dev/null +++ b/painting_walls.cpp @@ -0,0 +1,50 @@ +// 2742. Painting the Walls +#include "leetcode.h" + +/* + * you are given two 0-indexed integer arrays, cost and time of size n + * representing the costs and the time taken to paint n walls respectively. + * there are two painters available: + * - a paid painter that paints the i'th wall in 'time[i]' units of time and + * takes 'cost[i]' units of money + * - a free painter that paints any wall in 1 unit of time at a cost of 0. but + * the free painter can only be used if the paid painter is already occupied + * return the minimum amount of money required to paint the 'n' walls. + */ + +class Solution { +public: + int paintWalls(vector<int> &cost, vector<int> &time) { + this->n = cost.size(); + vvd(int) memo(n, vector<int>(n + 1)); + this->cost = cost; + this->time = time; + return dfs(0, n, memo); + } + +private: + int memo[501][501]; + vector<int> cost; + vector<int> time; + int n; + int dfs(int curr, int left_wall, vvd(int) & memo) { + if (left_wall <= 0) + return 0; + if (curr == n) + return 1e9; + if (memo[curr][left_wall] != -1) + return memo[curr][left_wall]; + int paid = cost[curr] + dfs(curr + 1, left_wall - 1 - time[curr], memo); + int free = dfs(curr + 1, left_wall, memo); + memo[curr][left_wall] = min(paid, free); + return memo[curr][left_wall]; + } +}; + +int main() { + Solution obj; + vector<int> c1 = {1, 2, 3, 2}, c2 = {2, 3, 4, 2}; + vector<int> t1 = {1, 2, 3, 2}, t2 = {1, 1, 1, 1}; + printf("%d\n", obj.paintWalls(c1, t1)); // expect: 3 + printf("%d\n", obj.paintWalls(c2, t2)); // expect: 4 +} diff --git a/painting_walls.py b/painting_walls.py new file mode 100644 index 0000000..5661285 --- /dev/null +++ b/painting_walls.py @@ -0,0 +1,31 @@ +# 2742. Painting the Walls + +""" +you are given two 0-indexed integer arrays, cost and time of size n +representing the costs and the time taken to paint n walls respectively. +there are two painters available: +- a paid painter that paints the i'th wall in 'time[i]' units of time and +takes 'cost[i]' units of money +- a free painter that paints any wall in 1 unit of time at a cost of 0. but +the free painter can only be used if the paid painter is already occupied +return the minimum amount of money required to paint the 'n' walls. +""" + + +class Solution(object): + def paintWalls(self, cost, time): + n = len(cost) + dp = [[0x3F3F3F3F3F3F for i in range(n + 1)] for j in range(n + 1)] + dp[0][0] = 0 + for i in range(n): + for j in range(n + 1): + t = min(n, j + time[i] + 1) + dp[i + 1][j] = min(dp[i + 1][j], dp[i][j]) + dp[i + 1][t] = min(dp[i + 1][t], dp[i][j] + cost[i]) + return dp[n][n] + + +if __name__ == "__main__": + obj = Solution() + print(obj.paintWalls([1, 2, 3, 2], [1, 2, 3, 2])) # expect: 3 + print(obj.paintWalls([2, 3, 4, 2], [1, 1, 1, 1])) # expect: 4 diff --git a/pairs_spells_potions.c b/pairs_spells_potions.c new file mode 100644 index 0000000..6981016 --- /dev/null +++ b/pairs_spells_potions.c @@ -0,0 +1,58 @@ +// 2300. Successful Pairs of Spells and Potions +#include <stdio.h> +#include <stdlib.h> + +/* + * given two positive integer arrays 'spells' and 'potions', of length n and m + * respectively where 'spells[i]' represents the strength of the i'th spell and + * 'potions[j] represents the strength of the j'th potion. also given an integer + * success. a spell and potion pair is considered successful if the product of + * their strengths is at least 'success'. return an integer array 'pairs' of + * lengthn where 'pairs[i]' is the number of potions that will form a successful + * pair with the i'th spell. + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int find_successful(int *potions, int potions_size, double val) { + int left = 0, right = potions_size - 1, mid; + while (left < right) { + mid = (left + right) >> 1; + if ((double)potions[mid] >= val) + right = mid; + else + left = mid + 1; + } + if ((double)potions[left] >= val) + return potions_size - left; + else + return 0; +} + +int *successfulPairs(int *spells, int spells_size, int *potions, + int potions_size, long long success, int *return_size) { + int i, j; + qsort(potions, potions_size, sizeof(int), cmp); + double *spells_float = malloc(spells_size * sizeof(double)); + for (i = 0; i < spells_size; i++) + spells_float[i] = 1.0 * success / spells[i]; + *return_size = spells_size; + int *ans = malloc(spells_size * sizeof(int)); + for (i = 0; i < spells_size; i++) + ans[i] = find_successful(potions, potions_size, spells_float[i]); + free(spells_float); + return ans; +} + +int main() { + int s1[] = {5, 1, 3}, s2[] = {3, 1, 2}; + int p1[] = {1, 2, 3, 4, 5}, p2[] = {8, 5, 8}; + int rs1[] = {3}, rs2[] = {3}; + int *ex1 = successfulPairs(s1, 3, p1, 5, 7, rs1); + int *ex2 = successfulPairs(s2, 3, p2, 3, 16, rs2); + for (int i = 0; i < 3; i++) + printf("%d ", ex1[i]); // expect: 4 0 3 + printf("\n"); + for (int i = 0; i < 3; i++) + printf("%d ", ex2[i]); // expect: 2 0 2 +} diff --git a/pairs_spells_potions.cpp b/pairs_spells_potions.cpp new file mode 100644 index 0000000..255b4a0 --- /dev/null +++ b/pairs_spells_potions.cpp @@ -0,0 +1,45 @@ +// 2300. Successful Pairs of Spells and Potions +#include "leetcode.h" + +/* + * given two positive integer arrays 'spells' and 'potions', of length n and m + * respectively where 'spells[i]' represents the strength of the i'th spell and + * 'potions[j] represents the strength of the j'th potion. also given an integer + * success. a spell and potion pair is considered successful if the product of + * their strengths is at least 'success'. return an integer array 'pairs' of + * lengthn where 'pairs[i]' is the number of potions that will form a successful + * pair with the i'th spell. + */ + +class Solution { +public: + vector<int> successfulPairs(vector<int> &spells, vector<int> &potions, + long long success) { + int m = potions.size(); + vector<int> ans; + sort(potions.begin(), potions.end()); + for (auto i : spells) { + int left = 0, right = m - 1, mid; + while (left <= right) { + mid = (left + right) >> 1; + if ((long long)i * potions[mid] >= success) + right = mid - 1; + else + left = mid + 1; + } + ans.push_back(m - left); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> s1 = {5, 1, 3}, s2 = {3, 1, 2}; + vector<int> p1 = {1, 2, 4, 4, 5}, p2 = {8, 5, 8}; + for (auto i : obj.successfulPairs(s1, p1, 7)) + printf("%d ", i); // expec: 4 0 3 + printf("\n"); + for (auto i : obj.successfulPairs(s2, p2, 16)) + printf("%d ", i); // expec: 2 0 2 +} diff --git a/palindrome_linked_list.c b/palindrome_linked_list.c new file mode 100644 index 0000000..5477736 --- /dev/null +++ b/palindrome_linked_list.c @@ -0,0 +1,54 @@ +// 234. Palindrome Linked List +#include "leetcode.h" + +/* + * given the head of a signly linked list return true if it is a palindrome or + * false otherwise. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +struct ListNode *reverse_list(struct ListNode *head) { + if (!head || !head->next) + return head; + struct ListNode *tmp = reverse_list(head->next); + head->next->next = head; + head->next = NULL; + return tmp; +} + +bool isPalindrome(struct ListNode *head) { + if (!head) + return 1; + struct ListNode *iter = head, *reversed_half_list; + int cnt = 0; + bool flag = 1; + while (iter) { + cnt++; + iter = iter->next; + } + iter = head; + for (int i = 0; i < cnt / 2; i++) + iter = iter->next; + if (!(cnt % 2)) + reversed_half_list = reverse_list(iter); + else if (iter->next) + reversed_half_list = reverse_list(iter->next); + iter = head; + if (cnt == 1) + return 1; + if (!reversed_half_list) + return 0; + while (iter && reversed_half_list) { + if (iter->val != reversed_half_list->val) { + flag = 0; + break; + } + iter = iter->next; + reversed_half_list = reversed_half_list->next; + } + return flag; +} diff --git a/palindrome_linked_list.cpp b/palindrome_linked_list.cpp new file mode 100644 index 0000000..1b08a0c --- /dev/null +++ b/palindrome_linked_list.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class Solution { +public: + bool isPalindrome(ListNode *head) { + ListNode *slow = head, *fast = head, *prev, *temp; + while (fast && fast->next) { + slow = slow->next; + fast = fast->next->next; + } + prev = slow; + slow = slow->next; + prev->next = NULL; + while (slow) { + temp = slow->next; + slow->next = prev; + prev = slow; + slow = temp + } + fast = head; + slow = prev; + while (slow) { + if (fast->val != slow->val) + return false; + else { + fast = fast->next; + slow = slow->next; + } + } + return true; + } +}; diff --git a/palindrome_linked_list.py b/palindrome_linked_list.py new file mode 100644 index 0000000..85c40c3 --- /dev/null +++ b/palindrome_linked_list.py @@ -0,0 +1,39 @@ +# 234. Palindrome Linked List + +""" +given the head of a signly linked list return true if it is a palindrome or +false otherwise. +""" + + +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, val=0, next=None): + self.val = val + self.next = next + + +class Solution(object): + def isPalindrome(self, head): + """ + :type head: ListNode + :rtype: bool + """ + slow, fast, prev = head, head, None + while fast and fast.next: + slow, fast = slow.next, fast.next.next + prev, slow, prev.next = slow, slow.next, None + while slow: + slow.next, prev, slow = prev, slow, slow.next + fast, slow = head, prev + while slow: + if fast.val != slow.val: + return False + fast, slow = fast.next, slow.next + return True + + +if __name__ == "__main__": + obj = Solution() + h1 = ListNode() + h2 = ListNode() diff --git a/palindrome_number.rs b/palindrome_number.rs new file mode 100644 index 0000000..bd3c641 --- /dev/null +++ b/palindrome_number.rs @@ -0,0 +1,24 @@ +struct Solution; + +impl Solution { + fn is_palindrome(mut x: i32) -> bool { + if x < 0 { + return false; + } + let mut nums = Vec::with_capacity(10); + while x != 0 { + nums.push(x % 10); + x /= 10; + } + for i in 0..(nums.len() / 2) { + if nums[i] != nums[nums.len() - i - 1] { + return false; + } + } + true + } +} + +fn main() { + print!("{}", Solution::is_palindrome(121)); +} diff --git a/palindrome_pairs.cpp b/palindrome_pairs.cpp new file mode 100644 index 0000000..bc00279 --- /dev/null +++ b/palindrome_pairs.cpp @@ -0,0 +1,38 @@ +#include "leetcode.h" + +class Solution { +public: + vvd(int) palindromePairs(vector<string> &words) { + unordered_map<string, int> um; + for (int i = 0; i < words.size(); i++) { + string x = words[i]; + reverse(x.begin(), x.end()); + um[x] = i; + } + vvd(int) ans; + for (int j = 0; j < words.size(); j++) { + string str = words[j]; + for (int i = 0; i <= str.size(); i++) { + string prefix = str.substr(0, i), suffix = str.substr(i); + if (!prefix.empty() && isPalindrome(prefix) && um.count(suffix) && + j != um[suffix]) + ans.push_back({um[suffix], j}); + if (isPalindrome(suffix) && um.count(prefix) && j != um[prefix]) + ans.push_back({j, um[prefix]}); + } + } + return ans; + } + +private: + bool isPalindrome(string &str) { + int i = 0, j = str.size() - 1; + while (i < j) { + if (str[i] != str[j]) + return false; + i++; + j--; + } + return true; + } +}; diff --git a/palindrome_partitioning.c b/palindrome_partitioning.c new file mode 100644 index 0000000..83bcf8d --- /dev/null +++ b/palindrome_partitioning.c @@ -0,0 +1,56 @@ +// 131. Palindrome Partitioning +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given: string 's', parition 's' such that every substring of the parition + * is a palindrome. return all possible palindrome paritioning of 's'. + */ + +bool isPalindrome(char *s, int end) { + if (end < 0) + return false; + int start = 0; + while (end > start) { + if (s[start] != s[end]) + return false; + start++; + end--; + } + return true; +} + +void dfs(char *s, char ***ret, int **cols, int *retColSz, char **curr, int k) { + if (*s == 0) { + ret[*retColSz] = (char **)malloc(sizeof(char *) * k); + for (int i = 0; i < k; i++) { + ret[*retColSz][i] = (char *)malloc(strlen(curr[i]) + 1); + strcpy(ret[*retColSz][i], curr[i]); + } + (*cols)[(*retColSz)++] = k; + return; + } + int len = strlen(s); + for (int i = 0; i < len; i++) { + if (isPalindrome(s, i)) { + strncpy(curr[k], s, i + 1); + curr[k][i + 1] = '\0'; + dfs(s + i + 1, ret, cols, retColSz, curr, k + 1); + } + } +} + +char ***partition(char *s, int **returnSize, int *returnColumnSizes) { + *returnColumnSizes = 0; + if (s == NULL || !strcmp(s, "")) + return NULL; + *returnSize = (int *)malloc(sizeof(int) * 500); + char ***ans = (char ***)malloc(sizeof(char ***) * 500); + int len = strlen(s) + 1; + char **curr = (char **)malloc(sizeof(char *) * 500); + for (int i = 0; i < 500; i++) + curr[i] = (char *)malloc(len); + dfs(s, ans, returnSize, returnColumnSizes, curr, 0); +} diff --git a/palindrome_partitioning.cpp b/palindrome_partitioning.cpp new file mode 100644 index 0000000..6a49703 --- /dev/null +++ b/palindrome_partitioning.cpp @@ -0,0 +1,50 @@ +// 131. Palindrome Partitioning +#include "leetcode.h" +#include <vector> + +/* + * given: string 's', parition 's' such that every substring of the parition + * is a palindrome. return all possible palindrome paritioning of 's'. + */ + +class Solution { +public: + vvd(string) partition(string s) { + vvd(string) ans; + if (s.empty()) + return ans; + vector<string> path; + dfs(0, s, path, ans); + return ans; + } + +private: + void dfs(int idx, string &s, vector<string> &path, vvd(string) & res) { + if (idx == s.size()) + res.push_back(path); + return; + for (int i = idx; i < s.size(); ++i) { + if (isPalindrome(s, idx, i)) { + path.push_back(s.substr(idx, i - idx + 1)); + dfs(i + 1, s, path, res); + path.pop_back(); + } + } + } + bool isPalindrome(const string &s, int start, int end) { + while (start <= end) + if (s[start++] != s[end--]) + return false; + return true; + } +}; + +int main() { + Solution obj; + for (auto i : obj.partition("aab")) + for (auto j : i) + cout << j << ' '; // expect: [["a","a","b"],["aa","b"]] + for (auto i : obj.partition("a")) + for (auto j : i) + cout << j << ' '; // expect: [["a"]] +} diff --git a/palindrome_partitioning.py b/palindrome_partitioning.py new file mode 100644 index 0000000..32805e8 --- /dev/null +++ b/palindrome_partitioning.py @@ -0,0 +1,35 @@ +# 131. Palindrome Partitioning +from collections import defaultdict + +""" +given: string 's', parition 's' such that every substring of the parition +is a palindrome. return all possible palindrome paritioning of 's'. +""" + + +class Solution(object): + def __init__(self): + self.memory = defaultdict(list) + + def partition(self, s): + """ + :type s: str + :rtype: List[List[str]] + """ + if not s: + return [[]] + if s in self.memory: + return self.memory[s] + ans = [] + for i in range(1, len(s) + 1): + if s[:i] == s[:i][::-1]: + for suf in self.partition(s[i:]): + ans.append([s[:i]] + suf) + self.memory[s] = ans + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.partition(s="aab")) + print(obj.partition(s="a")) diff --git a/palindromic_paths_bt.c b/palindromic_paths_bt.c new file mode 100644 index 0000000..183e19f --- /dev/null +++ b/palindromic_paths_bt.c @@ -0,0 +1,46 @@ +// 1457. Pseudo-Palindromic Paths in a Binary Tree +#include "leetcode.h" + +/* + * given a binary tree where node values are digits from 1 to 9. a path in the + * binary tree is said to be pseudo palindromic if at least one permutation of + * the node values in the path is a palindrome. return the number of pseudo + * palindromic paths going from the root node to leaf nodes. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int dfs(struct TreeNode *root, int *hash_table, int hash_size) { + hash_table[root->val]++; + if (!root->left && !root->right) { + int odd = 0; + for (int i = 0; i < hash_size; i++) { + if (hash_table[i] % 2) { + odd++; + if (odd > 1) + return 0; + } + } + return 1; + } + int left_cnt = 0, right_cnt = 0; + if (root->left) { + left_cnt = dfs(root->left, hash_table, hash_size); + hash_table[root->left->val]--; + } + if (root->right) { + right_cnt = dfs(root->right, hash_table, hash_size); + hash_table[root->right->val]--; + } + return left_cnt + right_cnt; +} + +int pseudoPalindromicPaths(struct TreeNode *root) { + int hash_size = 10; + int *hash_table = calloc(hash_size, sizeof(int)); + return dfs(root, hash_table, hash_size); +} diff --git a/palindromic_paths_bt.py b/palindromic_paths_bt.py new file mode 100644 index 0000000..1f65c94 --- /dev/null +++ b/palindromic_paths_bt.py @@ -0,0 +1,45 @@ +# 1457. Pseudo-Palindromic Paths in a Binary Tree + +""" +given a binary tree where node values are digits from 1 to 9. a path in the +binary tree is said to be pseudo palindromic if at least one permutation of +the node values in the path is a palindrome. return the number of pseudo +palindromic paths going from the root node to leaf nodes. +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def pseudoPalindromicPaths(self, root): + """ + :type root: TreeNode + :rtype: int + """ + if not root: + return 0 + count ^= 1 << (root.val - 1) + res = self.pseudoPalindromicPaths( + root.left, count + ) + self.pseudoPalindromicPaths(root.right, count) + if root.left == root.right: + if count & (count - 1) == 0: + res += 1 + return res + + +if __name__ == "__main__": + obj = Solution() + print(obj.pseudoPalindromicPaths(root=[2, 3, 1, 3, 1, null, 1])) + print( + obj.pseudoPalindromicPaths( + root=[2, 1, 1, 1, 3, null, null, null, null, null, 1] + ) + ) + print(obj.pseudoPalindromicPaths(root=[9])) diff --git a/palindromic_substrings.c b/palindromic_substrings.c new file mode 100644 index 0000000..b450091 --- /dev/null +++ b/palindromic_substrings.c @@ -0,0 +1,35 @@ +// 647. Palindromic Substrings +#include "leetcode.h" + +/* + * given a string 's', return the number of palindromic substrings in it. a + * string is a palindrome when it reads the same backward as forward. a + * substring is a contiguous sequence of charcters within the string. + */ + +int countSubstrings(char *s) { + int i = 0, num = 0, left = 0, right = 0; + while (s[i] != '\0') { + left = right = i; + while (left >= 0 && right < strlen(s) && s[left] == s[right]) { + num++; + left--; + right++; + } + left = i; + right = i + 1; + while (left >= 0 && right < strlen(s) && s[left] == s[right]) { + num++; + left--; + right++; + } + i++; + } + return num; +} + +int main() { + char *s1 = "abc", *s2 = "aaa"; + printf("%d\n", countSubstrings(s1)); // expect: 3 + printf("%d\n", countSubstrings(s2)); // expect: 6 +} diff --git a/palindromic_substrings.cpp b/palindromic_substrings.cpp new file mode 100644 index 0000000..8de80a0 --- /dev/null +++ b/palindromic_substrings.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + int countSubstrings(string s) { + this->s = s; + int ans = 0, n = s.size(); + dp.resize(n, vector<int>(n, -1)); + for (int i = 0; i < n; i++) + for (int j = i; j < n; j++) + ans += helper(i, j, s); + return ans; + } + +private: + vector<vector<int>> dp; + // string s = "abc"; + int helper(int l, int r, string s) { + if (l > r || l == r) + return 1; + if (dp[l][r] != -1) + return dp[l][r]; + if (s[l] != s[r]) + return dp[l][r] = 0; + if (helper(l + 1, r - 1, s)) + return dp[l][r] = 1; + return dp[l][r] = 0; + } +}; + +int main() {} diff --git a/palindromic_substrings.py b/palindromic_substrings.py new file mode 100644 index 0000000..8f6343e --- /dev/null +++ b/palindromic_substrings.py @@ -0,0 +1,36 @@ +# 647. Palindromic Substrings + +""" +given a string 's', return the number of palindromic substrings in it. a +string is a palindrome when it reads the same backward as forward. a +substring is a contiguous sequence of charcters within the string. +""" + + +class Solution(object): + def countSubstrings(self, s): + """ + :type s: str + :rtype: int + """ + n, ans = len(s), 0 + + def palindrome_count(left, right): + cnt = 0 + while left >= 0 and right < n and s[left] == s[right]: + left -= 1 + right += 1 + cnt += 1 + return cnt + + for i in range(n): + even = palindrome_count(i, i + 1) + odd = palindrome_count(i, i) + ans += even + odd + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.countSubstrings("abc")) + print(obj.countSubstrings("aaa")) diff --git a/parallel_courses3.cpp b/parallel_courses3.cpp new file mode 100644 index 0000000..3c9e2d3 --- /dev/null +++ b/parallel_courses3.cpp @@ -0,0 +1,54 @@ +// 2050. Parallel Courses III +#include "leetcode.h" + +/* + * given an integer 'n' which indicates that there are n courses labeled from 1 + * to n. you are also given a 2d integer array rleations where relations[j] = + * pre_course[j], denotes that course pre_course has to be completed before + * next_course. furthermore, you are given a 0-indexed integer array 'time' + * where 'time[i]' denotes how many months it takes to complete the '(i + 1)'th + * course. you must find the minimum number of months needed to complete all the + * courses following these rules. you may start taking courses at any time if + * the prerequisites have been met, and any number of courses can be taken at + * the same time. return the minimum number of monthsneeded to omplete all the + * courses. + */ + +class Solution { +public: + int minimumTime(int n, vvd(int) & relations, vector<int> &time) { + vector<int> in_deg(n + 1); + vvd(int) g(n + 1); + for (auto r : relations) { + int a = r[0]; + int b = r[1]; + g[a].push_back(b); + in_deg[b]++; + } + vector<int> finish_time(n + 1); + queue<int> q; + for (int i = 1; i <= n; i++) + if (!in_deg[i]) + q.push(i); + while (!q.empty()) { + int curr = q.front(); + q.pop(); + finish_time[curr] += time[curr - 1]; + for (auto next : g[curr]) { + in_deg[next]--; + finish_time[next] = max(finish_time[next], finish_time[curr]); + if (!in_deg[next]) + q.push(next); + } + } + return *max_element(finish_time.begin(), finish_time.end()); + } +}; + +int main() { + Solution obj; + vvd(int) r1 = {{1, 3}, {2, 3}}, r2 = {{1, 5}, {2, 5}, {3, 5}, {3, 4}, {4, 5}}; + vector<int> t1 = {3, 2, 5}, t2 = {1, 2, 3, 4, 5}; + printf("%d\n", obj.minimumTime(3, r1, t1)); // expect: 8 + printf("%d\n", obj.minimumTime(5, r2, t2)); // expect: 12 +} diff --git a/parallel_courses3.py b/parallel_courses3.py new file mode 100644 index 0000000..dd60e45 --- /dev/null +++ b/parallel_courses3.py @@ -0,0 +1,53 @@ +# 2050. Parallel Courses III +from collections import defaultdict, deque + +""" +given an integer 'n' which indicates that there are n courses labeled from 1 +to n. you are also given a 2d integer array rleations where relations[j] = +pre_course[j], denotes that course pre_course has to be completed before +next_course. furthermore, you are given a 0-indexed integer array 'time' +where 'time[i]' denotes how many months it takes to complete the '(i + 1)'th +course. you must find the minimum number of months needed to complete all the +courses following these rules. you may start taking courses at any time if +the prerequisites have been met, and any number of courses can be taken at +the same time. return the minimum number of monthsneeded to omplete all the +courses. +""" + + +class Solution(object): + def minimumTime(self, n, relations, time): + graph = defaultdict(list) + inDegree = [0] * n + for prv, nxt in relations: + prv, nxt = prv - 1, nxt - 1 + graph[prv].append(nxt) + inDegree[nxt] += 1 + + q = deque([]) + dist = [0] * n + for u in range(n): + if inDegree[u] == 0: + q.append(u) + dist[u] = time[u] + + while q: + u = q.popleft() + for v in graph[u]: + dist[v] = max(dist[u] + time[v], dist[v]) + inDegree[v] -= 1 + if inDegree[v] == 0: + q.append(v) + return max(dist) + + +if __name__ == "__main__": + obj = Solution() + print(obj.minimumTime(n=3, relations=[[1, 3], [2, 3]], time=[3, 2, 5])) # expect: 8 + print( + obj.minimumTime( + n=5, + relations=[[1, 5], [2, 5], [3, 5], [3, 4], [4, 5]], + time=[1, 2, 3, 4, 5], + ) + ) # expect: 12 diff --git a/parse_boolean_expression.c b/parse_boolean_expression.c new file mode 100644 index 0000000..f970141 --- /dev/null +++ b/parse_boolean_expression.c @@ -0,0 +1,75 @@ +// 1106. Parsing A Boolean Expression +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * a boolean expression is an expression that evaluates to either 'true' or + * 'false'. it can be one of the following shapes: + * - 't' that evaluates to true + * - 'f' that evaluates to false + * - '!(subExpr)' that evalutes to the logical not of the inner expression + * 'subExpr' + * - '&(subExpr1, subExpr2, ..., subExprn)' that evalutes to the logical AND of + * the inner expressions 'subExpr1, subExpr2, ..., subExprn' where 'n >= 1' + * - '|(subExpr1, subExpr2, ..., subExprn)' that evaluates to the logical OR of + * the inner expressions 'subExpr1, subExpr2, ..., subExprn' where 'n >= 1' + * given a string 'expression' that represents a boolean expression, return the + * evaluation of that expression + */ + +#define IS_VALUE(c) ((c) == 't' || (c) == 'f') +#define IS_OPERA(c) ((c) == '!' || (c) == '&' || (c) == '|') + +static char *expr, *s; + +bool parse() { + if (IS_VALUE(*s)) + return (*s++) == 't'; + if (IS_OPERA(*s)) { + char op = *s; + s++; + if (*s != '(') { + fprintf(stderr, "error: unexpected char '%c' at pos %ld, expects '('\n", + *s, s - expr); + exit(1); + } + s++; + bool b = false; + if (op == '!') + b = !parse(); + else { + b = parse(); + while (*s == ',') { + s++; + bool n = parse(); + if (op == '&') + b = b && n; + else + b = b || n; + } + } + if (*s != ')') { + fprintf(stderr, "error: unexpected char '%c' at pos %ld, expects ')'\n", + *s, s - expr); + exit(1); + } + s++; + return b; + } + fprintf(stderr, "error: unexpected char '%c' at pos %ld\n", *s, s - expr); + exit(1); +} + +bool parseBoolExpr(char *expression) { + expr = expression; + s = expression; + return parse(); +} + +int main() { + char e1[] = {"&(|(f))"}, e2[] = {"|(f,f,f,t)"}, e3[] = {"!(&(f,t))"}; + printf("%d\n", parseBoolExpr(e1)); // expect: 0 + printf("%d\n", parseBoolExpr(e2)); // expect: 1 + printf("%d\n", parseBoolExpr(e3)); // expect: 1 +} diff --git a/partition_array_max_sum.c b/partition_array_max_sum.c new file mode 100644 index 0000000..8e37cc5 --- /dev/null +++ b/partition_array_max_sum.c @@ -0,0 +1,36 @@ +// 1043. Partition Array for Maximum Sum +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integeer array 'arr', partition the array into contiguous subarrays + * of length at most 'k'. after partitioning, each subarray has their values + * changed to become the maximum value of that subarray. return the largest sum + * of the given array after partitioning. test cases are generated so that + * answer fits in a 32-bit integer + */ + +int maxSumAfterPartitioning(int *arr, int arr_size, int k) { + int n = arr_size, *dp = malloc((n + 1) * sizeof(int)); + dp[0] = 0; + for (int i = 0; i < n; i++) { + int m = arr[i]; + dp[i + 1] = arr[i] + dp[i]; + for (int j = i - 1; j >= fmax(0, i - k + 1); j--) { + m = fmax(m, arr[j]); + dp[i + 1] = fmax(dp[i + 1], m * (i - j + 1) + dp[j]); + } + } + int ans = dp[n]; + free(dp); + return ans; +} + +int main() { + int a1[] = {1, 15, 7, 9, 2, 5, 10}, a2[] = {1, 4, 1, 5, 7, 3, 6, 1, 9, 9, 3}, + a3[] = {1}; + printf("%d\n", maxSumAfterPartitioning(a1, 7, 3)); // expect: 84 + printf("%d\n", maxSumAfterPartitioning(a2, 11, 4)); // expect: 83 + printf("%d\n", maxSumAfterPartitioning(a3, 1, 1)); // expect: 1 +} diff --git a/partition_array_max_sum.cpp b/partition_array_max_sum.cpp new file mode 100644 index 0000000..98efe07 --- /dev/null +++ b/partition_array_max_sum.cpp @@ -0,0 +1,36 @@ +// 1043. Partition Array for Maximum Sum +#include "leetcode.h" + +/* + * given an integeer array 'arr', partition the array into contiguous subarrays + * of length at most 'k'. after partitioning, each subarray has their values + * changed to become the maximum value of that subarray. return the largest sum + * of the given array after partitioning. test cases are generated so that + * answer fits in a 32-bit integer + */ + +class Solution { +public: + int maxSumAfterPartitioning(vector<int> &arr, int k) { + int n = arr.size(); + vector<int> dp(n + 1); + for (int i = 1; i <= n; ++i) { + int curr = 0, best = 0; + for (int j = 1; j <= k && i - j >= 0; ++j) { + curr = max(curr, arr[i - j]); + best = max(best, dp[i - j] + curr * j); + } + dp[i] = best; + } + return dp[n]; + } +}; + +int main() { + Solution obj; + vector<int> a1 = {1, 15, 7, 9, 2, 5, 10}, + a2 = {1, 4, 1, 5, 7, 3, 6, 1, 9, 9, 3}, a3 = {1}; + printf("%d\n", obj.maxSumAfterPartitioning(a1, 3)); // expect: 84 + printf("%d\n", obj.maxSumAfterPartitioning(a2, 4)); // expect: 83 + printf("%d\n", obj.maxSumAfterPartitioning(a3, 1)); // expect: 1 +} diff --git a/partition_array_max_sum.py b/partition_array_max_sum.py new file mode 100644 index 0000000..7c208e3 --- /dev/null +++ b/partition_array_max_sum.py @@ -0,0 +1,37 @@ +# 1043. Partition Array for Maximum Sum + +""" +given an integeer array 'arr', partition the array into contiguous subarrays +of length at most 'k'. after partitioning, each subarray has their values +changed to become the maximum value of that subarray. return the largest sum +of the given array after partitioning. test cases are generated so that +answer fits in a 32-bit integer +""" + + +class Solution(object): + def maxSumAfterPartitioning(self, arr, k): + """ + :type arr: List[int] + :type k: int + :rtype: int + """ + n = len(arr) + m = k + 1 + dp = [0] * m + for start in range(n - 1, -1, -1): + curr_max = 0 + end = min(n, start + m) + for i in range(start, end): + curr_max = max(curr_max, arr[i]) + dp[start % m] = max( + dp[start % m], dp[(i + 1) % m] + curr_max * (i - start + 1) + ) + return dp[0] + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxSumAfterPartitioning(arr=[1, 15, 7, 9, 2, 5, 10], k=3)) + print(obj.maxSumAfterPartitioning(arr=[1, 4, 1, 5, 7, 3, 6, 1, 9, 9, 3], k=4)) + print(obj.maxSumAfterPartitioning(arr=[1], k=1)) diff --git a/partition_array_pivot.rs b/partition_array_pivot.rs new file mode 100644 index 0000000..8a126da --- /dev/null +++ b/partition_array_pivot.rs @@ -0,0 +1,32 @@ +struct Solution; + +impl Solution { + pub fn pivot_array(nums: Vec<i32>, pivot: i32) -> Vec<i32> { + let mut greater = vec![]; + let mut same = 0; + let ans = vec![]; + for n in nums { + if n < pivot { + ans.push(n); + } else if n == pivot { + same += 1; + } else { + greater.push(n); + } + } + for _ in 0..same { + ans.push(pivot); + } + for g in greater { + ans.push(g); + } + ans + } +} + +fn main() { + let s = Solution; + let nums = vec![9,12,5,10,14,3,10]; + let pivot = 10; + print!("{}", s.pivot_array(nums, pivot)); +} diff --git a/partition_list.c b/partition_list.c new file mode 100644 index 0000000..a95b1d9 --- /dev/null +++ b/partition_list.c @@ -0,0 +1,59 @@ +// 86. Partition List +#include <stdlib.h> + +/* + * given the head of a linked list and a value 'x', partition it such that all + * nodes less than 'x' come before nodes greater than or equal to 'x'. you + * should preserve the original relative order of the nodes in each of the two + * partitions. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +struct ListNode *add(struct ListNode *head, int data) { + struct ListNode *tmp = (struct ListNode *)malloc(sizeof(struct ListNode)); + tmp->val = data; + tmp->next = NULL; + if (!head) { + head = (struct ListNode *)malloc(sizeof(struct ListNode)); + head->val = data; + head->next = NULL; + } else { + struct ListNode *traverse = head; + while (traverse) + traverse = traverse->next; + traverse->next = tmp; + } + return head; +} + +struct ListNode *partition(struct ListNode *head, int x) { + if (!head) + return head; + int *arr = (int *)malloc(200 * sizeof(int)); + struct ListNode *traverse = head; + int idx = 0, is_head = 0; + if (traverse->val >= x) { + arr[idx++] = traverse->val; + is_head = 1; + } + while (traverse && traverse->next) { + if (traverse->next->val >= x) { + arr[idx++] = traverse->next->val; + traverse->next = traverse->next->next; + } else { + traverse = traverse->next; + } + } + struct ListNode *res = head; + while (res && res->next) + res = res->next; + for (int i = 0; i < idx; i++) + res = add(res, arr[i]); + if (is_head == 1) + head = head->next; + return head; +} diff --git a/partition_list.cpp b/partition_list.cpp new file mode 100644 index 0000000..b2e44a9 --- /dev/null +++ b/partition_list.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + ListNode *partition(ListNode *head, int x) { + ListNode *fTmp = new ListNode(0), *bTmp = new ListNode(0), *front = fTmp, + *back = bTmp, *curr = head; + while (curr) { + if (curr->val < x) { + front->next = curr; + front = curr; + } else { + back->next = curr; + back = curr; + } + } + front->next = bTmp->next, back->next = nullptr; + return fTmp->next; + } +}; diff --git a/partition_min_binary_array.cpp b/partition_min_binary_array.cpp new file mode 100644 index 0000000..8cec267 --- /dev/null +++ b/partition_min_binary_array.cpp @@ -0,0 +1,18 @@ +#include "leetcode.h" + +class Solution { +public: + int minPartitions(string n) { + char ans = '0'; + for (char c : n) + if (c > ans) + ans = c; + return ans - '0'; + } +}; + +int main() { + Solution obj; + string n = "32"; + cout << obj.minPartitions(n); +} diff --git a/pascals_triangle.c b/pascals_triangle.c new file mode 100644 index 0000000..969bdf0 --- /dev/null +++ b/pascals_triangle.c @@ -0,0 +1,45 @@ +// 118. Pascal's Triangle +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer 'num_rows', return the first numrows of pascal's triangle. + * in pascal's triangle, each number is the sum of the two number direction + * above it as show [gif] + */ + +int **generate(int num_rows, int *return_size, int **col_size) { + int **ans = (int **)malloc(sizeof(int *) * num_rows); + int i, j; + *return_size = num_rows; + for (i = 0; i < num_rows; i++) { + ans[i] = (int *)malloc(sizeof(int) * (i + 1)); + ans[i][0] = 1; + ans[i][i] = 1; + } + *col_size = (int *)malloc(sizeof(int) * num_rows); + for (i = 0; i < num_rows; i++) + (*col_size)[i] = i + 1; + i = 2; + while (i < num_rows) { + j = 1; + while (j < i) { + ans[i][j] = ans[i - 1][j - 1] + ans[i - 1][j]; + j++; + } + i++; + } + return ans; +} + +int main() { + int **g1 = generate(5, NULL, NULL); + int **g2 = generate(1, NULL, NULL); + for (int i = 0; i < 5; i++) + for (int j = 0; j < 5; j++) + printf("%d ", + g1[i][j]); // expect: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]] + for (int i = 0; i < 1; i++) + for (int j = 0; j < 1; j++) + printf("%d ", g2[i][j]); // expect: [[1]] +} diff --git a/pascals_triangle.cpp b/pascals_triangle.cpp new file mode 100644 index 0000000..343c116 --- /dev/null +++ b/pascals_triangle.cpp @@ -0,0 +1,19 @@ +#include "leetcode.h" + +class Solution { +public: + vector<vector<int>> generate(int numRows) { + vector<vector<int>> ans(numRows); + for (int i = 0; i < numRows; i++) { + vector<int> row(i + 1, 1); + int mid = i >> 1; + for (int j = 1; j <= mid; j++) { + int val = ans[i - 1][j - 1] + ans[i - 1][j]; + row[j] = val; + row[row.size() - j - 1] = val; + } + ans[i] = row; + } + return ans; + } +}; diff --git a/pascals_triangle.py b/pascals_triangle.py new file mode 100644 index 0000000..0b2bf08 --- /dev/null +++ b/pascals_triangle.py @@ -0,0 +1,22 @@ +# 118. Pascal's Triangle + +""" +given an integer 'num_rows', return the first numrows of pascal's triangle. +in pascal's triangle, each number is the sum of the two number direction +above it as show [gif] +""" + + +class Solution(object): + def generate(self, num_rows): + ans = [[1 for _ in range(row + 1)] for row in range(num_rows)] + for row in range(num_rows): + for col in range(1, row): + ans[row][col] = ans[row - 1][col] + ans[row - 1][col - 1] + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.generate(5)) # expect: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]] + print(obj.generate(1)) # expect: [[1]] diff --git a/pascals_triangle2.c b/pascals_triangle2.c new file mode 100644 index 0000000..ef21edc --- /dev/null +++ b/pascals_triangle2.c @@ -0,0 +1,46 @@ +// 119. Pascal's Triangle II +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given an integer 'row_index', return the 'row_index'th row of the pascals + * triangle. in pascals triangle, each number is the sum of the two numbers + * directly above it as shown. + */ + +int *getRow(int row_index, int *return_size) { + uint val[34]; + memset(val, 0, sizeof(val)); + val[0] = 1; + *return_size = row_index + 1; + for (int i = 0; i < row_index; ++i) { + int prev = 1, j; + const int total = row_index + 1, half = total / 2; + for (j = 1; j < half; ++j) { + val[j] = prev + val[j]; + prev = val[j] - prev; + val[total - j - 1] = val[j]; + } + if (total & 1) + val[j] = prev + val[j]; + val[total - 1] = 1; + } + return val; +} + +int main() { + int rs1[] = {}, rs2[] = {}, rs3[] = {}; + int *gr1 = getRow(3, rs1); + int *gr2 = getRow(0, rs2); + int *gr3 = getRow(1, rs3); + for (int i = 0; i < 4; i++) + printf("%d ", gr1[i]); // expect: 1 3 3 1 + printf("\n"); + for (int i = 0; i < 1; i++) + printf("%d ", gr2[i]); // expect: 1 + printf("\n"); + for (int i = 0; i < 2; i++) + printf("%d ", gr3[i]); // expect: 1 1 + printf("\n"); +} diff --git a/pascals_triangle2.py b/pascals_triangle2.py new file mode 100644 index 0000000..4fe79f7 --- /dev/null +++ b/pascals_triangle2.py @@ -0,0 +1,22 @@ +# 119. Pascal's Triangle II + +""" +given an integer 'row_index', return the 'row_index'th row of the pascals +triangle. in pascals triangle, each number is the sum of the two numbers +directly above it as shown. +""" + + +class Solution(object): + def getRow(self, row_index): + row = [1] + for _ in range(row_index): + row = [x + y for x, y in zip([0] + row, row + [0])] + return row + + +if __name__ == "__main__": + obj = Solution() + print(obj.getRow(3)) + print(obj.getRow(0)) + print(obj.getRow(1)) diff --git a/path_crossing.c b/path_crossing.c new file mode 100644 index 0000000..039556a --- /dev/null +++ b/path_crossing.c @@ -0,0 +1,71 @@ +// 1496. Path Crossing +#include "leetcode.h" + +/* + * given a string 'path' where 'path[i] = 'N, 'S', 'E', or 'W', each + * representing moving one unit north, south, east, or west, respectively. you + * start at the origin '(0, 0)' on a 2d plane and walk on the path specified by + * 'path'. return 'true' if the path crosses itself at any point, that is, if at + * any time you are on a location you have previously visited. return 'false' + * otherwise. + */ + +typedef struct { + uint val; + int r_type; + int c_type; +} data; + +bool isPathCrossing(char *path) { + int n = strlen(path), m = 5 * n; + data **hash = calloc(m, sizeof(data *)); + hash[0] = malloc(sizeof(data)); + hash[0]->val = 0; + hash[0]->r_type = 1; + hash[0]->c_type = 1; + int r = 0, c = 0; + bool ans = 0; + for (int i = 0; i < n; i++) { + if (ans) + break; + switch (path[i]) { + case 'N': + r++; + break; + case 'S': + r--; + break; + case 'W': + c++; + break; + default: + c++; + } + uint val = abs(r) * 10000 + abs(c), d = val; + while (1) { + if (!hash[d % m]) { + hash[d % m] = malloc(sizeof(data)); + hash[d % m]->val = val; + hash[d % m]->r_type = r >= 0; + hash[d % m]->c_type = c >= 0; + break; + } else if (hash[d % m]->val == val && hash[d % m]->r_type == r >= 0 && + hash[d % m]->c_type == c >= 0) { + ans = 1; + break; + } else + d++; + } + } + for (int i = 0; i < m; i++) + if (hash[i]) + free(hash[i]); + free(hash); + return ans; +} + +int main() { + char *p1 = "NES", *p2 = "NESWW"; + printf("%d\n", isPathCrossing(p1)); // expect: 0 + printf("%d\n", isPathCrossing(p2)); // expect: 1 +} diff --git a/path_crossing.py b/path_crossing.py new file mode 100644 index 0000000..8b431ac --- /dev/null +++ b/path_crossing.py @@ -0,0 +1,35 @@ +# 1496. Path Crossing + +""" +given a string 'path' where 'path[i] = 'N, 'S', 'E', or 'W', each +representing moving one unit north, south, east, or west, respectively. you +start at the origin '(0, 0)' on a 2d plane and walk on the path specified by +'path'. return 'true' if the path crosses itself at any point, that is, if at +any time you are on a location you have previously visited. return 'false' +otherwise. +""" + + +class Solution(object): + def isPathCrossing(self, path): + """ + :type path: str + :rtype: bool + """ + moves = {"N": (0, 1), "S": (0, -1), "W": (-1, 0), "E": (1, 0)} + vis = {(0, 0)} + x = y = 0 + for i in path: + dx, dy = moves[i] + x += dx + y += dy + if (x, y) in vis: + return True + vis.add((x, y)) + return False + + +if __name__ == "__main__": + obj = Solution() + print(obj.isPathCrossing("NES")) + print(obj.isPathCrossing("NESWW")) diff --git a/path_max_gold.c b/path_max_gold.c new file mode 100644 index 0000000..9d31536 --- /dev/null +++ b/path_max_gold.c @@ -0,0 +1,38 @@ +// 1219. Path with Maximum Gold +#include "leetcode.h" + +/* + * in a gold mine 'grid' of size 'm * n' each cell in this mine has an integer + * representing the amount of gold in that cell, 0 if it is empty. return the + * maximum amount of gold you can collect under the conditions: every time you + * are located in a cell, you will collect all the gold in that cell. from your + * position, you can walk one step to the left, right, up, or down. you cannot + * visit thesame cell more than once. never visit a cell with 0 gold. you can + * start and stop collecting gold from any position in the grid that has some + * gold. + */ + +void dfs(int **grid, int m, int n, int i, int j, int val, int *ans) { + if (i < 0 || j < 0 || i == m || j == n || !grid[i][j]) { + *ans = fmax(*ans, val); + return; + } + int start_pos = grid[i][j]; + grid[i][j] = 0; + dfs(grid, m, n, i + 1, j, val + start_pos, ans); + dfs(grid, m, n, i - 1, j, val + start_pos, ans); + dfs(grid, m, n, i, j + 1, val + start_pos, ans); + dfs(grid, m, n, i, j - 1, val + start_pos, ans); + grid[i][j] = start_pos; +} + +int getMaximumGold(int **grid, int gridSize, int *gridColSize) { + int ans = 0, m = gridSize, n = *gridColSize; + for (int i = 0; i < m; i++) + for (int j = 0; j < n; j++) { + if (!grid[i][j]) + continue; + dfs(grid, m, n, i, j, 0, &ans); + } + return ans; +} diff --git a/path_max_gold.py b/path_max_gold.py new file mode 100644 index 0000000..a11a05c --- /dev/null +++ b/path_max_gold.py @@ -0,0 +1,46 @@ +# 1219. Path with Maximum Gold + +""" +in a gold mine 'grid' of size 'm n' each cell in this mine has an integer +representing the amount of gold in that cell, 0 if it is empty. return the +maximum amount of gold you can collect under the conditions: every time you +are located in a cell, you will collect all the gold in that cell. from your +position, you can walk one step to the left, right, up, or down. you cannot +visit thesame cell more than once. never visit a cell with 0 gold. you can +start and stop collecting gold from any position in the grid that has some +gold. +""" + + +class Solution(object): + def dfs(self, grid, r, c, m, n): + if r < 0 or r == m or c < 0 or c == n or grid[r][c] == 0: + return 0 + res, start_pos = 0, grid[r][c] + dir = [0, 1, 0, -1, 0] + grid[r][c] = 0 + for i in range(4): + res = max(res, self.dfs(grid, r + dir[i], c + dir[i + 1], m, n)) + grid[r][c] = start_pos + return res + grid[r][c] + + def getMaximumGold(self, grid): + """ + :type grid: List[List[int]] + :rtype: int + """ + ans, m, n = 0, len(grid), len(grid[0]) + for r in range(m): + for c in range(n): + ans = max(ans, self.dfs(grid, r, c, m, n)) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.getMaximumGold(grid=[[0, 6, 0], [5, 8, 7], [0, 9, 0]])) + print( + obj.getMaximumGold( + grid=[[1, 0, 7], [2, 0, 6], [3, 4, 5], [0, 3, 0], [9, 0, 20]] + ) + ) diff --git a/path_max_probability.c b/path_max_probability.c new file mode 100644 index 0000000..11e2b41 --- /dev/null +++ b/path_max_probability.c @@ -0,0 +1,77 @@ +// 1514. Path with Maximum Probability +#include <math.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an undirected weighted graph of 'n' nodes (0-indexed). represented by + * an edge list where 'edges[i] = [a, b]' is an undirected edge connecting the + * nodes 'a' and 'b' with a probability of success of traversing that edge + * 'succ_prob[i]'. given two nodes 'start, end', find the path with the maximum + * probability of success to go from 'start' to 'end' and return its success + * probability. if there is no path from 'start' to 'end', return 0. your answer + * will be accepted if it differs from the correct answer by at most '1e-5' + */ + +#define LOWER_BOUND 1e-5 + +typedef struct { + int next; + double val; +} node; + +void dfs(int n, bool *visited, double val, double *ans, int curr, int end, + int *cn, node **map) { + if (curr == end) + *ans = fmax(*ans, val); + if (*ans >= val) + return; + if (val - *ans <= LOWER_BOUND) + return; + if (visited[curr]) + return; + visited[curr] = true; + for (int i = 0; i < cn[curr]; i++) { + double new_val = val * map[curr][i].val; + dfs(n, visited, new_val, ans, map[curr][i].next, end, cn, map); + } + visited[curr] = false; +} + +double maxProbability(int n, int **edges, int edges_size, int *edges_col_size, + double *succ_prob, int succ_prob_size, int start, + int end) { + double ans = 0; + bool *visited = calloc(n, sizeof(bool)); + int *cn = calloc(n, sizeof(int)); + node **map = calloc(n, sizeof(node *)); + for (int i = 0; i < edges_size; i++) { + cn[edges[i][0]]++; + cn[edges[i][1]]++; + } + for (int i = 0; i < n; i++) + if (cn[i]) + map[i] = malloc(cn[i] * sizeof(node)); + int *m_idx = calloc(n, sizeof(int)); + for (int i = 0; i < edges_size; i++) { + int prob = edges[i][0], next = edges[i][1], idx = m_idx[prob]; + map[prob][idx].next = next; + map[prob][idx].val = succ_prob[i]; + m_idx[prob]++; + prob = edges[i][1]; + next = edges[i][0]; + idx = m_idx[prob]; + map[prob][idx].next = next; + map[prob][idx].val = succ_prob[i]; + m_idx[prob]++; + } + dfs(n, visited, 1.0, &ans, start, end, cn, map); + free(visited); + for (int i = 0; i < n; i++) + if (cn[i]) + free(map[i]); + free(cn); + free(map); + return ans; +} diff --git a/path_max_probability.cpp b/path_max_probability.cpp new file mode 100644 index 0000000..12eb644 --- /dev/null +++ b/path_max_probability.cpp @@ -0,0 +1,53 @@ +// 1514. Path with Maximum Probability +#include "leetcode.h" + +/* + * given an undirected weighted graph of 'n' nodes (0-indexed). represented by + * an edge list where 'edges[i] = [a, b]' is an undirected edge connecting the + * nodes 'a' and 'b' with a probability of success of traversing that edge + * 'succ_prob[i]'. given two nodes 'start, end', find the path with the maximum + * probability of success to go from 'start' to 'end' and return its success + * probability. if there is no path from 'start' to 'end', return 0. your answer + * will be accepted if it differs from the correct answer by at most '1e-5' + */ + +class Solution { +public: + double maxProbability(int n, vvd(int) & edges, vector<double> &succ_prob, + int start, int end) { + vector<vector<pair<int, double>>> vvp(n); + for (int i = 0; i < edges.size(); i++) { + vvp[edges[i][0]].push_back({edges[i][1], succ_prob[i]}); + vvp[edges[i][1]].push_back({edges[i][0], succ_prob[i]}); + } + vector<int> seen(n, 0); + priority_queue<pair<double, int>> pqp; + pqp.push({(double)1.0, start}); + vector<double> mx(n, (double)0.0); + mx[start] = 1.0; + while (!pqp.empty()) { + auto top = pqp.top(); + pqp.pop(); + double prob_a = top.first; + int node = top.second; + if (!seen[node]) { + seen[node]++; + for (auto to : vvp[node]) { + if (mx[to.first] < to.second * prob_a) { + mx[to.first] = to.second * prob_a; + pqp.push({mx[to.first], to.first}); + } + } + } + } + return mx[end]; + } +}; + +int main() { + Solution obj; + vvd(int) e = {{0, 1}, {1, 2}, {0, 2}}; + vector<double> sp1 = {0.5, 0.5, 0.2}, sp2 = {0.5, 0.5, 0.3}; + printf("%f\n", obj.maxProbability(3, e, sp1, 0, 2)); // expect: 0.25000 + printf("%f\n", obj.maxProbability(3, e, sp2, 0, 2)); // expect: 0.30000 +} diff --git a/path_min_effort.c b/path_min_effort.c new file mode 100644 index 0000000..afabf1c --- /dev/null +++ b/path_min_effort.c @@ -0,0 +1,53 @@ +// 1631. Path With Minimum Effort +#include <math.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * you are a hiker preparing for an upcoming hike. you are given 'heights', a 2d + * array size 'rows * columsn', where 'heights[row][col]' represents the height + * of cell '(row, ccol)'. you are situated in the top-left cell, '(rows - 1, + * cols - 1)'. you can move up down left or right. and you wish to find a route + * that requires the minimum effort. a route's effort is the maximum absolute + * difference in heights between two consecutive cells of the route. return the + * minimum effor required to travel from the top left cell to the bottom right + * cell. + */ + +int minimumEfforPath(int **heights, int heights_size, int *heights_col_size) { + int r = heights_size, c = *heights_col_size; + int dp[100][100]; + memset(dp, 0x7F, sizeof(dp)); + dp[0][0] = 0; + int dir[5] = {0, -1, 0, 1, 0}; + for (int k = 0; k < r * c; k++) { + bool stable = true; + for (int y = 0; y < r; y++) { + for (int x = 0; x < c; x++) { + for (int d = 0; d < 4; d++) { + int tx = x = dir[d]; + int ty = y + dir[d + 1]; + if (tx < 0 || tx == c || ty < 0 || ty == r) + continue; + int t = fmax(dp[ty][tx], abs(heights[ty][tx] - heights[y][x])); + if (t < dp[y][x]) { + stable = false; + dp[y][x] = t; + } + } + if (stable) + break; + } + } + } + return dp[r - 1][c - 1]; +} + +int main() { + int h1[3][3] = {{1, 2, 2}, {3, 8, 2}, {5, 3, 5}}, + h2[3][3] = {{1, 2, 3}, {3, 8, 4}, {5, 3, 5}}; + printf("%d\n", minimumEfforPath(h1, 3, (int *)3)); // expect: 2 + printf("%d\n", minimumEfforPath(h2, 3, (int *)3)); // expect: 1 +} diff --git a/path_min_effort.cpp b/path_min_effort.cpp new file mode 100644 index 0000000..0b93590 --- /dev/null +++ b/path_min_effort.cpp @@ -0,0 +1,34 @@ +#include "leetcode.h" + +class Solution { +public: + int minimumEffortPath(vector<vector<int>> &heights) { + int m = heights.size(), n = heights[0].size(); + int dirs[5] = {-1, 0, 1, 0, -1}; + vector<vector<int>> efforts(m, vector<int>(n, INT_MAX)); + priority_queue<pair<int, int>, vector<pair<int, int>>, + greater<pair<int, int>>> + pq; + pq.emplace(0, 0); + while (!pq.empty()) { + int effort = pq.top().first; + int x = pq.top().second / 100, y = pq.top().second % 100; + pq.pop(); + if (x == m - 1 && y == n - 1) + return effort; + if (effort >= efforts[x][y]) + continue; + efforts[x][y] = effort; + for (int i = 0; i < 4; i++) { + int nX = x + dirs[i], nY = +dirs[i + 1]; + if (nX < 0 || nX >= m || nY < 0 || nY >= n) + continue; + int nEffort = max(effort, abs(heights[x][y] - heights[nX][nY])); + pq.emplace(nEffort, nX * 100 + nY); + } + } + return -1; + } +}; + +int min() {} diff --git a/path_min_effort.py b/path_min_effort.py new file mode 100644 index 0000000..c95f493 --- /dev/null +++ b/path_min_effort.py @@ -0,0 +1,23 @@ +class Solution:
+ def minimumEffortPath(self, heights):
+ m, n = len(heights), len(heights[0])
+ neibs = [[1, 0], [0, 1], [-1, 0], [0, -1]]
+
+ def dfs(LIMIT, x, y):
+ visited.add((x, y))
+ for dx, dy in neibs:
+ if 0<=dx+x<m and 0<=dy+y<n and (dx+x, dy+y) not in visited:
+ if abs(heights[x][y] - heights[dx+x][dy+y]) <= LIMIT:
+ dfs(LIMIT, dx+x, dy+y)
+
+ beg, end = -1, max(max(heights, key=max))
+ while beg + 1 < end:
+ mid = (beg + end)//2
+ visited = set()
+ dfs(mid, 0, 0)
+ if (m - 1, n - 1) in visited:
+ end = mid
+ else:
+ beg = mid
+
+ return end diff --git a/path_min_effort1.cpp b/path_min_effort1.cpp new file mode 100644 index 0000000..d9066cd --- /dev/null +++ b/path_min_effort1.cpp @@ -0,0 +1,42 @@ +#include "leetcode.h" +#include <algorithm> +#include <climits> +#include <cmath> +#include <functional> +#include <utility> +#include <vector> + +class Solution { + const int d4x[4] = {-1, 0, 1, 0}, d4y[4] = {0, 1, 0, -1}; + +public: + int minimumEffortPath(vector<vector<int>> &heights) { + int n = heights.size(), m = heights[0].size(); + priority_queue<pair<int, int>, vector<pair<int, int>>, + greater<pair<int, int>>> + pq; + vector<vector<int>> dis(n, vector<int>(m, INT_MAX)); + dis[0][0] = 0; + pq.push({0, {0, 0}}); + while (!pq.empty()) { + pair<int, pair<int, int>> curr = pq.top(); + pq.pop(); + int d = curr.first, r = curr.second.first, c = curr.second.second; + if (r == n - 1 && c == m - 1) + return d; + for (int i = 0; i < 4; ++i) { + int nX = r + d4x[i], nY = x + d4y[i]; + if (nX < 0 || nX >= n || nY < 0 || nY >= m) + continue; + int nD = max(d, abs(h[nX][nY] - h[r][c])); + if (nD < dis[nX][nY]) { + dis[nX][nY] = nD; + pq.push({nD, {nX, nY}}); + } + } + } + return 0; + } +}; + +int main() {} diff --git a/path_sum.cpp b/path_sum.cpp new file mode 100644 index 0000000..41498ca --- /dev/null +++ b/path_sum.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + bool hasPathSum(TreeNode *root, int targetSum) { + if (root == NULL) + return false; + stack<pair<TreeNode *, int>> s; + s.push({root, root->val}); + while (!s.empty()) { + TreeNode *curr = s.top().first; + int total = s.top().second; + s.pop(); + if (curr->right) + s.push({curr->right, total + curr->right->val}); + if (curr->left) + s.push({curr->left, total + curr->left->val}); + if (!curr->right && !curr->left && total == targetSum) + return true; + } + return false; + } +}; diff --git a/path_sum2.cpp b/path_sum2.cpp new file mode 100644 index 0000000..3e64ee3 --- /dev/null +++ b/path_sum2.cpp @@ -0,0 +1,25 @@ +#include "leetcode.h" + +class Solution { +public: + vvd(int) pathSum(TreeNode *root, int targetSum) { + vvd(int) ans; + vector<int> d; + dfs(root, targetSum, d, ans); + return ans; + } + +private: + void dfs(TreeNode *root, int targetSum, vector<int> d, vvd(int) & ans) { + if (root == NULL) + return; + d.push_back(root->val); + targetSum -= root->val; + if (targetSum == 0 && root->left == NULL && root->right == NULL) { + ans.push_back(d); + return; + } + dfs(root->left, targetSum, d, ans); + dfs(root->right, targetSum, d, ans); + } +}; diff --git a/peak_idx_mountain_arr.c b/peak_idx_mountain_arr.c new file mode 100644 index 0000000..7ffe4f1 --- /dev/null +++ b/peak_idx_mountain_arr.c @@ -0,0 +1,21 @@ +// 852. Peak Index in a Mountain Array +#include <stdio.h> + +int peakIndexInMountainArray(int *arr, int arr_size) { + int left = 1, right = arr_size - 1; + while (left < right) { + int mid = (left + right) / 2; + if (arr[mid] < arr[mid + 1]) + left = mid + 1; + else + right = mid; + } + return left; +} + +int main() { + int a1[] = {0, 1, 0}, a2[] = {0, 2, 1, 0}, a3[] = {0, 10, 5, 2}; + printf("%d\n", peakIndexInMountainArray(a1, 3)); // expect: 1 + printf("%d\n", peakIndexInMountainArray(a2, 4)); // expect: 1 + printf("%d\n", peakIndexInMountainArray(a3, 4)); // expect: 1 +} diff --git a/peak_idx_mountain_arr.cpp b/peak_idx_mountain_arr.cpp new file mode 100644 index 0000000..2900091 --- /dev/null +++ b/peak_idx_mountain_arr.cpp @@ -0,0 +1,25 @@ +// 852. Peak Index in a Mountain Array +#include "leetcode.h" + +class Solution { +public: + int peakIndexInMountainArray(vector<int> &arr) { + int left = 1, right = arr.size() - 1; + while (left < right) { + int mid = (left + right) / 2; + if (arr[mid] < arr[mid + 1]) + left = mid + 1; + else + right = mid; + } + return left; + } +}; + +int main() { + Solution obj; + vector<int> a1 = {0, 1, 0}, a2 = {0, 2, 1, 0}, a3 = {0, 10, 5, 2}; + printf("%d\n", obj.peakIndexInMountainArray(a1)); // expect: 1 + printf("%d\n", obj.peakIndexInMountainArray(a2)); // expect: 1 + printf("%d\n", obj.peakIndexInMountainArray(a3)); // expect: 1 +} diff --git a/peeking_iterator.cpp b/peeking_iterator.cpp new file mode 100644 index 0000000..1c4d0b9 --- /dev/null +++ b/peeking_iterator.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class Iterator { + struct Data; + Data *data; + +public: + Iterator(const vector<int> &nums); + Iterator(const Iterator &iter); + int next(); + bool hasNext() const; +}; + +class PeekingIterator : public Iterator { +public: + int nextVal; + PeekingIterator(const vector<int> &nums) : Iterator(nums) { + nextVal = Iterator::next(); + } + int peek() { return nextVal; } + int next() { + int tmp = nextVal; + if (Iterator::hasNext()) + nextVal = Iterator::next(); + else + nextVal = NULL; + return tmp; + } + bool hasNext() const { return (nextVal != NULL); } +}; + +int main() {} diff --git a/percentage_letter_string.cpp b/percentage_letter_string.cpp new file mode 100644 index 0000000..18744ea --- /dev/null +++ b/percentage_letter_string.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + int percentageLetter(string s, char letter) { + int n = s.size(); + int freq = 0; + for (int i = 0; i < n; i++) + if (s[i] == letter) + freq++; + return (freq * 100) / n; + } +}; + +int main() { + string s = "foobar"; + char letter = 'o'; + Solution obj; + cout << obj.percentageLetter(s, letter); +} diff --git a/perfect_squares.c b/perfect_squares.c new file mode 100644 index 0000000..3510bf6 --- /dev/null +++ b/perfect_squares.c @@ -0,0 +1,45 @@ +// 279. Perfect Squares +#include "leetcode.h" + +/* + * given an integer 'n', return the least number of perfect square numbers that + * sum to 'n'. a perfect square is an integer that is the square of an integer; + * in other words, it is the product of some integer with itself. for example, + * 1,4,9,16 are perfect squares while 3 and 11 are not. + */ + +int numSquares(int n) { + int *dp = (int *)malloc((n + 1) * sizeof(int)); + for (int i = 0; i <= n; i++) + dp[i] = INT_MAX; + dp[0] = INT_MAX; + if (n > 0) + dp[1] = 1; + if (n > 1) + dp[2] = 2; + if (n > 2) + dp[3] = 3; + if (n > 3) + dp[4] = 1; + int k, tmp; + for (int i = 5; i <= n; i++) { + k = sqrt(i); + if (k * k == i) { + dp[i] = 1; + continue; + } + for (int j = 1; j <= k; j++) { + tmp = j * j; + if (dp[tmp] + dp[i - tmp] < dp[i]) + dp[i] = dp[tmp] + dp[i - tmp]; + } + } + int ans = dp[n]; + free(dp); + return ans; +} + +int main() { + printf("%d\n", numSquares(12)); // expect: 3 + printf("%d\n", numSquares(13)); // expect: 2 +} diff --git a/perfect_squares.cpp b/perfect_squares.cpp new file mode 100644 index 0000000..677c4a0 --- /dev/null +++ b/perfect_squares.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + int numSquares(int n) { + vector<int> dp(n + 1, INT_MAX); + dp[0] = 0; + for (int target = 1; target <= n; target++) { + int mmCount = INT_MAX; + for (int num = 1; num <= sqrt(target); num++) { + int sqNum = pow(num, 2), curr = 1 + dp[target - sqNum]; + mmCount = min(mmCount, curr); + } + dp[target] = mmCount; + } + return dp[n]; + } +}; + +int main() { + Solution obj; + cout << obj.numSquares(12); +} diff --git a/perfect_squares.py b/perfect_squares.py new file mode 100644 index 0000000..7d87d80 --- /dev/null +++ b/perfect_squares.py @@ -0,0 +1,43 @@ +# 279. Perfect Squares + +""" +given an integer 'n', return the least number of perfect square numbers that +sum to 'n'. a perfect square is an integer that is the square of an integer; +in other words, it is the product of some integer with itself. for example, +1,4,9,16 are perfect squares while 3 and 11 are not. +""" + + +class Solution(object): + def numSquares(self, n): + """ + :type n: int + :rtype: int + """ + if n < 2: + return n + lst = [] + i = 1 + while i * i <= n: + lst.append(i * i) + i += 1 + cnt = 0 + to_check = {n} + while to_check: + cnt += 1 + tmp = set() + for x in to_check: + for y in lst: + if x == y: + return cnt + if x < y: + break + tmp.add(x - y) + to_check = tmp + return cnt + + +if __name__ == "__main__": + obj = Solution() + print(obj.numSquares(12)) + print(obj.numSquares(13)) diff --git a/perfect_squares.rs b/perfect_squares.rs new file mode 100644 index 0000000..3887e40 --- /dev/null +++ b/perfect_squares.rs @@ -0,0 +1,21 @@ +use std::cmp::min; +struct Solution; + +impl Solution { + pub fn num_squares(n: i32) -> i32 { + let mut dp: Vec<i32> = vec![std::i32::MAX; n as usize + 1]; + dp[0] = 0; + for i in 1..(n as usize + 1) { + let mut j: usize = 1; + while j * j <= i { + dp[i] = min(dp[i], dp[i - j * j] + 1); + j += 1; + } + } + dp[n as usize] + } +} + +fn main() { + print!("{}", Solution::num_squares(12)); +} diff --git a/permutation_in_string.c b/permutation_in_string.c new file mode 100644 index 0000000..b6d0878 --- /dev/null +++ b/permutation_in_string.c @@ -0,0 +1,37 @@ +// 567. Permutation in String +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given two strings 's1 s2' return true if 's2' contains a permutation of 's1' + * or false otherwise. in other words, return true if one of 's1's permutations + * is in the substring of 's2' + */ + +bool checkInclusion(char *s1, char *s2) { + int len1 = strlen(s1), len2 = strlen(s2); + if (len1 > len2) + return false; + int freq1[128] = {0}, freq2[128] = {0}; + for (int i = 0; i < len1; i++) { + freq1[s1[i]]++; + freq2[s2[i]]++; + } + if (memcmp(freq1, freq2, sizeof(freq1)) == 0) + return true; + for (int i = len1; i < len2; i++) { + --freq2[s2[i - len1]]; + ++freq2[s2[i]]; + if (memcmp(freq1, freq2, sizeof(freq1)) == 0) + return true; + } + return false; +} + +int main() { + char s[] = "ab", s1[] = "eidbaooo", s2[] = "eidboaoo"; + printf("%d\n", checkInclusion(s, s1)); // expect: 1 + printf("%d\n", checkInclusion(s, s2)); // expect: 1 +} diff --git a/permutation_in_string.cpp b/permutation_in_string.cpp new file mode 100644 index 0000000..f4e09f3 --- /dev/null +++ b/permutation_in_string.cpp @@ -0,0 +1,47 @@ +// 567. Permutation in String +#include "leetcode.h" + +/* + * given two strings 's1 s2' return true if 's2' contains a permutation of 's1' + * or false otherwise. in other words, return true if one of 's1's permutations + * is in the substring of 's2' + */ + +class Solution { +public: + bool checkInclusion(string s1, string s2) { + if (s2.size() < s1.size()) + return false; + vector<int> freq1(26, 0), freq2(26, 0); + for (char c : s1) + freq1[c - 'a']++; + int i = 0, j = 0; + while (j < s2.size()) { + freq2[s2[j] - 'a']++; + if (j - i + 1 == s1.size()) + if (cmp(freq1, freq2)) + return true; + if (j - i + 1 < s1.size()) + j++; + else { + freq2[s2[i] - 'a']--; + i++, j++; + } + } + return false; + } + +private: + bool cmp(vector<int> a, vector<int> b) { + for (int i = 0; i < 26; i++) + if (a[i] != b[i]) + return false; + return true; + } +}; + +int main() { + Solution obj; + cout << obj.checkInclusion("ab", "eidbaooo") << endl; // expect: 1 + cout << obj.checkInclusion("ab", "eidboaoo") << endl; // expect: 0 +} diff --git a/permutation_sequence.c b/permutation_sequence.c new file mode 100644 index 0000000..15cc7a3 --- /dev/null +++ b/permutation_sequence.c @@ -0,0 +1,42 @@ +// 60. Permutation Sequence +#include "leetcode.h" + +/* + * the set '[1,2,3, ..., n]' contains a total of 'n!' unique permutations. by + * listing and labeling all of the permutations in order, we get the following + * sequence for 'n = 3' 123, 132, 213, 231, 312, 321 given 'n' and 'k', return + * the k'th permutation sequence + */ + +int cmp(const void *a, const void *b) { return *(char *)a - *(char *)b; } + +void next_permutation(char *nums, int nums_size) { + for (int i = nums_size - 2; i >= 0; i--) + if (nums[i] < nums[i + 1]) { + qsort(&nums[i + 1], nums_size - (i + 1), sizeof(char), cmp); + for (int j = i + 1; j < nums_size; j++) + if (nums[j] > nums[i]) { + char tmp = nums[i]; + nums[i] = nums[j]; + nums[j] = tmp; + return; + } + } + qsort(nums, nums_size, sizeof(char), cmp); +} + +char *getPermutation(int n, int k) { + char *ans = malloc((n + 1) * sizeof(char)); + ans[n] = '\0'; + for (int i = 0; i < n; i++) + ans[i] = '1' + i; + for (int i = 1; i < k; i++) + next_permutation(ans, n); + return ans; +} + +int main() { + printf("%s\n", getPermutation(3, 3)); // expect: 213 + printf("%s\n", getPermutation(4, 9)); // expect: 2314 + printf("%s\n", getPermutation(3, 1)); // expect: 123 +} diff --git a/permutation_sequence.cpp b/permutation_sequence.cpp new file mode 100644 index 0000000..a77286b --- /dev/null +++ b/permutation_sequence.cpp @@ -0,0 +1,25 @@ +#include "leetcode.h" +#include <vector> + +class Solution { +public: + vector<int> fact; + string getPermutation(int n, int k) { int n = k - 1; } + +private: + void helper(int k) { + fact = vector<int>(k); + fact[0] = 1; + if (k == 1) + return; + fact[1] = 1; + for (int i = 2; i < k; i++) + fact[i] = i * fact[i - 1]; + } +}; + +int main() { + Solution obj; + int n = 3, k = 3; + cout << obj.getPermutation(n, k); +} diff --git a/permutation_sequence.py b/permutation_sequence.py new file mode 100644 index 0000000..96d8377 --- /dev/null +++ b/permutation_sequence.py @@ -0,0 +1,29 @@ +# 60. Permutation Sequence +import math + +""" +the set '[1,2,3, ..., n]' contains a total of 'n!' unique permutations. by +listing and labeling all of the permutations in order, we get the following +sequence for 'n = 3' 123, 132, 213, 231, 312, 321 given 'n' and 'k', return +the k'th permutation sequence +""" + + +class Solution(object): + def getPermutation(self, n, k): + nums = range(1, n + 1) + permutation = "" + k -= 1 + while n > 0: + n -= 1 + idx, k = divmod(k, math.factorial(n)) + permutation += str(nums[idx]) + nums.remove(nums[idx]) + return permutation + + +if __name__ == "__main__": + obj = Solution() + print(obj.getPermutation(3, 3)) # expect: 213 + print(obj.getPermutation(4, 9)) # expect: 2314 + print(obj.getPermutation(3, 1)) # expect: 123 diff --git a/permutations.c b/permutations.c new file mode 100644 index 0000000..38caf69 --- /dev/null +++ b/permutations.c @@ -0,0 +1,58 @@ +// 46. Permutations +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array 'nums' of distinct integers, return all the possible + * permutations. you can return the answer in any order + */ + +void swap(int *p, int *q) { + int tmp = *p; + *p = *q; + *q = tmp; +} + +void search(int *nums, int nums_size, int ***arr, int *return_size, int begin, + int end) { + if (begin == end) { + (*return_size)++; + *arr = (int **)realloc(*arr, sizeof(int *) * (*return_size)); + (*arr)[*return_size - 1] = (int *)malloc(sizeof(int) * nums_size); + for (int i = 0; i < nums_size; i++) + (*arr)[*return_size - 1][i] = nums[i]; + return; + } + for (int i = begin; i <= end; i++) { + swap(nums + begin, nums + i); + search(nums, nums_size, arr, return_size, begin + 1, end); + swap(nums + begin, nums + i); + } +} + +int **permute(int *nums, int nums_size, int *return_size, + int **return_col_size) { + *return_size = 0; + int **ans = (int **)malloc(sizeof(int *)); + search(nums, nums_size, &ans, return_size, 0, nums_size - 1); + return ans; +} + +int main() { + int n1[] = {1, 2, 3}, n2[] = {0, 1}, n3[] = {1}; + int **p1 = permute(n1, 3, NULL, NULL); + int **p2 = permute(n2, 2, NULL, NULL); + int **p3 = permute(n3, 1, NULL, NULL); + for (int i = 0; i < 6; i++) + for (int j = 0; j < 3; j++) + printf("%d ", p1[i][j]); + printf("\n"); + for (int i = 0; i < 6; i++) + for (int j = 0; j < 3; j++) + printf("%d ", p2[i][j]); + printf("\n"); + for (int i = 0; i < 6; i++) + for (int j = 0; j < 3; j++) + printf("%d ", p3[i][j]); + printf("\n"); +} diff --git a/permutations.cpp b/permutations.cpp new file mode 100644 index 0000000..2e86fc0 --- /dev/null +++ b/permutations.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + vector<vector<int>> permute(vector<int> &nums) { + vector<vector<int>> ans; + int idx = 0; + helper(nums, ans, idx); + return ans; + } + +private: + void helper(vector<int> &nums, vector<vector<int>> &ans, int idx) { + if (idx >= nums.size()) { + ans.push_back(nums); + return; + } + for (int i = idx; i < nums.size(); i++) { + swap(nums[idx], nums[i]); + helper(nums, ans, idx + 1); + swap(nums[idx], nums[i]); + } + } +}; + +int main() {} diff --git a/permutations2.cpp b/permutations2.cpp new file mode 100644 index 0000000..16d0162 --- /dev/null +++ b/permutations2.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +class Solution { +public: + vector<vector<int>> permuteUnique(vector<int> &nums) { + vector<vector<int>> ans; + helper(0, nums, ans); + return ans; + } + +private: + void helper(int i, vector<int> &nums, vector<vector<int>> &ans) { + if (i == nums.size()) { + ans.emplace_back(nums); + return; + } + unordered_set<int> us; + for (int j = i; j < nums.size(); j++) { + if (us.count(nums[j]) == 1) + continue; + us.insert(nums[j]); + swap(nums[i], nums[j]); + helper(i + 1, nums, ans); + swap(nums[i], nums[j]); + } + } +}; + +int main() {} diff --git a/poor-pigs.cpp b/poor-pigs.cpp new file mode 100644 index 0000000..7455583 --- /dev/null +++ b/poor-pigs.cpp @@ -0,0 +1,8 @@ +#include "leetcode.h" + +class Solution { +public: + int poorPigs(int buckets, int poisonTime, int totalTime) { + return ceil(log(buckets) / log(totalTime / poisonTime + 1)); + } +}; diff --git a/populating_right_pointer.cpp b/populating_right_pointer.cpp new file mode 100644 index 0000000..d977321 --- /dev/null +++ b/populating_right_pointer.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class Solution { +public: + Node *connect(Node *root) { + Node *currParent = root, *baseChild, *currChild, *nextChild; + while (currParent) { + while (currParent->next && !currParent->left && !currParent->right) + currParent = currParent->next; + currChild = baseChild = + currParent->left ? currParent->left : currParent->right; + while (currChild) { + if (currParent->right && currChild != currParent->right) + nextChild = currParent->right; + else { + currParent = currParent->next; + while (currParent && !currParent->left && !currParent->right) + currParent = currParent->next; + nextChild = currParent ? currParent->left ? currParent->left + : currParent->right + : currParent; + } + currChild->next = nextChild; + currChild = nextChild; + } + currParent = baseChild; + } + return root; + } +}; + +int main() {} diff --git a/possible_bipartition.cpp b/possible_bipartition.cpp new file mode 100644 index 0000000..8566e9f --- /dev/null +++ b/possible_bipartition.cpp @@ -0,0 +1,45 @@ +#include "leetcode.h" + +class Solution { +public: + bool possibleBipartition(int n, vvd(int) & dislikes) { + enum color { green = -1, uncolored, blue }; + if (n == 1 || dislikes.size() == 0) + return true; + unordered_map<int, vector<int>> dislikeTable; + unordered_map<int, int> colorTable; + function<bool(int, int)> helper; + helper = [&](int personID, int color) -> bool { + colorTable[personID] = color; + for (const int &other : dislikeTable[personID]) { + if (colorTable[other] == color) + return false; + if (colorTable[other] == uncolored && (!helper(other, -color))) + return false; + } + return true; + }; + for (const auto &relation : dislikes) { + int p1 = relation[0], p2 = relation[1]; + dislikeTable[p1].emplace_back(p2); + dislikeTable[p2].emplace_back(p1); + } + for (int i = 1; i <= n; i++) + if (colorTable[i] == uncolored && (!helper(i, blue))) + return false; + return true; + } +}; + +int main() { + Solution obj; + vvd(int) dislikes1 = {{1, 2}, {1, 3}, {2, 4}}, + dislikes2 = {{1, 2}, {1, 3}, {2, 3}}, + dislikes3 = {{1, 2}, {2, 3}, {3, 4}, {4, 5}, {1, 5}}; + testBool(obj.possibleBipartition(4, dislikes1)); + // true: [2,3] [1,4] + testBool(obj.possibleBipartition(3, dislikes2)); + // false + testBool(obj.possibleBipartition(5, dislikes3)); + // false +} diff --git a/possible_bipartition.rs b/possible_bipartition.rs new file mode 100644 index 0000000..13b8cf5 --- /dev/null +++ b/possible_bipartition.rs @@ -0,0 +1,40 @@ +use std::collections::VecDeque; +struct Solution; + +impl Solution { + pub fn possible_bipartition(n: i32, dislikes: Vec<Vec<i32>>) -> bool { + let mut dmap: Vec<Vec<usize>> = vec![vec![]; n as usize]; + for d in dislikes.iter() { + dmap[d[0] as usize - 1].push(d[1] as usize - 1); + dmap[d[1] as usize - 1].push(d[0] as usize - 1); + } + let mut v: Vec<Option<bool>> = vec![None; n as usize]; + for i in 0..n as usize { + if v[i].is_some() { + continue; + } + let mut vd: VecDeque<(usize, bool)> = VecDeque::new(); + vd.push_back((i, true)); + while let Some(last) = vd.pop_front() { + if let Some(b) = v[last.0] { + if b != last.1 { + return false; + } + continue; + } + v[last.0] = Some(last.1); + for j in dmap[last.0].iter() { + if v[*j].is_none() { + vd.push_back((*j, !last.1)); + } + } + } + } + true + } +} + +fn main() { + let dislikes = vec![vec![1,2], vec![1,3], vec![2,4]]; + print!("{}", Solution::possible_bipartition(4, dislikes)); +} diff --git a/pow_xn.c b/pow_xn.c new file mode 100644 index 0000000..9baec1b --- /dev/null +++ b/pow_xn.c @@ -0,0 +1,31 @@ +// 50. Pow(x, n)50. Pow(x, n) +#include <limits.h> +#include <stdio.h> + +/* + * implement 'pow(x, n)', which calculates 'x' raised to the power 'n' (i.e. + * x^n) + */ + +double myPow(double x, int n) { + if (x == 1.0) + return x; + if (x == -1.0) + return (n % 2 ? -1.0 : 1.0); + if (n == INT_MIN) + return 0; + double ans = 1; + if (n < 0) { + x = 1 / x; + n = -n; + } + for (int i = 0; i < n && ans * x != ans; i++) + ans *= x; + return ans; +} + +int main() { + printf("%f\n", myPow(2, 10)); // expect: 1024.00000 + printf("%f\n", myPow(2.1, 3)); // expect: 9.26100 + printf("%f\n", myPow(2, -2)); // expect: 0.25000 +} diff --git a/pow_xn.cpp b/pow_xn.cpp new file mode 100644 index 0000000..f64161f --- /dev/null +++ b/pow_xn.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + double myPow(double x, int n) { + if (n < 0) + x = 1 / x; + long num = labs(n); + double pow = 1; + while (num) { + if (num & 1) + pow *= x; + x *= x; + num >>= 1; + } + return pow; + } +}; + +int main() {} diff --git a/power_3.cpp b/power_3.cpp new file mode 100644 index 0000000..f92e6e3 --- /dev/null +++ b/power_3.cpp @@ -0,0 +1,19 @@ +#include "leetcode.h" + +class Solution { +public: + bool isPowerOfThree(int n) { + if (n > 1) + while (n % 3 == 0) + n /= 3; + return n == 1; + } +}; + +int main() { + Solution obj; + if (obj.isPowerOfThree(27)) + cout << "true"; + else + cout << "false"; +} diff --git a/power_of_four.c b/power_of_four.c new file mode 100644 index 0000000..7ab3cae --- /dev/null +++ b/power_of_four.c @@ -0,0 +1,28 @@ +// 342. Power of Four +#include <stdbool.h> +#include <stdio.h> + +/* + * given an integer 'n', return 'true' if it is a power of four, otherwise, + * return 'false'. an integer 'n' is a power of four if there exists an integer + * 'x' such that 'n == 4^x' + */ + +bool isPowerOfFour(int n) { + int ans = 0, pos = 1, ones = 0; + while (n) { + if (n & 1) { // if 'n' is even... + ans++; + ones = pos; + } + n >>= 1; // 'n' / 2 + pos++; + } + return ans == 1 && ones & 1; +} + +int main() { + printf("%d\n", isPowerOfFour(16)); // expect: 1 + printf("%d\n", isPowerOfFour(5)); // expect: 0 + printf("%d\n", isPowerOfFour(1)); // expect: 1 +} diff --git a/power_of_four.cpp b/power_of_four.cpp new file mode 100644 index 0000000..ecf6de0 --- /dev/null +++ b/power_of_four.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + bool isPowerOfFour(int num) { + if (num < 0) + return false; + int ans = 0, pos = 1, ones = 0; + while (num) { + if (num & 1) + ans += 1, ones = pos; + num >>= 1, pos += 1; + } + return ans == 1 && ones & 1; + } +}; + +int main() { + Solution obj; + if (obj.isPowerOfFour(16)) + cout << "true"; + else + cout << "false"; +} diff --git a/power_of_four.py b/power_of_four.py new file mode 100644 index 0000000..13a0dc5 --- /dev/null +++ b/power_of_four.py @@ -0,0 +1,19 @@ +# 342. Power of Four + +""" +given an integer 'n', return 'true' if it is a power of four, otherwise, +return 'false'. an integer 'n' is a power of four if there exists an integer +'x' such that 'n == 4^x' +""" + + +class Solution(object): + def isPowerOfFour(self, n): + return n != 0 and n & (n - 1) == 0 and n & 1431655765 == n + + +if __name__ == "__main__": + obj = Solution() + print(obj.isPowerOfFour(16)) # expect: True + print(obj.isPowerOfFour(5)) # expect: False + print(obj.isPowerOfFour(1)) # expect: True diff --git a/power_of_four.rs b/power_of_four.rs new file mode 100644 index 0000000..f20335f --- /dev/null +++ b/power_of_four.rs @@ -0,0 +1,24 @@ +//INCOMPLETE +struct Solution; + +impl Solution { + pub fn is_power_of_four(num: i32) -> bool { + if num < 0 { + return false; + } + let (ans, pos, ones) = (0, 1, 0); + while num { + if num & 1 { + ans += 1; + ones = pos; + } + num >>= 1; + pos += 1; + } + ans == 1 && ones & 1 + } +} + +fn main() { + print!("{}", Solution::is_power_of_four(16)); +} diff --git a/power_of_three.c b/power_of_three.c new file mode 100644 index 0000000..d76dc75 --- /dev/null +++ b/power_of_three.c @@ -0,0 +1,34 @@ +// 326. Power of Three +#include "leetcode.h" + +/* + * power of 3 | decimal | bit + * -----------|---------|------ + * 3^0 | 1 | 00001 + * 3^1 | 3 | 00011 + * 3^2 | 9 | 01001 + * 3^3 | 27 | 11011 + * + * notice pattern in above bits: + * 3^1: 0b0001 + 0b0010 = 0b0011 (3) + * 3^2: 0b0011 + 0b0110 = 0b1001 (9) + * 3^3: 0b1001 + 0b10010 = 0b11011 (27) + * + * we can keep shifting 'tmp' left by 1 until 'n' is reached. initialise 'tmp' + * to 1 because the least power of 3 can be 0. if 'tmp' is exactly 'n', it is + * divisible by 3. returns false automatically when 'n' is negative + */ + +bool isPowerOfThree(int n) { + long tmp = 1; + while (tmp < n) + tmp += tmp << 1; + return tmp == n; +} + +int main() { + printf("%d\n", isPowerOfThree(27)); // expect: 1 + printf("%d\n", isPowerOfThree(0)); // expect: 0 + printf("%d\n", isPowerOfThree(-1)); // expect: 0 + printf("%d\n", isPowerOfThree(6561)); // expect: 1 +} diff --git a/power_of_three.py b/power_of_three.py new file mode 100644 index 0000000..7349ee4 --- /dev/null +++ b/power_of_three.py @@ -0,0 +1,20 @@ +# 326. Power of Three + + +class Solution(object): + def isPowerOfThree(self, n): + """ + the positive divisors of 3^19 are exactly the powers of 3 + from 3^0 to 3^19. that's all powers of 3 in the possible range + here (signed 32-bit integer). so check whether the number is + positive and whether it divides 3^19 + """ + return n > 0 == 3**19 % n + + +if __name__ == "__main__": + obj = Solution() + print(obj.isPowerOfThree(27)) + print(obj.isPowerOfThree(0)) + print(obj.isPowerOfThree(-1)) + print(obj.isPowerOfThree(6561)) diff --git a/power_of_two.c b/power_of_two.c new file mode 100644 index 0000000..0be3ced --- /dev/null +++ b/power_of_two.c @@ -0,0 +1,20 @@ +// 231. Power of Two +#include "leetcode.h" + +/* + * given an integer 'n', return true if it is a power of two. otherwise, return + * false. an integer 'n' is a power of two if there exists an integer 'x' such + * that 'n == 2^x' + */ + +bool isPowerOfTwo(int n) { + if (n <= 0) + return 0; + return !(n & (n - 1)); +} + +int main() { + printf("%d\n", isPowerOfTwo(1)); // expect: 1 + printf("%d\n", isPowerOfTwo(16)); // expect: 1 + printf("%d\n", isPowerOfTwo(3)); // expect: 0 +} diff --git a/power_of_two.cpp b/power_of_two.cpp new file mode 100644 index 0000000..7e38aeb --- /dev/null +++ b/power_of_two.cpp @@ -0,0 +1,11 @@ +#include "leetcode.h" + +class Solution { +public: + bool isPowerOfTwo(int n) { if (n) } +}; + +int main() { + Solution obj; + obj.isPowerOfTwo(16); +} diff --git a/power_of_two.py b/power_of_two.py new file mode 100644 index 0000000..80dd7d0 --- /dev/null +++ b/power_of_two.py @@ -0,0 +1,24 @@ +# 231. Power of Two + +""" +given an integer 'n', return true if it is a power of two. otherwise, return +false. an integer 'n' is a power of two if there exists an integer 'x' such +that 'n == 2^x' +""" + + +class Solution(object): + def isPowerOfTwo(self, n): + """ + :type n: int + :rtype: bool + """ + if n <= 0: + return False + return not (n & (n - 1)) + +if __name__ == "__main__": + obj = Solution() + print(obj.isPowerOfTwo(1)) + print(obj.isPowerOfTwo(16)) + print(obj.isPowerOfTwo(3)) diff --git a/predict_winner.c b/predict_winner.c new file mode 100644 index 0000000..ed27618 --- /dev/null +++ b/predict_winner.c @@ -0,0 +1,37 @@ +// 486. Predict the Winner +#include <math.h> +#include <stdbool.h> +#include <stdio.h> + +/* + * given an integer array 'nums'. two players are playing a game with this + * array: player 1 and player 2. player 1 and player 2 take turns, with player 1 + * starting first. both players start the game with a score of zero. at each + * turn, the player takes one of the numbers from either end of the array (ie. + * 'nums[0]', or 'nums[nums.len - 1]') which reduces the size of the array by + * one. the player adds the chosen number to their score. the game ends when + * there are no more elements in the array. return 'true' if player 1 can win + * the game. if the scores of both players are equal, then player 1 is still the + * winner, and you should also return 'true'. you may assume that both players + * are playing optimally. + */ + +int get_score(int *nums, int left, int right) { + if (left == right) + return nums[left]; + return fmax(nums[left] - get_score(nums, left + 1, right), + nums[right] - get_score(nums, left, right - 1)); +} + +bool PredictTheWinner(int *nums, int nums_size) { + if (get_score(nums, 0, nums_size - 1) >= 0) + return true; + else + return false; +} + +int main() { + int n1[] = {1, 5, 2}, n2[] = {1, 5, 233, 7}; + printf("%d\n", PredictTheWinner(n1, 3)); // expect: 0 + printf("%d\n", PredictTheWinner(n2, 4)); // expect: 1 +} diff --git a/predict_winner.cpp b/predict_winner.cpp new file mode 100644 index 0000000..edf9ee3 --- /dev/null +++ b/predict_winner.cpp @@ -0,0 +1,40 @@ +// 486. Predict the Winner +#include "leetcode.h" + +/* + * given an integer array 'nums'. two players are playing a game with this + * array: player 1 and player 2. player 1 and player 2 take turns, with player 1 + * starting first. both players start the game with a score of zero. at each + * turn, the player takes one of the numbers from either end of the array (ie. + * 'nums[0]', or 'nums[nums.len - 1]') which reduces the size of the array by + * one. the player adds the chosen number to their score. the game ends when + * there are no more elements in the array. return 'true' if player 1 can win + * the game. if the scores of both players are equal, then player 1 is still the + * winner, and you should also return 'true'. you may assume that both players + * are playing optimally. + */ + +class Solution { + bool check_win(int ans, int total) { return ans >= total - ans; } + int max_score(vector<int> &nums, int total, int i, int j) { + if (i > j) + return 0; + return total - min(max_score(nums, total - nums[i], i + 1, j), + max_score(nums, total - nums[j], i, j - 1)); + } + +public: + bool PredictTheWinner(vector<int> &nums) { + int total = 0; + for (auto i : nums) + total += i; + return check_win(max_score(nums, total, 0, nums.size() - 1), total); + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 5, 2}, n2 = {1, 5, 233, 7}; + printf("%d\n", obj.PredictTheWinner(n1)); // expect: 0 + printf("%d\n", obj.PredictTheWinner(n2)); // expect: 1 +} diff --git a/prefix_suffix_search.cpp b/prefix_suffix_search.cpp new file mode 100644 index 0000000..67d4d4f --- /dev/null +++ b/prefix_suffix_search.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class WordFilter { +public: + WordFilter(vector<string> &words) { + int n = words.size(); + for (int i = 0; i < n; i++) { + string word = words[i]; + int wordSize = word.size(); + for (int j = 1; j <= wordSize; j++) { + string p = word.substr(0, j); + for (int k = 0; k < wordSize; k++) { + string s = word.substr(k, wordSize); + hashMap[p + '|' + s] = i + 1; + } + } + } + } + int f(string prefix, string suffix) { + string s = prefix + '|' + suffix; + return hashMap[s] - 1; + } + +private: + unordered_map<string, int> hashMap; +}; diff --git a/product_array_except_self.c b/product_array_except_self.c new file mode 100644 index 0000000..3a125da --- /dev/null +++ b/product_array_except_self.c @@ -0,0 +1,37 @@ +// 238. Product of Array Except Self +#include "leetcode.h" + +/* + * given an integer array 'nums' return an array 'answer' such that 'answer[i]' + * is equal to the product of all the elements of 'nums' except 'nums[i]'. the + * product of any prefix or suffix of 'nums' is guaranteed to fit in a 32-bit + * integer. you must write an algorithm that runs in O(n) time and without the + * division operation. + */ + +int *productExceptSelf(int *nums, int nums_size, int *return_size) { + int *ans = (int *)malloc(nums_size * sizeof(int)); + *return_size = nums_size; + ans[0] = 1; + for (int i = 1; i < nums_size; i++) + ans[i] = nums[i - 1] * ans[i - 1]; + int tmp = 1; + for (int i = nums_size - 1; i >= 0; i--) { + ans[i] *= tmp; + tmp *= nums[i]; + } + return ans; +} + +int main() { + int n1[] = {1, 2, 3, 4}, n2[] = {-1, 1, 0, -3, 3}; + int rs1[] = {}, rs2[] = {}; + int *pes1 = productExceptSelf(n1, ARRAY_SIZE(n1), rs1); + int *pes2 = productExceptSelf(n2, ARRAY_SIZE(n2), rs2); + for (int i = 0; i < ARRAY_SIZE(n1); i++) + printf("%d ", pes1[i]); // expect: 24 12 8 6 + printf("\n"); + for (int i = 0; i < ARRAY_SIZE(n2); i++) + printf("%d ", pes2[i]); // expect: 0 0 9 0 0 + printf("\n"); +} diff --git a/product_array_except_self.py b/product_array_except_self.py new file mode 100644 index 0000000..2a064ba --- /dev/null +++ b/product_array_except_self.py @@ -0,0 +1,35 @@ +# 238. Product of Array Except Self +from functools import reduce + +""" +given an integer array 'nums' return an array 'answer' such that 'answer[i]' +is equal to the product of all the elements of 'nums' except 'nums[i]'. the +product of any prefix or suffix of 'nums' is guaranteed to fit in a 32-bit +integer. you must write an algorithm that runs in O(n) time and without the +division operation. +""" + + +class Solution(object): + def productExceptSelf(self, nums): + """ + :type nums: List[int] + :rtype: List[int] + """ + prod, zero_cnt = reduce(lambda a, b: a * (b if b else 1), nums, 1), nums.count( + 0 + ) + if zero_cnt > 1: + return [0] * len(nums) + for i, c in enumerate(nums): + if zero_cnt: + nums[i] = 0 if c else prod + else: + nums[i] = prod // c + return nums + + +if __name__ == "__main__": + obj = Solution() + print(obj.productExceptSelf([1, 2, 3, 4])) + print(obj.productExceptSelf([-1, 1, 0, -3, 3])) diff --git a/profitable_schemes.cpp b/profitable_schemes.cpp new file mode 100644 index 0000000..d0f353a --- /dev/null +++ b/profitable_schemes.cpp @@ -0,0 +1,71 @@ +// 879. Profitable Schemes +#include "leetcode.h" + +/* + * there is a group of 'n' members, and a list of various crimes + * they could commit. the i'th crime generates a 'profit[i]' and + * requires 'group[i]' members to participate in it. if a member + * participates in one crime, that member cannot participate in + * another crime. a profitable scheme is any subset of these crimes + * that generates at least 'min_profit', and the total number of + * members participating in that subset of crimes is at most 'n' + * return the number of schemes that can be chosen. + */ + +struct scheme { + int n; + int min_profit; + vector<int> group; + vector<int> profit; +}; + +class Solution { + vector<int> g, p; + int mp, mod = 1e9 + 7, dp[101][101][101]; + int find(int id, int n, int total_profit) { + if (id == p.size()) + return 0; + if (dp[id][n][total_profit != -1]) + return dp[id][n][total_profit]; + int res = 0; + if (n >= g[id]) { + int new_profit = max(0, total_profit - p[id]); + if (new_profit <= 0) + res += (1 + find(id + 1, n - g[id], new_profit) % mod) % mod; + else + res += find(id + 1, n - g[id], new_profit) % mod; + } + res %= mod; + res += find(id + 1, n, total_profit) % mod; + res %= mod; + return dp[id][n][total_profit] = res % mod; + } + +public: + int profitableSchemes(int n, int min_profit, vector<int> &group, + vector<int> &profit) { + mp = min_profit; + p = profit; + g = group; + for (int i = 0; i < 101; i++) + for (int j = 0; j < 101; j++) + for (int k = 0; k < 101; k++) + dp[i][j][k] = -1; + int ans = find(0, n, mp) % mod; + if (!mp) + ans++; + ans %= mod; + return ans; + } +}; + +int main() { + Solution obj; + scheme one = {.n = 5, .min_profit = 3, .group = {2, 2}, .profit = {2, 3}}; + scheme two = { + .n = 10, .min_profit = 5, .group = {2, 3, 5}, .profit = {6, 7, 8}}; + printf("%d\n", obj.profitableSchemes(one.n, one.min_profit, one.group, + one.profit)); // expect: 2 + printf("%d\n", obj.profitableSchemes(two.n, two.min_profit, two.group, + two.profit)); // expect: 7 +} diff --git a/pseudo_palindrome_binary_tree.cpp b/pseudo_palindrome_binary_tree.cpp new file mode 100644 index 0000000..63b2cac --- /dev/null +++ b/pseudo_palindrome_binary_tree.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +class Solution { +public: + int pseudoPalindromicPaths(TreeNode *root) { + vector<int> v(10, 0); + dfs(root, v); + return count; + } + +private: + int count = 0; + void dfs(TreeNode *root, vector<int> v) { + if (root == NULL) + return; + v[root->val]++; + if (root->left == NULL && root->right == NULL) { + int oddCount = 0; + for (auto x : v) + if (x % 2) + oddCount++; + if (oddCount <= 1) + count++; + return; + } + dfs(root->left, v); + dfs(root->right, v); + } +}; diff --git a/push_dominoes.cpp b/push_dominoes.cpp new file mode 100644 index 0000000..859dad9 --- /dev/null +++ b/push_dominoes.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" +#include <string> + +class Solution { +public: + string pushDominoes(string dominoes) { + dominoes = 'L' + dominoes + 'R'; + string ans = ""; + for (int i = 0, j = 1; j < dominoes.size(); ++j) { + if (dominoes[j] == '.') + continue; + int middle = j - i - 1; + if (i > 0) + ans += dominoes[i]; + if (dominoes[i] == dominoes[j]) + ans += string(middle, dominoes[i]); + else if (dominoes[i] == 'L' && dominoes[j] == 'R') + ans += string(middle, '.'); + else + ans += string(middle / 2, 'R') + string(middle % 2, '.') + + string(middle / 2, 'L'); + i = j; + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.pushDominoes("RR.L"); +} diff --git a/queue_reconstruction.cpp b/queue_reconstruction.cpp new file mode 100644 index 0000000..17ea0ea --- /dev/null +++ b/queue_reconstruction.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + vector<vector<int>> reconstructQueue(vector<vector<int>> &people) { + sort(people.begin(), people.end(), cmp); + vector<vector<int>> ans; + for (int i = 0; i < people.size(); i++) + ans.insert(ans.begin() + people[i][1], people[i]); + return ans; + } + +private: + static bool cmp(vector<int> &p1, vector<int> &p2) { + if (p1[0] != p2[0]) + return p1[0] > p2[0]; + else + return p1[1] < p2[1]; + } +}; diff --git a/qunique_char.cpp b/qunique_char.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/qunique_char.cpp diff --git a/range_sum_bst.c b/range_sum_bst.c new file mode 100644 index 0000000..9db0643 --- /dev/null +++ b/range_sum_bst.c @@ -0,0 +1,25 @@ +// 938. Range Sum of BST +#include "leetcode.h" + +/* + * given the 'root' of a binary search tree and two integers 'low' and 'high', + * return the sum of values of all nodes with a value in the inclusive range + * '(low, high)' + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +int rangeSumBST(struct TreeNode *root, int low, int high) { + if (!root) + return 0; + else if (root->val >= low && root->val <= high) + return root->val + rangeSumBST(root->left, low, high) + + rangeSumBST(root->right, low, high); + else + return rangeSumBST(root->left, low, high) + + rangeSumBST(root->right, low, high); +} diff --git a/range_sum_bst.cpp b/range_sum_bst.cpp new file mode 100644 index 0000000..046aee2 --- /dev/null +++ b/range_sum_bst.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + int rangeSumBST(TreeNode *root, int low, int high) { + queue<TreeNode *> q; + q.push(root); + int sum = 0, v; + while (q.size()) { + root = q.front(); + q.pop(); + v = root->val; + if (v >= low && v <= high) + sum += v; + if (v > low && root->left) + q.push(root->left); + if (v < high && root->right) + q.push(root->right); + } + return sum; + } +}; diff --git a/range_sum_bst.py b/range_sum_bst.py new file mode 100644 index 0000000..f783759 --- /dev/null +++ b/range_sum_bst.py @@ -0,0 +1,41 @@ +# 938. Range Sum of BST + +""" +given the 'root' of a binary search tree and two integers 'low' and 'high', +return the sum of values of all nodes with a value in the inclusive range +'(low, high)' +""" + +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution(object): + def rangeSumBST(self, root, low, high): + """ + :type root: TreeNode + :type low: int + :type high: int + :rtype: int + """ + def dfs(node): + if not node: + return 0 + + current_val = 0 + if low <= node.val <= high: + current_val = node.val + + left_sum = dfs(node.left) + right_sum = dfs(node.right) + + return current_val + left_sum + right_sum + + return dfs(root) + +if __name__ == "__main__": + obj = Solution() + print(obj.rangeSumBST(root = [10,5,15,3,7,null,18], low = 7, high = 15)) # expect: 15 + print(obj.rangeSumBST(root = [10,5,15,3,7,13,18,1,null,6], low = 6, high = 10)) # expect: 23 diff --git a/range_sum_bst.rs b/range_sum_bst.rs new file mode 100644 index 0000000..f793202 --- /dev/null +++ b/range_sum_bst.rs @@ -0,0 +1,38 @@ +#[derive(Debug, PartialEq, Eq)] +pub struct TreeNode { + pub val: i32, + pub left: Option<Rc<RefCell<TreeNode>>>, + pub right: Option<Rc<RefCell<TreeNode>>> +} + +impl TreeNode { + #[inline] + pub fn new(val: i32) -> Self { + TreeNode { + val, + left: None, + right: None + } + } +} + +use std::rc::Rc; +use std::cell::RefCell; +impl Solution { + pub fn range_sum_bst(root: Option<Rc<RefCell<TreeNode>>>, low: i32, high: i32) -> i32 { + if let Some(root) = root { + let mut sum = 0; + if low <= root.borrow().val && root.borrow().val <= high { + sum += root.borrow().val; + } + if low < root.borrow().val { + sum += Self::range_sum_bst(root.borrow().left.clone(), low, high); + } + if high > root.borrow().val { + sum += Self::range_sum_bst(root.borrow().right.clone(), low, high); + } + return sum; + } + 0 + } +} diff --git a/range_sum_query_2d.cpp b/range_sum_query_2d.cpp new file mode 100644 index 0000000..d50ea14 --- /dev/null +++ b/range_sum_query_2d.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class NumMatrix { +public: + vector<vector<int>> sum; + NumMatrix(vector<vector<int>> &matrix) { + int m = matrix.size(), n = matrix[0].size(); + sum = vector<vector<int>>(m + 1, vector<int>(n + 1)); + for (int i = 1; i <= m; i++) + for (int j = 1; j <= n; j++) + sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + + matrix[i - 1][j - 1]; + } + int sumRegion(int row1, int col1, int row2, int col2) { + row1++, col1++, row2++, col2++; + return sum[row2][col2] - sum[row2][col1 - 1] - sum[row1 - 1][col2] + + sum[row1 - 1][col1 - 1]; + } +}; + +int main() {} diff --git a/range_sum_query_mutable.cpp b/range_sum_query_mutable.cpp new file mode 100644 index 0000000..cdc0230 --- /dev/null +++ b/range_sum_query_mutable.cpp @@ -0,0 +1,61 @@ +#include "leetcode.h" + +struct segNode { + int start, end, sum; + segNode *left, *right; + segNode(int a, int b) + : start(a), end(b), sum(0), left(nullptr), right(nullptr) {} +}; + +class NumArray { +public: + segNode *root; + NumArray(vector<int> &nums) { root = buildTree(nums, 0, nums.size() - 1); } + void update(int index, int val) { modifyTree(index, val, root); } + int sumRange(int left, int right) { return queryTree(left, right, root); } + +private: + segNode *buildTree(vector<int> &nums, int start, int end) { + if (start > end) + return nullptr; + segNode *root = new segNode(start, end); + if (start == end) { + root->sum = nums[start]; + return root; + } + int mid = start + (end - start) / 2; + root->left = buildTree(nums, start, mid); + root->right = buildTree(nums, mid + 1, end); + root->sum = root->left->sum + root->right->sum; + return root; + } + int modifyTree(int i, int val, segNode *root) { + if (root == nullptr) + return 0; + int diff; + if (root->start == i && root->end == i) { + diff = val - root->sum; + root->sum = val; + return diff; + } + int mid = (root->start + root->end) / 2; + if (i > mid) + diff = modifyTree(i, val, root->right); + else + diff = modifyTree(i, val, root->left); + root->sum = root->sum + diff; + return diff; + } + int queryTree(int i, int j, segNode *root) { + if (root == nullptr) + return 0; + if (root->start == i && root->end == j) + return root->sum; + int mid = (root->start + root->end) / 2; + if (i > mid) + return queryTree(i, j, root->right); + if (j <= mid) + return queryTree(i, j, root->left); + return queryTree(i, mid, root->left) + queryTree(mid + 1, j, root->right); + } +}; diff --git a/ransom_note.cpp b/ransom_note.cpp new file mode 100644 index 0000000..1a78e07 --- /dev/null +++ b/ransom_note.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + bool canConstruct(string ransomNote, string magazine) { + int count[26] = {0}; + for (char ch : magazine) + count[ch - 'a']++; + for (char ch : ransomNote) + if (count[ch - 'a']-- <= 0) + return false; + return true; + } +}; + +int main() { + Solution obj; + string ransomNote = "a", magazine = "b"; + if (obj.canConstruct(ransomNote, magazine)) + cout << "true"; + else + cout << "false"; +} diff --git a/reconstruct_digit_english.cpp b/reconstruct_digit_english.cpp new file mode 100644 index 0000000..fdc1022 --- /dev/null +++ b/reconstruct_digit_english.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + string originalDigits(string s) { + int fMap[26] = {0}, ans[10] = {0}; + for (char c : s) + fMap[c - 97]++; + for (int i = 0; i < 10; i++) { + int count = fMap[CHARS[i]]; + for (int remain : REM[i]) + fMap[remain] -= count; + ans[DIGITS[i]] = count; + } + string ansStr; + for (int i = 0; i < 10; i++) { + char c = (char)(i + 48); + for (int j = ans[i]; j; j--) + ansStr += c; + } + return ansStr; + } + +private: + const int DIGITS[10] = {0, 2, 4, 6, 8, 5, 7, 3, 9, 1}, + CHARS[10] = {25, 22, 20, 23, 6, 5, 18, 7, 8, 14}; + const vector<vector<int>> REM = {{14}, {14}, {5, 14}, {18, 8}, {8, 7}, + {8}, {}, {}, {}, {}}; +}; + +int main() {} diff --git a/reconstruct_itinerary.c b/reconstruct_itinerary.c new file mode 100644 index 0000000..a625ece --- /dev/null +++ b/reconstruct_itinerary.c @@ -0,0 +1,202 @@ +// 332. Reconstruct Itinerary +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a list of airline 'tickets' where 'tickets[i] = [from[i], to[i]]' + * represents the departure and the arrival airpots of one flight. reconstruct + * the itinerary in order and return it. all of the tickets belong to a man who + * departs from "JFK", thus, the itinerary must begin with "JFK". if there are + * multiple valid entires, you should return the itinerary that has the smallest + * lexical order when read as a string. you may assume all tickets form at least + * one valid itinerary. you must all the tickets once and only once. + */ + +#define MAGIC_NUM 31L +#define MODULE_NUM 1000007L +#define NEXT_MAX 50 +long mod(long n, long m) { return (n % m + m) % m; } + +long hash(char *charater) { + long hash_value = 0; + hash_value += MAGIC_NUM * charater[0]; + hash_value = mod(hash_value, MODULE_NUM); + + hash_value += MAGIC_NUM * MAGIC_NUM * charater[1]; + hash_value = mod(hash_value, MODULE_NUM); + + hash_value += MAGIC_NUM * MAGIC_NUM * MAGIC_NUM * charater[2]; + hash_value = mod(hash_value, MODULE_NUM); + + return hash_value; +} + +typedef struct _node_t { + struct _node_t *adj_list[NEXT_MAX]; + int adj_count; + int i_count; + struct _node_t *left; + struct _node_t *right; + long hash_val; + char *string_p; +} node_t; + +node_t *generate_itinerary(long hash_val) { + node_t *node = malloc(sizeof(node_t)); + for (int i = 0; i < NEXT_MAX; i++) + node->adj_list[i] = NULL; + node->hash_val = hash_val; + node->adj_count = 0; + node->i_count = 0; + node->left = NULL; + node->right = NULL; + + return node; +} + +node_t *insert_bst(node_t *node, long hash_val, node_t **insert_node) { + if (node == NULL) { + node = generate_itinerary(hash_val); + *insert_node = node; + return node; + } + + if (node->hash_val == hash_val) { + return NULL; + } else if (hash_val < node->hash_val) { + node_t *temp = insert_bst(node->left, hash_val, insert_node); + if (temp != node->left) { + node->left = temp; + *insert_node = temp; + } + } else if (hash_val > node->hash_val) { + node_t *temp = insert_bst(node->right, hash_val, insert_node); + if (temp != node->right) { + node->right = temp; + *insert_node = temp; + } + } + + return node; +} + +node_t *search_in_bst(node_t *node, long hash_val) { + if (node == NULL) + return NULL; + + if (hash_val == node->hash_val) { + return node; + } + if (hash_val < node->hash_val) { + return search_in_bst(node->left, hash_val); + } else if (hash_val > node->hash_val) { + return search_in_bst(node->right, hash_val); + } else { + return NULL; + } +} + +int laxical_determine(char *s1, char *s2) { + for (int i = 0; i < 3; i++) { + if (s1[i] < s2[i]) { + return 0; + } else if (s1[i] > s2[i]) { + return 1; + } + } + + return 0; +} + +void swap_node(node_t **n1, node_t **n2) { + node_t *temp = *n1; + *n1 = *n2; + *n2 = temp; +} + +void print_bst(node_t *node) { + if (node == NULL) + return; + + print_bst(node->left); + printf("[%s] hash: %ld, count: %d\n", node->string_p, node->hash_val, + node->adj_count); + print_bst(node->right); +} + +void traverse_graph(node_t *node, char ***result, int *count) { + while (node->i_count < node->adj_count) { + traverse_graph(node->adj_list[node->i_count++], result, count); + } + // post-order + // printf("traverse: %s\n", node->string_p); + memcpy((*result)[*count], node->string_p, 3 * sizeof(char)); + (*count)++; +} + +/** + * Note: The returned array must be malloced, assume caller calls free(). + */ +char **findItinerary(char ***tickets, int ticketsSize, int *ticketsColSize, + int *returnSize) { + char **result = malloc(ticketsSize * 2 * sizeof(char *)); + long start_hash = hash("JFK"); + // printf("start hash: %ld\n", start_hash); + + for (int i = 0; i < ticketsSize * 2; i++) { + result[i] = malloc(4 * sizeof(char)); + memset(result[i], 0, 4 * sizeof(char)); + } + + node_t *st_itinerary = NULL; + node_t *bst_root = NULL; + int node_count = 0; + + for (int i = 0; i < ticketsSize; i++) { + long from_hash = hash(tickets[i][0]); + long to_hash = hash(tickets[i][1]); + + node_t *from_node = search_in_bst(bst_root, from_hash); + node_t *to_node = search_in_bst(bst_root, to_hash); + + if (NULL == from_node) { + bst_root = insert_bst(bst_root, from_hash, &from_node); + node_count++; + } + if (NULL == to_node) { + bst_root = insert_bst(bst_root, to_hash, &to_node); + node_count++; + } + + from_node->string_p = tickets[i][0]; + to_node->string_p = tickets[i][1]; + + if (from_hash == start_hash) + st_itinerary = from_node; + + from_node->adj_list[from_node->adj_count++] = to_node; + for (int k = from_node->adj_count - 2; k >= 0; k--) { + if (laxical_determine(from_node->adj_list[k]->string_p, + from_node->adj_list[k + 1]->string_p)) { + swap_node(&from_node->adj_list[k], &from_node->adj_list[k + 1]); + } + } + } + + if (st_itinerary == NULL) + return NULL; + int col = 0; + traverse_graph(st_itinerary, &result, &col); + + for (int i = 0; i < col >> 1; i++) { + char *temp = result[i]; + result[i] = result[col - i - 1]; + result[col - i - 1] = temp; + } + + *ticketsColSize = col; + *returnSize = col; + + return result; +} diff --git a/reconstruct_itinerary.py b/reconstruct_itinerary.py new file mode 100644 index 0000000..275f25e --- /dev/null +++ b/reconstruct_itinerary.py @@ -0,0 +1,28 @@ +# 332. Reconstruct Itinerary +from collections import defaultdict + +""" +given a list of airline 'tickets' where 'tickets[i] = [from[i], to[i]]' +represents the departure and the arrival airpots of one flight. reconstruct +the itinerary in order and return it. all of the tickets belong to a man who +departs from "JFK", thus, the itinerary must begin with "JFK". if there are +multiple valid entires, you should return the itinerary that has the smallest +lexical order when read as a string. you may assume all tickets form at least +one valid itinerary. you must all the tickets once and only once. +""" + + +class Solution(object): + def findItinerary(self, tickets): + targets = collections.defaultdict(list) + for a, b in sorted(tickets)[::-1]: + targets[a] += b + route = [] + + def visit(airport): + while targets[airport]: + visit(targets[airport].pop()) + route.append(airport) + + visit("JFK") + return route[::-1] diff --git a/recover_BST.cpp b/recover_BST.cpp new file mode 100644 index 0000000..9120825 --- /dev/null +++ b/recover_BST.cpp @@ -0,0 +1,27 @@ +#include "leetcode.h" + +class Solution { +public: + vector<pair<TreeNode *, TreeNode *>> vec; + void recoverTree(TreeNode *root) { + inOrder(root); + if (vec.size() == 1) + swap(vec[0].first->val, vec[0].second->val); + if (vec.size() == 2) + swap(vec[0].first->val, vec[1].second->val); + } + +private: + TreeNode *prev = NULL; + void inOrder(TreeNode *root) { + if (!root) + return; + inOrder(root->left); + if (prev && prev->val > root->val) + vec.push_back({prev, root}); + prev = root; + inOrder(root->right); + } +}; + +int main() {} diff --git a/rectangle_area.cpp b/rectangle_area.cpp new file mode 100644 index 0000000..fa56d94 --- /dev/null +++ b/rectangle_area.cpp @@ -0,0 +1,16 @@ +#include "leetcode.h" + +class Solution { +public: + int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, + int by2) { + return (ax2 - ax1) * (ay2 - ay1) + (bx2 - bx1) * (by2 - by1) - + max(min(ax2, bx2) - max(ax1, bx1), 0) * + max(min(ay2, by2) - max(ay1, by1), 0); + } +}; + +int main() { + Solution obj; + cout << obj.computeArea(-3, 0, 3, 4, 0, -1, 9, 2); +} diff --git a/rectangle_area.rs b/rectangle_area.rs new file mode 100644 index 0000000..4d9c013 --- /dev/null +++ b/rectangle_area.rs @@ -0,0 +1,14 @@ +struct Solution; + +impl Solution { + pub fn compute_area(ax1: i32, ay1: i32, ax2: i32, ay2: i32, bx1: i32, by1: i32, bx2: i32, by2: i32) -> i32 { + (ax2 - ax1) * (ay2 - ay1) + + (bx2 - bx1) * (by2 - by1) - + 0.max(ax2.min(bx2) - ax1.max(bx1)) * + 0.max(ay2.min(by2) - ay1.max(by1)) + } +} + +fn main() { + print!("{}", Solution::compute_area(-3, 0, 3, 4, 0, -1, 9, 2)); +} diff --git a/rectangle_fewest_squares.cpp b/rectangle_fewest_squares.cpp new file mode 100644 index 0000000..ef56533 --- /dev/null +++ b/rectangle_fewest_squares.cpp @@ -0,0 +1,51 @@ +#include "leetcode.h" + +class Solution { +public: + int maxDepth = 0; + int tilingRectangle(int n, int m) { + if (n > m) + swap(n, m); + vector<int> s; + for (int i = 0; i < n; i++) + s.push_back(m); + maxDepth = max(n, m); + dfs(s, 0); + return maxDepth; + } + +private: + typedef long long key; + unordered_map<key, int> dp; + key hash(vector<int> &j) { + key r = 0; + for (int n : j) + r = (r << 4LL) + n; + return r; + } + void dfs(vector<int> j, int depth) { + key h = hash(j); + if (h == 0) { + maxDepth = min(maxDepth, depth); + return; + } + if (depth >= maxDepth || dp.count(h)) + return; + auto topLeft = max_element(j.begin(), j.end()); + int width = 1; + for (auto top = topLeft + 1; top != j.end() && *top == *topLeft; top++) + width++; + for (int w = min(width, *topLeft); w > 0; w--) { + for (int i = 0; i < w; i++) + *(topLeft + i) -= w; + dfs(j, depth + 1); + for (int i = 0; i < w; i++) + *(topLeft + i) += w; + } + } +}; + +int main() { + Solution obj; + cout << obj.tilingRectangle(2, 3); +} diff --git a/redistribute_char_str_eq.c b/redistribute_char_str_eq.c new file mode 100644 index 0000000..d81114a --- /dev/null +++ b/redistribute_char_str_eq.c @@ -0,0 +1,29 @@ +// 1897. Redistribute Characters to Make All Strings Equal +#include "leetcode.h" + +/* + * given an array of strings 'words' in one operation, pick two distinct indices + * 'i' and 'j' where 'words[i]' is a non empty string and ove any character from + * words[i] to any position in 'words[j]'. return 1 if you can make every string + * in 'words' equal using any number of operations, and 0 otherwise. + */ + +bool makeEqual(char **words, int words_size) { + int n = words_size; + int *alpha = calloc(26, sizeof(int)); + for (int i = 0; i < n; i++) { + int l = strlen(words[i]); + for (int j = 0; j < l; j++) + alpha[words[i][j] - 'a']++; + } + for (int i = 0; i < 26; i++) + if (alpha[i] % n) + return false; + return true; +} + +int main() { + char **w1 = {"abc", "aabc", "bc"}, **w2 = {"ab", "a"}; + printf("%d\n", makeEqual(w1, ARRAY_SIZE(w1))); // expect: 1 + printf("%d\n", makeEqual(w2, ARRAY_SIZE(w2))); // expect: 0 +} diff --git a/redistribute_char_str_eq.py b/redistribute_char_str_eq.py new file mode 100644 index 0000000..c76b9b2 --- /dev/null +++ b/redistribute_char_str_eq.py @@ -0,0 +1,32 @@ +# 1897. Redistribute Characters to Make All Strings Equal +from collections import defaultdict + +""" +given an array of strings 'words' in one operation, pick two distinct indices +'i' and 'j' where 'words[i]' is a non empty string and ove any character from +words[i] to any position in 'words[j]'. return 1 if you can make every string +in 'words' equal using any number of operations, and 0 otherwise. +""" + + +class Solution(object): + def makeEqual(self, words): + """ + :type words: List[str] + :rtype: bool + """ + cnt = defaultdict(int) + for w in words: + for c in w: + cnt[c] += 1 + n = len(words) + for val in cnt.values(): + if val % n != 0: + return False + return True + + +if __name__ == "__main__": + obj = Solution() + print(obj.makeEqual(words=["abc", "aabc", "bc"])) + print(obj.makeEqual(words=["ab", "a"])) diff --git a/reduce_array_size_half.c b/reduce_array_size_half.c new file mode 100644 index 0000000..da62032 --- /dev/null +++ b/reduce_array_size_half.c @@ -0,0 +1,38 @@ +// 1338. Reduce Array Size to The Half +#include "leetcode.h" + +/* + * you are given an integer array 'arr'. you can choose a set of integers and + * remove all the occurences of these integers in the array. return the minimum + * size of the set so that at least half of the integers in the array are + * removed. + */ + +int minSetSize(int *arr, int arrSize) { + int *hash = (int *)calloc(100001, sizeof(int)); + int *hash_cnt = (int *)calloc(arrSize + 1, sizeof(int)); + int max = 0, ans = 0, ans_cnt = 0; + for (int i = 0; i < arrSize; i++) { + if (hash[arr[i]]) + hash_cnt[hash[arr[i]]]--; + hash_cnt[++hash[arr[i]]]++; + if (hash[arr[i]] > max) + max = hash[arr[i]]; + } + while (ans_cnt < arrSize / 2) { + while (!hash_cnt[max]) + max--; + while (ans_cnt < arrSize / 2 && hash_cnt[max]) { + ans_cnt += max; + hash_cnt[max]--; + ans++; + } + } + return ans; +} + +int main() { + int a1[] = {3, 3, 3, 3, 5, 5, 5, 2, 2, 7}, a2[] = {7, 7, 7, 7, 7, 7}; + printf("%d\n", minSetSize(a1, ARRAY_SIZE(a1))); // expect: 2 + printf("%d\n", minSetSize(a2, ARRAY_SIZE(a2))); // expect: 1 +} diff --git a/reduce_array_size_half.cpp b/reduce_array_size_half.cpp new file mode 100644 index 0000000..fd922dc --- /dev/null +++ b/reduce_array_size_half.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + int minSetSize(vector<int> &arr) { + int ans = 0, n = arr.size(), n1 = 0; + vector<int> j; + unordered_map<int, int> um; + for (int i = 0; i < n; i++) + um[arr[i]]++; + for (auto x : um) + j.push_back(x.second); + if (j.size() == 1) + return 1; + sort(j.begin(), j.end()); + for (int i = j.size() - 1; i >= 0; i--) { + if (ans >= n / 2) + return n1; + n1++; + ans = ans + j[i]; + } + return 0; + } +}; + +int main() { + Solution obj; + vector<int> arr = {3, 3, 3, 3, 5, 5, 5, 2, 2, 7}; + cout << obj.minSetSize(arr); +} diff --git a/reduce_array_size_half.py b/reduce_array_size_half.py new file mode 100644 index 0000000..bcbac65 --- /dev/null +++ b/reduce_array_size_half.py @@ -0,0 +1,31 @@ +# 1338. Reduce Array Size to The Half +from collections import Counter + +""" +you are given an integer array 'arr'. you can choose a set of integers and +remove all the occurences of these integers in the array. return the minimum +size of the set so that at least half of the integers in the array are +removed. +""" + + +class Solution(object): + def minSetSize(self, arr): + """ + :type arr: List[int] + :rtype: int + """ + cnt = Counter(arr) + freq = list(cnt.values()) + freq.sort() + ans, removed, half = 0, 0, len(arr) // 2 + while removed < half: + ans += 1 + removed += freq.pop() + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.minSetSize(arr=[3, 3, 3, 3, 5, 5, 5, 2, 2, 7])) + print(obj.minSetSize(arr=[7, 7, 7, 7, 7, 7])) diff --git a/reducing_dishes.c b/reducing_dishes.c new file mode 100644 index 0000000..2f5a4c7 --- /dev/null +++ b/reducing_dishes.c @@ -0,0 +1,47 @@ +// 1402. Reducing Dishes +#include <stdio.h> +#include <stdlib.h> + +/* + * a chef has collected data on the 'satisfaction' level of his 'n' dishes. chef + * can cook any dish in 1 unit of time. like-time coefficient of a dish is + * defined as the time taken to cook that dish including previous dishes + * multiplied by its satisfaction level - eg. 'time[i] * satisfaction[i]'. + * return maximum sum of like-time coefficient that the chef can obtain after + * dishes preparation. dishes can be prepared in any order and the chef can + * discard some dishes to get this maximum value. + */ + +int cmp(const void *a, const void *b) { return (*(int *)a - *(int *)b); } + +int sum(int *satisfaction, int satisfaction_size, int idx) { + int val = 0; + for (int i = idx, j = 1; i < satisfaction_size; ++i, ++j) + val += satisfaction[i] * j; + return val; +} + +int maxSatisfaction(int *satisfaction, int satisfaction_size) { + int max, idx, tmp; + qsort(satisfaction, satisfaction_size, sizeof(int), cmp); + for (int i = 0; i < satisfaction_size; ++i) + if (satisfaction[i] >= 0) { + idx = i; + break; + } + while (idx >= 0) { + tmp = sum(satisfaction, satisfaction_size, idx); + max = (max > tmp) ? max : tmp; + idx--; + } + return max; +} + +int main() { + int s1[] = {-1, -8, 0, 5, -9}; + int s2[] = {4, 3, 2}; + int s3[] = {-1, -4, -5}; + printf("%d\n", maxSatisfaction(s1, 5)); // expect: 14 + printf("%d\n", maxSatisfaction(s2, 3)); // expect: 20 + printf("%d\n", maxSatisfaction(s3, 3)); // expect: 0 +} diff --git a/reducing_dishes.cpp b/reducing_dishes.cpp new file mode 100644 index 0000000..3982095 --- /dev/null +++ b/reducing_dishes.cpp @@ -0,0 +1,37 @@ +// 1402. Reducing Dishes +#include "leetcode.h" + +/* + * a chef has collected data on the 'satisfaction' level of his 'n' dishes. chef + * can cook any dish in 1 unit of time. like-time coefficient of a dish is + * defined as the time taken to cook that dish including previous dishes + * multiplied by its satisfaction level - eg. 'time[i] * satisfaction[i]'. + * return maximum sum of like-time coefficient that the chef can obtain after + * dishes preparation. dishes can be prepared in any order and the chef can + * discard some dishes to get this maximum value. + */ + +class Solution { +public: + int maxSatisfaction(vector<int> &satisfaction) { + sort(satisfaction.begin(), satisfaction.end(), greater<int>()); + int n = satisfaction.size(), pre_sum = 0, ans = 0; + for (int i = 0; i < n; i++) { + pre_sum += satisfaction[i]; + if (pre_sum < 0) + break; + ans += pre_sum; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> s1 = {-1, -8, 0, 5, -9}; + vector<int> s2 = {4, 3, 2}; + vector<int> s3 = {-1, -4, -5}; + printf("%d\n", obj.maxSatisfaction(s1)); // expect: 14 + printf("%d\n", obj.maxSatisfaction(s2)); // expect: 20 + printf("%d\n", obj.maxSatisfaction(s3)); // expect: 0 +} diff --git a/reduction_oper_arr_eq.c b/reduction_oper_arr_eq.c new file mode 100644 index 0000000..7f4be1a --- /dev/null +++ b/reduction_oper_arr_eq.c @@ -0,0 +1,36 @@ +// 1887. Reduction Operations to Make the Array Elements Equal +#include "leetcode.h" + +/* + * given an integer array 'nums', your goal is to make all elements in 'nums' + * equal. to complete one operation, follow the steps find the largest value in + * 'nums'. let its index be 'i' and its value be 'largest'. if there are + * multiple elements with the largest value, pick the smallest. find the next + * largest value in 'nums' strictly smaller than largest. let its value be + * next_largest. reduce 'nums[i]' to next_largest. return the number of + * operations to make all the elements in 'nums' equal + */ + +int cmp(const void *a, const void *b) { return *(int *)b - *(int *)a; } + +int reductionOperations(int *nums, int nums_size) { + int n = nums_size, ans = 0, cnt = 1, k = 0; + qsort(nums, n, sizeof(int), cmp); + for (int i = 1; i < n; i++) { + if (nums[i] == nums[i - 1]) + cnt++; + else { + k += cnt; + ans += k; + cnt = 1; + } + } + return ans; +} + +int main() { + int n1[] = {5, 1, 3}, n2[] = {1, 1, 1}, n3[] = {1, 1, 2, 2, 3}; + printf("%d\n", reductionOperations(n1, ARRAY_SIZE(n1))); // expect: 3 + printf("%d\n", reductionOperations(n2, ARRAY_SIZE(n2))); // expect: 0 + printf("%d\n", reductionOperations(n3, ARRAY_SIZE(n3))); // expect: 4 +} diff --git a/reduction_oper_arr_eq.py b/reduction_oper_arr_eq.py new file mode 100644 index 0000000..383a259 --- /dev/null +++ b/reduction_oper_arr_eq.py @@ -0,0 +1,36 @@ +# 1887. Reduction Operations to Make the Array Elements Equal + +""" +given an integer array 'nums', your goal is to make all elements in 'nums' +equal. to complete one operation, follow the steps find the largest value in +'nums'. let its index be 'i' and its value be 'largest'. if there are +multiple elements with the largest value, pick the smallest. find the next +largest value in 'nums' strictly smaller than largest. let its value be +next_largest. reduce 'nums[i]' to next_largest. return the number of +operations to make all the elements in 'nums' equal +""" + + +class Solution(object): + def reductionOperations(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + n = len(nums) + freq = [0] * 50001 + for i in nums: + freq[i] += 1 + ans, ops = 0, 0 + for i in range(50000, 0, -1): + if freq[i] > 0: + ops += freq[i] + ans += ops - freq[i] + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.reductionOperations([5, 1, 3])) + print(obj.reductionOperations([1, 1, 1])) + print(obj.reductionOperations([1, 1, 2, 2, 3])) diff --git a/relative_ranks.c b/relative_ranks.c new file mode 100644 index 0000000..ba43919 --- /dev/null +++ b/relative_ranks.c @@ -0,0 +1,69 @@ +// 506. Relative Ranks +#include "leetcode.h" + +/* + * given an integer array score of size 'n' where 'score[i]' is the score of the + * i'th athlete in a competition. all the scores are guaranteed to be unique. + * the athletes are placed based on their scores where the first place athlete + * has the highest score, the second place athlet has the second highest score, + * and so on. return an array 'ans' of size 'n' where 'ans[i]' is the rank of + * the i'th athlete. + */ + +struct pair { + int idx; + int score; +}; + +int cmp(const void *a, const void *b) { + struct pair aa = *(const struct pair *)a; + struct pair bb = *(const struct pair *)b; + return bb.score - aa.score; +} + +char **findRelativeRanks(int *score, int scoreSize, int *returnSize) { + struct pair *arr = (struct pair *)calloc(scoreSize, sizeof(struct pair)); + for (int i = 0; i < scoreSize; i++) { + arr[i].idx = i; + arr[i].score = score[i]; + } + qsort(arr, scoreSize, sizeof(struct pair), cmp); + *returnSize = scoreSize; + char **ans = (char **)malloc(*returnSize * sizeof(char *)); + for (int i = 0; i < *returnSize; i++) + ans[i] = (char *)malloc(13); + for (int i = 0; i < scoreSize; i++) { + switch (i) { + case 0: + ans[arr[0].idx] = "Gold Medal"; + break; + case 1: + ans[arr[1].idx] = "Silver Medal"; + break; + case 2: + ans[arr[2].idx] = "Bronze Medal"; + break; + default: + sprintf(ans[arr[i].idx], "%d", i + 1); + } + } + free(arr); + return ans; +} + +int main() { + int s1[] = {5, 4, 3, 2, 1}, s2[] = {10, 3, 8, 9, 4}, rs1, rs2; + char **frr1 = findRelativeRanks(s1, ARRAY_SIZE(s1), &rs1); + char **frr2 = findRelativeRanks(s2, ARRAY_SIZE(s2), &rs2); + for (int i = 0; i < rs1; i++) + printf( + "%s ", + frr1[i]); // expect: "Gold Medal","Silver Medal","Bronze Medal","4","5" + printf("\n"); + for (int i = 0; i < rs2; i++) + printf( + "%s ", + frr2[i]); // expect: "Gold Medal","5","Bronze Medal","Silver Medal","4" + printf("\n"); + free(frr1), free(frr2); +} diff --git a/relative_ranks.py b/relative_ranks.py new file mode 100644 index 0000000..c1a5dbe --- /dev/null +++ b/relative_ranks.py @@ -0,0 +1,29 @@ +# 506. Relative Ranks + +""" +given an integer array score of size 'n' where 'score[i]' is the score of the +i'th athlete in a competition. all the scores are guaranteed to be unique. +the athletes are placed based on their scores where the first place athlete +has the highest score, the second place athlet has the second highest score, +and so on. return an array 'ans' of size 'n' where 'ans[i]' is the rank of +the i'th athlete. +""" + + +class Solution(object): + def findRelativeRanks(self, score): + """ + :type score: List[int] + :rtype: List[str] + """ + sort = sorted(score)[::-1] + rank = ["Gold Medal", "Silver Medal", "Bronze Medal"] + map( + str, range(4, len(score) + 1) + ) + return map(dict(zip(sort, rank)).get, score) + + +if __name__ == "__main__": + obj = Solution() + print(obj.findRelativeRanks(score=[5, 4, 3, 2, 1])) + print(obj.findRelativeRanks(score=[10, 3, 8, 9, 4])) diff --git a/relative_sort_array.c b/relative_sort_array.c new file mode 100644 index 0000000..fa997c3 --- /dev/null +++ b/relative_sort_array.c @@ -0,0 +1,50 @@ +// 1122. Relative Sort Array +#include "leetcode.h" + +/* + * given two arrays 'arr1' and 'arr2', the elements of 'arr2' are distinct and + * all elements in 'arr2' are also in 'arr1'. sort the elements of 'arr1' such + * that the relative ordering of items in 'arr1' are the same as in 'arr2'. + * elements that do not appear in 'arr2' should be placed at the end of 'arr1' + * in ascending order. + */ + +void swap(int *a, int *b) { + int tmp = *a; + *a = *b; + *b = tmp; +} + +int *relativeSortArray(int *arr1, int arr1Size, int *arr2, int arr2Size, + int *returnSize) { + int cnt = 0; + for (int i = 0; i < arr2Size; i++) + for (int j = 0; j < arr1Size; j++) + if (arr1[j] == arr2[i]) + swap(&arr1[j], &arr1[cnt++]); + for (int i = cnt; i < arr1Size; i++) { + int min = arr1[i], idx = i; + for (int j = i + 1; j < arr1Size; j++) + if (arr1[j] < min) + min = arr1[j], idx = j; + swap(&arr1[i], &arr1[idx]); + }; + *returnSize = arr1Size; + return arr1; +} + +int main() { + int a11[] = {2, 3, 1, 3, 2, 4, 6, 7, 9, 2, 19}, a21[] = {2, 1, 4, 3, 9, 6}, + a12[] = {28, 6, 22, 8, 44, 17}, a22[] = {22, 28, 8, 6}, rs1, rs2; + int *rsa1 = + relativeSortArray(a11, ARRAY_SIZE(a11), a21, ARRAY_SIZE(a21), &rs1); + int *rsa2 = + relativeSortArray(a12, ARRAY_SIZE(a12), a22, ARRAY_SIZE(a22), &rs2); + for (int i = 0; i < rs1; i++) + printf("%d ", rsa1[i]); // expect: 2,2,2,1,4,3,3,9,6,7,19 + printf("\n"); + for (int i = 0; i < rs2; i++) + printf("%d ", rsa2[i]); // expect: 22,28,8,6,17,44 + printf("\n"); + free(rsa1), free(rsa2); +} diff --git a/relative_sort_array.py b/relative_sort_array.py new file mode 100644 index 0000000..6550290 --- /dev/null +++ b/relative_sort_array.py @@ -0,0 +1,22 @@ +# 1122. Relative Sort Array + +""" +given two arrays 'arr1' and 'arr2', the elements of 'arr2' are distinct and +all elements in 'arr2' are also in 'arr1'. sort the elements of 'arr1' such +that the relative ordering of items in 'arr1' are the same as in 'arr2'. +elements that do not appear in 'arr2' should be placed at the end of 'arr1' +in ascending order. +""" +class Solution(object): + def relativeSortArray(self, arr1, arr2): + """ + :type arr1: List[int] + :type arr2: List[int] + :rtype: List[int] + """ + return sorted(arr1, key=(arr2 + sorted(arr1)).index) + +if __name__ == "__main__": + obj = Solution() + print(obj.relativeSortArray(arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6])) + print(obj.relativeSortArray(arr1 = [28,6,22,8,44,17], arr2 = [22,28,8,6])) diff --git a/remove_adjacent_dup.cpp b/remove_adjacent_dup.cpp new file mode 100644 index 0000000..c0cc341 --- /dev/null +++ b/remove_adjacent_dup.cpp @@ -0,0 +1,37 @@ +#include "leetcode.h" + +class Solution { +public: + string removeDuplicates(string s, int k) { + // cout << s << endl << k << endl; + if (s.size() < k) + return s; + stack<pair<char, int>> stk; + for (int i = 0; i < s.size(); ++i) { + if (stk.empty() || stk.top().first != s[i]) + stk.push({s[i], 1}); + else { + auto prev = stk.top(); + stk.pop(); + stk.push({s[i], prev.second + 1}); + } + if (stk.top().second == k) + stk.pop(); + } + string ans = ""; + while (!stk.empty()) { + auto curr = stk.top(); + stk.pop(); + while (curr.second--) + ans.push_back(curr.first); + } + reverse(ans.begin(), ans.end()); + // cout << ans; + return ans; + } +}; + +int main() { + Solution obj; + obj.removeDuplicates("deeedbbcccbdaa", 3); +} diff --git a/remove_adjacent_dup_str.cpp b/remove_adjacent_dup_str.cpp new file mode 100644 index 0000000..80b61ab --- /dev/null +++ b/remove_adjacent_dup_str.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + string removeDuplicates(string s) { + string ans; + for (char &c : s) { + if (ans.size() && c == ans.back()) + ans.pop_back(); + else + ans.push_back(c); + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.removeDuplicates("abbaca"); +} diff --git a/remove_adjacent_dup_str.rs b/remove_adjacent_dup_str.rs new file mode 100644 index 0000000..063cfbb --- /dev/null +++ b/remove_adjacent_dup_str.rs @@ -0,0 +1,20 @@ +struct Solution; + +impl Solution { + pub fn remove_duplicates(s: String) -> String { + let mut ans = String::new(); + for c in s.chars() { + if ans.len() > 0 && ans.chars().last() == Some(c) { + ans.pop(); + } else { + ans.push(c); + } + } + ans + } +} + +fn main() { + let s = "abbaca".to_string(); + print!("{}", Solution::remove_duplicates(s)); +} diff --git a/remove_adjacent_equal_char.c b/remove_adjacent_equal_char.c new file mode 100644 index 0000000..f3a8231 --- /dev/null +++ b/remove_adjacent_equal_char.c @@ -0,0 +1,40 @@ +// 2957. Remove Adjacent Almost-Equal Characters +#include "leetcode.h" + +/* + * you are given a 0 indexed string 'word'. in one operation you can pick any + * index 'i' of 'word' and change 'word[i]' to any lowercase english letter. + * return the minimum number of operations needed to remove all adjacent almost + * equal characters from 'word'. two characters 'a' and 'b' are almost equal if + * 'a == b' or 'a' and 'b' are adjacent in the alphabet + */ + +int removeAlmostEqualCharacters(char *word) { + int n = strlen(word), ans = 0; + if (n == 1) + return 0; + else if (n == 2) + return abs(word[0] - word[1]) < 2 ? 1 : 0; + for (int i = 0; i < n - 2; i++) { + if (abs(word[i + 1] - word[i]) < 2) { + if (abs(word[i + 1] - word[i + 2]) < 2) { + ans++; + word[i + 1] = ' '; + } else { + ans++; + word[i] = ' '; + } + } else if (abs(word[i + 1] - word[i + 2]) < 2) { + ans++; + word[i + 2] = ' '; + } + } + return ans; +} + +int main() { + char *w1 = "aaaaa", *w2 = "abddez", *w3 = "zyxyxyz"; + printf("%d\n", removeAlmostEqualCharacters(w1)); // expect: 2 + printf("%d\n", removeAlmostEqualCharacters(w2)); // expect: 2 + printf("%d\n", removeAlmostEqualCharacters(w3)); // expect: 3 +} diff --git a/remove_adjacent_equal_char.py b/remove_adjacent_equal_char.py new file mode 100644 index 0000000..20a6b31 --- /dev/null +++ b/remove_adjacent_equal_char.py @@ -0,0 +1,29 @@ +# 2957. Remove Adjacent Almost-Equal Characters + +""" +you are given a 0 indexed string 'word'. in one operation you can pick any +index 'i' of 'word' and change 'word[i]' to any lowercase english letter. +return the minimum number of operations needed to remove all adjacent almost +equal characters from 'word'. two characters 'a' and 'b' are almost equal if +'a == b' or 'a' and 'b' are adjacent in the alphabet +""" + + +class Solution(object): + def removeAlmostEqualCharacters(self, word): + """ + :type word: str + :rtype: int + """ + i, k = 1, 0 + while i + k < len(word): + k += abs(ord(word[i + k]) - ord(word[i + k - 1])) < 2 + i += 1 + return k + + +if __name__ == "__main__": + obj = Solution() + print(obj.removeAlmostEqualCharacters("aaaaa")) + print(obj.removeAlmostEqualCharacters("abddez")) + print(obj.removeAlmostEqualCharacters("zyxyxyz")) diff --git a/remove_boxes.cpp b/remove_boxes.cpp new file mode 100644 index 0000000..47f62a9 --- /dev/null +++ b/remove_boxes.cpp @@ -0,0 +1,40 @@ +// 546. Remove Boxes +#include "leetcode.h" + +/* + * given several 'boxes' with different colours represented by different + * positive numbers. you may experience several rounds to remove boxes until + * there is no box left. each time you can choose some continuous boxes with the + * same colour (ie. composed of 'k' boxes, 'k >= 1'), remove them and get 'k * + * k' points. return the maximum points you can get. + */ + +class Solution { + int dp[100][100][100] = {0}; + int dfs(vector<int> &boxes, int i, int j, int k) { + if (j < i) + return 0; + if (dp[i][j][k]) + return dp[i][j][k]; + int res = (1 + k) * (1 + k) + dfs(boxes, i + 1, j, 0); + for (int m = i + 1; m <= j; m++) + if (boxes[m] == boxes[i]) + res = max(res, dfs(boxes, i + 1, m - 1, 0) + dfs(boxes, m, j, k + 1)); + dp[i][j][k] = res; + return res; + } + +public: + int removeBoxes(vector<int> &boxes) { + int n = boxes.size(); + return dfs(boxes, 0, n - 1, 0); + } +}; + +int main() { + Solution obj; + vector<int> b1 = {1, 3, 2, 2, 2, 3, 4, 3, 1}, b2 = {1, 1, 1}, b3 = {1}; + printf("%d\n", obj.removeBoxes(b1)); // expect: 23 + printf("%d\n", obj.removeBoxes(b2)); // expect: 9 + printf("%d\n", obj.removeBoxes(b3)); // expect: 1 +} diff --git a/remove_coloured_pc.c b/remove_coloured_pc.c new file mode 100644 index 0000000..c597d72 --- /dev/null +++ b/remove_coloured_pc.c @@ -0,0 +1,36 @@ +// 2038. Remove Colored Pieces if Both Neighbors are the Same Color +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +bool winnerOfGame(char *colours) { + int n = strlen(colours); + int grpa = 0, grpb = 0, cnt = 1; + for (int i = 1; i < n; i++) { + if (colours[i] == colours[i - 1]) + cnt++; + else { + if (cnt > 2) { + if (colours[i - 1] == 'A') + grpa += cnt - 2; + else + grpb += cnt - 2; + } + cnt = 1; + } + } + if (cnt > 2) { + if (colours[n - 1] == 'A') + grpa += cnt - 2; + else + grpb += cnt - 2; + } + return grpa > grpb; +} + +int main() { + char c1[] = {"AAABABB"}, c2[] = {"AA"}, c3[] = {"ABBBBBBBAAA"}; + printf("%d\n", winnerOfGame(c1)); // expect: 1 + printf("%d\n", winnerOfGame(c2)); // expect: 0 + printf("%d\n", winnerOfGame(c3)); // expect: 0 +} diff --git a/remove_coloured_pc.py b/remove_coloured_pc.py new file mode 100644 index 0000000..64fe023 --- /dev/null +++ b/remove_coloured_pc.py @@ -0,0 +1,20 @@ +# 2038. Remove Colored Pieces if Both Neighbors are the Same Color + +from collections import Counter + + +class Solution(object): + def winnerOfGame(self, colours): + c = collections.Counter() + for x, t in groupby(colours): + c[x] += max(len(list(t)) - 2, 0) + if c["A"] > c["B"]: + return True + return False + + +if __name__ == "__main__": + obj = Solution() + print(obj.winnerOfGame("AAABABB")) # expect: 1 + print(obj.winnerOfGame("AA")) # expect: 0 + print(obj.winnerOfGame("ABBBBBBBAAA")) # expect: 0 diff --git a/remove_dupplicate.cpp b/remove_dupplicate.cpp new file mode 100644 index 0000000..2628677 --- /dev/null +++ b/remove_dupplicate.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + int removeDuplicates(vector<int> &nums) { + if (nums.size() == 0) + return 0; + int ans = 0; + for (int i = 1; i < nums.size(); i++) { + if (nums[ans] != nums[i]) + ans++; + nums[ans] = nums[i]; + } + return ans + 1; + } +}; + +int main() { + Solution obj; + vector<int> nums = {0, 0, 1, 1, 1, 2, 2, 3, 3, 4}; + cout << obj.removeDuplicates(nums); +} diff --git a/remove_dupplicate.rs b/remove_dupplicate.rs new file mode 100644 index 0000000..c192b22 --- /dev/null +++ b/remove_dupplicate.rs @@ -0,0 +1,24 @@ +struct Solution; + +impl Solution { + pub fn remove_duplicates(nums: &mut Vec<i32>) -> i32 { + match nums.is_empty() { + true => 0, + false => { + let mut prev = 0; + for i in 1..nums.len() { + if nums[prev] != nums[i] { + prev += 1; + nums[prev] = nums[i]; + } + } + (prev + 1) as i32 + } + } + } +} + +fn main() { + let mut nums = vec![0,0,1,1,1,2,2,3,3,4]; + print!("{}", Solution::remove_duplicates(nums)); +} diff --git a/remove_dupplicate_letters.c b/remove_dupplicate_letters.c new file mode 100644 index 0000000..f1dc4ef --- /dev/null +++ b/remove_dupplicate_letters.c @@ -0,0 +1,42 @@ +// 316. Remove Duplicate Letters +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a string 's', remove duplicate letters so that every letter appears + * once and only once. you must make sure your result is the smallest in + * lexicographical order among all possible results. + */ + +char *removeDuplicateLetters(char *s) { + int n = strlen(s), a_idx = 0; + int *digit = calloc(26, sizeof(int)); + for (int i = 0; i < n; i++) + digit[s[i] - 'a']++; + bool *set = calloc(26, sizeof(bool)); + char *ans = malloc(n + 1); + for (int i = 0; i < n; i++) { + if (set[s[i] - 'a']) { + digit[s[i] - 'a']--; + continue; + } + while (a_idx && s[i] < ans[a_idx] && digit[ans[a_idx - 1] - 'a']) { + set[ans[a_idx - 1] - 'a'] = false; + a_idx--; + } + ans[a_idx] = s[i]; + a_idx++; + digit[s[i] - 'a']--; + set[s[i] - 'a'] = true; + } + ans[a_idx] = '\0'; + return ans; +} + +int main() { + char s1[] = {"bcabc"}, s2[] = {"cbacdcbc"}; + printf("%s\n", removeDuplicateLetters(s1)); // expect: abc + printf("%s\n", removeDuplicateLetters(s2)); // expect: acdb +} diff --git a/remove_dupplicate_letters.py b/remove_dupplicate_letters.py new file mode 100644 index 0000000..01ef970 --- /dev/null +++ b/remove_dupplicate_letters.py @@ -0,0 +1,29 @@ +# 316. Remove Duplicate Letters + +""" +given a string 's', remove duplicate letters so that every letter appears +once and only once. you must make sure your result is the smallest in +lexicographical order among all possible results. +""" + + +class Solution(object): + def removeDuplicateLetters(self, s): + last = {} + stack = [] + visited = set() + for i in range(len(s)): + last[s[i]] = i + for i in range(len(s)): + if s[i] not in visited: + while stack and stack[-1] > s[i] and last[stack[-1]] > i: + visited.remove(stack.pop()) + stack.append(s[i]) + visited.add(s[i]) + return "".join(stack) + + +if __name__ == "__main__": + obj = Solution() + print(obj.removeDuplicateLetters("bcabc")) # expect: abc + print(obj.removeDuplicateLetters("cbacdcbc")) # expect: acdb diff --git a/remove_element.cpp b/remove_element.cpp new file mode 100644 index 0000000..644f239 --- /dev/null +++ b/remove_element.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" + +class Solution { +public: + int removeElement(vector<int> &nums, int val) { + int idx = 0, k = nums.size(); + while (idx < k) { + if (nums[idx] == val) { + // cout << "idx " << idx << endl; + // cout << "k " << k << endl; + nums[idx] = nums[k - 1]; + --k; + } else + ++idx; + } + return k; + } +}; + +int main() { + Solution obj; + vector<int> nums = {0, 1, 2, 2, 3, 0, 4, 2}; + int val = 2; + for (int i = 0; i < nums.size(); i++) + cout << nums[i] << ' '; + cout << endl << nums.size() << endl; + cout << obj.removeElement(nums, val); +} diff --git a/remove_element.rs b/remove_element.rs new file mode 100644 index 0000000..fec38b6 --- /dev/null +++ b/remove_element.rs @@ -0,0 +1,22 @@ +use std::convert::TryInto; +struct Solution; + +impl Solution { + pub fn remove_element(mut nums: Vec<i32>, val: i32) -> i32 { + let (mut idx, mut k) = (0, nums.len()); + while idx < k { + if nums[idx] == val { + nums[idx] = nums[k - 1]; + k -= 1; + } else { + idx += 1; + } + } + k.try_into().unwrap() + } +} + +fn main() { + let nums = vec![0,1,2,2,3,0,4,2]; + print!("{}", Solution::remove_element(nums, 2)); +} diff --git a/remove_k_digits.c b/remove_k_digits.c new file mode 100644 index 0000000..c662223 --- /dev/null +++ b/remove_k_digits.c @@ -0,0 +1,51 @@ +// 402. Remove K Digits +#include "leetcode.h" + +/* + * given string 'num' representing a non-negative integer 'num', and an integer + * 'k' return the smallest possible integer after removing 'k' digits from + * 'num'. + */ + +char *removeKdigits(char *num, int k) { + int n = strlen(num), s_idx = 1; + if (k >= n) + return "0"; + int *stk = malloc(n * sizeof(int)); + stk[0] = 0; + for (int i = 1; i < n; i++) { + if (!k) { + stk[s_idx] = i; + s_idx++; + continue; + } + while (s_idx && num[i] < num[stk[s_idx - 1]]) { + s_idx--, k--; + if (!k) + break; + } + stk[s_idx] = i; + s_idx++; + } + int i = 0, a_idx = 0; + s_idx -= k; + char *ans = malloc(s_idx + 1); + for (i = 0; i < s_idx; i++) + if (num[stk[i]] != '0') + break; + for (int j = i; j < s_idx; j++) { + ans[a_idx] = num[stk[j]]; + a_idx++; + } + ans[a_idx] = '\0'; + if (!a_idx) + return "0"; + return ans; +} + +int main() { + char *n1 = "1432219", *n2 = "10200", *n3 = "10"; + printf("%s\n", removeKdigits(n1, 3)); // expect: 1219 + printf("%s\n", removeKdigits(n2, 1)); // expect: 200 + printf("%s\n", removeKdigits(n3, 2)); // expect: 0 +} diff --git a/remove_k_digits.py b/remove_k_digits.py new file mode 100644 index 0000000..6355b1b --- /dev/null +++ b/remove_k_digits.py @@ -0,0 +1,33 @@ +# 402. Remove K Digits + +""" +given string 'num' representing a non-negative integer 'num', and an integer +'k' return the smallest possible integer after removing 'k' digits from +'num'. +""" + + +class Solution(object): + def removeKdigits(self, num, k): + """ + :type num: str + :type k: int + :rtype: str + """ + stk = list() + for n in num: + while stk and k and stk[-1] > n: + stk.pop() + k -= 1 + if stk or n != "0": + stk.append(n) + if k: + stk = stk[0:-k] + return "".join(stk) or "0" + + +if __name__ == "__main__": + obj = Solution() + print(obj.removeKdigits(num="1432219", k=3)) + print(obj.removeKdigits(num="10200", k=1)) + print(obj.removeKdigits(num="10", k=2)) diff --git a/remove_max_edge.cpp b/remove_max_edge.cpp new file mode 100644 index 0000000..fb73f0b --- /dev/null +++ b/remove_max_edge.cpp @@ -0,0 +1,58 @@ +// 1579. Remove Max Number of Edges to Keep Graph Fully Traversable +#include "leetcode.h" + +/* + * alice and bob have an undirected graph of 'n' nodes and three + * types of edges: + * type1: can be traversed by alice only + * type2: can be traversed by bob only + * type3: can be traversed by both alice and bob + * given an array of 'edges' where 'edges[i] = [typei, ui, vi]' + * represents a bidirectional edge of type 'typei' between nodes + * 'ui' and 'vi', find the maximum number of edges you can remove + * so that after removing the edges, the graph can still be fully + * traversed by alice and bob if starting from any node, they can + * reach all other nodes. return the maximum number of edges you + * can remove, or return -1 if alice and bob cannot traverse graph + */ + +class Solution { +public: + int find(vector<int> &ds, int i) { + return ds[i] < 0 ? i : ds[i] = find(ds, ds[i]); + } + int maxNumEdgesToRemove(int n, vvd(int) & edges) { + vector<int> ds_both(n + 1, -1); + int used = 0; + for (int type = 3; type > 0; --type) { + auto ds_one = ds_both; + auto &ds = type == 3 ? ds_both : ds_one; + for (auto &e : edges) { + if (e[0] == type) { + int i = find(ds, e[1]), j = find(ds, e[2]); + if (i != j) { + ++used; + if (ds[j] < ds[i]) + swap(i, j); + ds[i] += ds[j]; + ds[j] = i; + } + } + } + if (type != 3 && ds[find(ds, 1)] != -n) + return -1; + } + return edges.size() - used; + } +}; + +int main() { + Solution obj; + vvd(int) + e1 = {{3, 1, 2}, {3, 2, 3}, {1, 1, 3}, {1, 2, 4}, {1, 1, 2}, {2, 3, 4}}; + vvd(int) e2 = {{3, 1, 2}, {3, 2, 3}, {1, 1, 4}, {2, 1, 4}}; + vvd(int) e3 = {{3, 2, 3}, {1, 1, 2}, {2, 3, 4}}; + printf("%d\n", obj.maxNumEdgesToRemove(4, e1)); + printf("%d\n", obj.maxNumEdgesToRemove(4, e2)); + printf("%d\n", obj.maxNumEdgesToRemove(4, e3)); +} diff --git a/remove_node.cpp b/remove_node.cpp new file mode 100644 index 0000000..1f79374 --- /dev/null +++ b/remove_node.cpp @@ -0,0 +1,31 @@ +#include <bits/stdc++.h> +#include <cstddef> +using namespace std; + +struct ListNode { + int val; + ListNode *next; + ListNode() : val(0), next(nullptr) {} + ListNode(int x) : val(x), next(nullptr) {} + ListNode(int x, ListNode *next) : val(x), next(next) {} +}; + +class Solution { +public: + ListNode *removeNthFromEnd(ListNode *head, int n) { + ListNode *temp = head; + for (int i = 0; i < n; i++) + temp = temp->next; + if (temp == NULL) + return head->next; + ListNode *curr = head; + while (temp->next) { + temp = temp->next; + curr = curr->next; + } + curr->next = curr->next->next; + return head; + } +}; + +int main() {} diff --git a/remove_nodes_linked_list.c b/remove_nodes_linked_list.c new file mode 100644 index 0000000..0bcae4f --- /dev/null +++ b/remove_nodes_linked_list.c @@ -0,0 +1,59 @@ +// 2487. Remove Nodes From Linked List +#include "leetcode.h" + +/* + * given the 'head' of a linked list, remove evey node which has a node with a + * greater value anywhere to the right side of it. return the 'head' of the + * modified linked list. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +int depth(struct ListNode *head) { + int n = 0; + struct ListNode *tmp = head; + while (tmp) { + n++; + tmp = tmp->next; + } + return n; +} + +struct ListNode *removeNodes(struct ListNode *head) { + int n = depth(head), i = 0; + struct ListNode **arr = + (struct ListNode **)malloc(n * sizeof(struct ListNode *)); + struct ListNode *tmp = head; + while (tmp) { + arr[i] = tmp; + i++; + tmp = tmp->next; + } + bool *remove = (bool *)calloc(n, sizeof(bool)); + int max = arr[n - 1]->val; + for (int i = n - 2; i >= 0; i--) { + if (arr[i]->val < max) + remove[i] = true; + else if (arr[i]->val > max) + max = arr[i]->val; + } + struct ListNode *ans; + for (int i = 0; i < n; i++) { + if (!remove[i]) { + ans = arr[i]; + tmp = ans; + for (int j = i + 1; j < n; j++) + if (!remove[j]) { + tmp->next = arr[j]; + tmp = tmp->next; + } + tmp->next = NULL; + break; + } + } + free(arr), free(remove); + return ans; +} diff --git a/remove_nodes_linked_list.py b/remove_nodes_linked_list.py new file mode 100644 index 0000000..75076c5 --- /dev/null +++ b/remove_nodes_linked_list.py @@ -0,0 +1,28 @@ +# 2487. Remove Nodes From Linked List + +""" +given the 'head' of a linked list, remove evey node which has a node with a +greater value anywhere to the right side of it. return the 'head' of the +modified linked list. +""" + + +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, val=0, next=None): + self.val = val + self.next = next + + +class Solution(object): + def removeNodes(self, head): + """ + :type head: Optional[ListNode] + :rtype: Optional[ListNode] + """ + if not head: + return None + head.next = self.removeNodes(head.next) + if head.next and head.val < head.next.val: + return head.next + return head diff --git a/remove_nth_node.c b/remove_nth_node.c new file mode 100644 index 0000000..216f3ac --- /dev/null +++ b/remove_nth_node.c @@ -0,0 +1,38 @@ +// 19. Remove Nth Node From End of List +#include "leetcode.h" + +/* + * given the 'head' of a linked list, remove the n'th node from the end of the + * list and return its head + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +int get_len(struct ListNode *head) { + struct ListNode *traverse = head; + int n = 0; + while (traverse) { + traverse = traverse->next; + n++; + } + return n; +} + +struct ListNode *removeNthFromEnd(struct ListNode *head, int n) { + int len = get_len(head); + if (len == 1 && n == 1) + return NULL; + if (len == n) + return head->next; + int del_idx = len - n - 1; + struct ListNode *traverse = head; + while (del_idx) { + traverse = traverse->next; + del_idx--; + } + traverse->next = traverse->next->next; + return head; +} diff --git a/remove_nth_node.cpp b/remove_nth_node.cpp new file mode 100644 index 0000000..38f8a72 --- /dev/null +++ b/remove_nth_node.cpp @@ -0,0 +1,18 @@ +#include "leetcode.h" + +class Solution { +public: + ListNode *removeNthFromEnd(ListNode *head, int n) { + ListNode *fast = head, *slow = head; + for (int i = 0; i < n; i++) + fast = fast->next; + if (!fast) + return head->next; + while (fast->next) { + fast = fast->next; + slow = slow->next; + } + slow->next = slow->next->next; + return head; + } +}; diff --git a/remove_palindromic_subsequence.cpp b/remove_palindromic_subsequence.cpp new file mode 100644 index 0000000..cbf7182 --- /dev/null +++ b/remove_palindromic_subsequence.cpp @@ -0,0 +1,19 @@ +#include "leetcode.h" + +class Solution { +public: + int removePalindromeSub(string s) { + if (s.size() == 0) + return 0; + for (int i = 0, j = s.size() - 1; i < j; i++, j--) + if (s[i] != s[j]) + return 2; + return 1; + } +}; + +int main() { + string s = "ababa"; + Solution obj; + cout << obj.removePalindromeSub(s); +} diff --git a/remove_star_string.c b/remove_star_string.c new file mode 100644 index 0000000..10a2862 --- /dev/null +++ b/remove_star_string.c @@ -0,0 +1,40 @@ +// 2390. Removing Stars From a String +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a string 's', which contains stars (*). in one operation + * you can choose a start in 's', remove the closest non-star + * character to its left, as well remove the star itself. + * return string after all stars have been removed. note, the + * input will be generated such that the operation is always + * possible, and the resulting string will always be unique + */ + +char *removeStars(char *s) { + int n = strlen(s), idx = 0; + char *stk = malloc((n + 1) * sizeof(char)); + for (int i = 0; i < n; i++) { + stk[idx] = s[i]; + if (stk[idx] == '*') { + if (!idx) + continue; + else + idx -= 2; + } + idx++; + } + stk[idx] = '\0'; + return stk; +} + +int main() { + char s1[] = {"leet**cod*e"}, s2[] = {"erase*****"}; + char *ans1 = removeStars(s1), *ans2 = removeStars(s2); + for (int i = 0; i < strlen(s1); i++) + printf("%c", ans1[i]); // expect: lecoe + printf("\n"); + for (int i = 0; i < strlen(s2); i++) + printf("%c", ans2[i]); // expect: null +} diff --git a/remove_star_string.cpp b/remove_star_string.cpp new file mode 100644 index 0000000..c7cbfb5 --- /dev/null +++ b/remove_star_string.cpp @@ -0,0 +1,40 @@ +// 2390. Removing Stars From a String +#include "leetcode.h" + +/* + * given a string 's', which contains stars (*). in one operation + * you can choose a start in 's', remove the closest non-star + * character to its left, as well remove the star itself. + * return string after all stars have been removed. note, the + * input will be generated such that the operation is always + * possible, and the resulting string will always be unique + */ + +class Solution { +public: + string removeStars(string s) { + stack<char> stk; + string ans; + vector<char> vec; + for (int i = 0; i < s.size(); i++) { + if (s[i] != '*') + stk.emplace(s[i]); + else + stk.pop(); + } + while (!stk.empty()) { + vec.emplace_back(stk.top()); + stk.pop(); + } + reverse(vec.begin(), vec.end()); + for (int i = 0; i < vec.size(); i++) + ans += vec[i]; + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.removeStars("leet**cod*e") << endl; // expect: lecoe + cout << obj.removeStars("erase*****") << endl; // expect: null +} diff --git a/remove_stones.cpp b/remove_stones.cpp new file mode 100644 index 0000000..f267b0c --- /dev/null +++ b/remove_stones.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + int minStoneSum(vector<int> &piles, int k) { + priority_queue<int> pq(piles.begin(), piles.end()); + int ans = accumulate(piles.begin(), piles.end(), 0); + while (k--) { + int i = pq.top(); + pq.pop(); + pq.push(i - i / 2); + ans -= i / 2; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> piles1 = {5, 4, 9}, piles2 = {4, 3, 6, 7}; + cout << obj.minStoneSum(piles1, 2); // expect: 12 + cout << endl; + cout << obj.minStoneSum(piles2, 3); // expect: 12 +} diff --git a/remove_stones.rs b/remove_stones.rs new file mode 100644 index 0000000..e55eade --- /dev/null +++ b/remove_stones.rs @@ -0,0 +1,26 @@ +use std::collections::BinaryHeap; +struct Solution; + +impl Solution { + pub fn min_stone_sum(piles: Vec<i32>, mut k: i32) -> i32 { + let mut max_heap = BinaryHeap::<i32>::new(); + for i in piles { + max_heap.push(i); + } + while k > 0 { + if let Some(top) = max_heap.pop() { + let removed = top - top / 2; + max_heap.push(removed); + } + k -= 1; + } + max_heap.iter().sum() + } +} + +fn main() { + let piles1 = vec![5,4,9]; + let piles2 = vec![4,3,6,7]; + println!("{}", Solution::min_stone_sum(piles1, 2)); //expect: 12 + println!("{}", Solution::min_stone_sum(piles2, 3)); //expect: 12 +} diff --git a/remove_substring.c b/remove_substring.c new file mode 100644 index 0000000..7a7aa38 --- /dev/null +++ b/remove_substring.c @@ -0,0 +1,31 @@ +// 1910. Remove All Occurrences of a Substring +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given two strings 's' and 'part', perform the following operation on 's' + * until all occurrences of the substring 'part' are removed; find the leftmost + * occurrence of the substring 'part' and remove it from 's'. return 's' after + * removing all occurrences of 'part'. a substring is a contiguous sequence of + * characters in a string + */ + +char *removeOccurrences(char *s, char *part) { + int s_len = strlen(s), p_len = strlen(part), idx = 0; + char *ans = (char *)malloc((s_len + 1) * sizeof(char)); + for (int i = 0; i < s_len; i++) { + ans[idx++] = s[i]; + if (idx >= p_len && (!strncmp(ans + idx - p_len, part, p_len))) + idx -= p_len; + } + ans[idx] = '\0'; + return ans; +} + +int main() { + char s1[] = {"daabcbaabcbc"}, p1[] = {"abc"}; + char s2[] = {"axxxxyyyyb"}, p2[] = {"xy"}; + printf("%s\n", removeOccurrences(s1, p1)); // expect: dab + printf("%s\n", removeOccurrences(s2, p2)); // expect: ab +} diff --git a/remove_substring.cpp b/remove_substring.cpp new file mode 100644 index 0000000..f3744ab --- /dev/null +++ b/remove_substring.cpp @@ -0,0 +1,48 @@ +// 1910. Remove All Occurrences of a Substring +#include "leetcode.h" + +/* + * given two strings 's' and 'part', perform the following operation on 's' + * until all occurrences of the substring 'part' are removed; find the leftmost + * occurrence of the substring 'part' and remove it from 's'. return 's' after + * removing all occurrences of 'part'. a substring is a contiguous sequence of + * characters in a string + */ + +class Solution { + bool check(stack<char> stk, string part) { + int n = part.size(), j = n - 1; + while (j >= 0 && stk.top() == part[j]) + stk.pop(), j--; + return j == -1; + } + +public: + string removeOccurrences(string s, string part) { + int n1 = s.size(), n2 = part.size(); + stack<char> stk; + string str = ""; + for (int i = 0; i < n1; i++) { + stk.push(s[i]); + if (stk.size() >= n2) + if (check(stk, part)) { + int cnt = n2; + while (cnt--) + stk.pop(); + } + } + string ans = ""; + while (!stk.empty()) { + ans += stk.top(); + stk.pop(); + } + reverse(ans.begin(), ans.end()); + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.removeOccurrences("daabcbaabcbc", "abc") << endl; // expect: dab + cout << obj.removeOccurrences("axxxxyyyyb", "xy") << endl; // expect: ab +} diff --git a/remove_zero_sum_ll.c b/remove_zero_sum_ll.c new file mode 100644 index 0000000..5a9a169 --- /dev/null +++ b/remove_zero_sum_ll.c @@ -0,0 +1,53 @@ +// 1171. Remove Zero Sum Consecutive Nodes from Linked List +#include "leetcode.h" + +/* + * given the 'head' of a linked list, we repeatedly delete the consecutive + * sequences of nodes that sum to 0 until there are no such sequences. after + * doing so, return the head of the final linked list. you may return any such + * answer. + */ + +// Definition for singly-linked list. +struct ListNode { + int val; + struct ListNode *next; +}; + +struct ListNode *get_sum(struct ListNode *head) { + struct ListNode *node = head; + int sum = 0; + while (node) { + sum += node->val; + if (!sum) + return node; + node = node->next; + } + return node; +} + +struct ListNode *removeZeroSumSublists(struct ListNode *head) { + struct ListNode *tmp, *node, *prev, *ans; + tmp = (struct ListNode *)malloc(sizeof(struct ListNode)); + tmp->val = -2000; + tmp->next = head; + while (1) { + prev = tmp; + node = tmp->next; + int n = 0; + while (node) { + ans = get_sum(node); + if (ans) { + prev->next = ans->next; + n = 1; + break; + } else { + prev = node; + node = node->next; + } + } + if (!n) + break; + } + return tmp->next; +} diff --git a/remove_zero_sum_ll.py b/remove_zero_sum_ll.py new file mode 100644 index 0000000..042e0e4 --- /dev/null +++ b/remove_zero_sum_ll.py @@ -0,0 +1,35 @@ +# 1171. Remove Zero Sum Consecutive Nodes from Linked List + +""" +given the 'head' of a linked list, we repeatedly delete the consecutive +sequences of nodes that sum to 0 until there are no such sequences. after +doing so, return the head of the final linked list. you may return any such +answer. +""" + + +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, val=0, next=None): + self.val = val + self.next = next + + +class Solution(object): + def removeZeroSumSublists(self, head): + """ + :type head: ListNode + :rtype: ListNode + """ + curr = tmp = ListNode(0) + tmp.next = head + prefix = 0 + seen = collections.OrderedDict() + while curr: + prefix += curr.val + node = seen.get(prefix, curr) + while prefix in seen: + seen.popitem() + seen[prefix] = node + node.next = curr = curr.next + return tmp.next diff --git a/reorder_list.c b/reorder_list.c new file mode 100644 index 0000000..c44a846 --- /dev/null +++ b/reorder_list.c @@ -0,0 +1,54 @@ +// 143. Reorder List +#include "leetcode.h" + +/* + * given the head of a singly linked list. the list can be represented as 'l0 -> + * l1 -> ... -> Ln'. reorder the list to be of the following form: 'l0 -> ln -> + * ln-1 -> ln-2'. you may not modify the values in the list's nodes. only nodes + * themselves may be changed. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +struct ListNode *get_mid(struct ListNode *head) { + struct ListNode *fast = head, *slow = head; + while (fast->next && fast->next->next) { + fast = fast->next->next; + slow = slow->next; + } + return slow; +} + +struct ListNode *reverse(struct ListNode *head) { + struct ListNode *tail = NULL; + while (head) { + struct ListNode *curr = head; + head = head->next; + curr->next = tail; + tail = curr; + } + return tail; +} + +void merge(struct ListNode *n, struct ListNode *m) { + struct ListNode *head = n; + while (m) { + struct ListNode *tmp = m->next; + m->next = head->next; + head->next = m; + head = head->next->next; + m = tmp; + } +} + +void reorderList(struct ListNode *head) { + if (!head || !head->next || !head->next->next) + return; + struct ListNode *mid = get_mid(head), *half = mid->next; + mid->next = NULL; + half = reverse(half); + merge(head, half); +} diff --git a/reorder_list.py b/reorder_list.py new file mode 100644 index 0000000..c25a277 --- /dev/null +++ b/reorder_list.py @@ -0,0 +1,42 @@ +# 143. Reorder List + +""" +given the head of a singly linked list. the list can be represented as 'l0 -> +l1 -> ... -> Ln'. reorder the list to be of the following form: 'l0 -> ln -> +ln-1 -> ln-2'. you may not modify the values in the list's nodes. only nodes +themselves may be changed. +""" + + +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, val=0, next=None): + self.val = val + self.next = next + + +class Solution(object): + def reorderList(self, head): + """ + :type head: ListNode + :rtype: None Do not return anything, modify head in-place instead. + """ + if not head: + return [] + slow, fast = head, head + while fast.next and fast.next.next: + slow = slow.next + fast = fast.next.next + prev, curr = None, slow.next + while curr: + tmp = curr.next + curr.next = prev + prev = curr + curr = tmp + slow.next = None + head1, head2 = head, prev + while head2: + tmp = head1.next + head1.next = head2 + head1 = head2 + head2 = tmp diff --git a/reorder_route_city_zero.c b/reorder_route_city_zero.c new file mode 100644 index 0000000..c182f34 --- /dev/null +++ b/reorder_route_city_zero.c @@ -0,0 +1,86 @@ +// 1466. Reorder Routes to Make All Paths Lead to the City Zero +#include <stdio.h> +#include <stdlib.h> + +struct node { + int *in; + int in_cnt; + int in_size; + int *out; + int out_cnt; + int out_size; +}; + +void dfs(struct node *n, int curr, int *ans) { + for (int i = 0; i < n[curr].in_cnt; i++) { + if (n[curr].in[i] != -1) { + int next = n[curr].in[i]; + for (int j = 0; j < n[next].out_cnt; j++) { + if (n[next].out[j] == curr) { + n[next].out[j] = -1; + n[curr].in[i] = -1; + dfs(n, next, ans); + } + } + } + } + for (int i = 0; i < n[curr].out_cnt; i++) { + if (n[curr].out[i] != -1) { + int next = n[curr].out[i]; + for (int j = 0; j < n[next].in_cnt; j++) { + if (n[next].in[j] == curr) { + n[next].in[j] = -1; + n[curr].out[i] = -1; + ++*ans; + dfs(n, next, ans); + } + } + } + } +} + +int minReorder(int n, int **connections, int connections_size, + int *connections_col_size) { + struct node *ns = malloc(n * sizeof(struct node)); + for (int i = 0; i < n; i++) { + ns[i].in = malloc(sizeof(int)); + ns[i].in_cnt = 0; + ns[i].in_size = 1; + ns[i].out = malloc(sizeof(int)); + ns[i].out_cnt = 0; + ns[i].out_size = 1; + } + for (int i = 0; i < connections_size; i++) { + int out_idx = connections[i][0]; + ns[out_idx].out[ns[out_idx].out_cnt] = connections[i][0]; + ++ns[out_idx].out_cnt; + if (ns[out_idx].out_cnt == ns[out_idx].out_size) { + ns[out_idx].out_size *= 2; + ns[out_idx].out = + realloc(ns[out_idx].out, ns[out_idx].out_size * sizeof(int)); + } + int in_idx = connections[i][1]; + ns[in_idx].in[ns[in_idx].in_cnt] = connections[i][0]; + ++ns[in_idx].in_cnt; + if (ns[in_idx].in_cnt == ns[in_idx].in_size) { + ns[in_idx].in_size *= 2; + ns[in_idx].in = realloc(ns[in_idx].in, ns[in_idx].in_size * sizeof(int)); + } + } + int ans = 0; + dfs(ns, 0, &ans); + for (int i = 0; i < n; i++) { + free(ns[i].in); + free(ns[i].out); + } + free(ns); + return ans; +} + +int main() { + int c1[5][2] = {{0, 1}, {1, 3}, {2, 3}, {4, 0}, {4, 5}}; + int c2[4][2] = {{1, 0}, {1, 2}, {3, 2}, {3, 4}}; + int c1_c_s[] = {5}, c2_c_s[] = {4}; + printf("%d\n", minReorder(6, c1, 5, c1_c_s)); + printf("%d\n", minReorder(5, c2, 4, c2_c_s)); +} diff --git a/reorder_route_city_zero.cpp b/reorder_route_city_zero.cpp new file mode 100644 index 0000000..cce2c92 --- /dev/null +++ b/reorder_route_city_zero.cpp @@ -0,0 +1,48 @@ +// 1466. Reorder Routes to Make All Paths Lead to the City Zero +#include "leetcode.h" + +/* + * there are 'n' cities numbered from 0 to 'n - 1' and 'n - 1' + * roads such that there is only one way to travel between two + * different cities (this network forms a tree). last year, the + * ministry of transport decided to orient the roads in one + * direction because they are too narrow. + * roads are represented by 'connections' where 'connections[i] = [ai, bi]' + * represents a road from city 'ai' to city 'bi'. + * this year, there will be a big event in the capital (city 0), + * and many people will want to travel to the city. task consists + * reorienting some roads such that each city can visit city 0. + * return minimum number of edges changed. + */ + +class Solution { +public: + int minReorder(int n, vvd(int) & connections) { + vvd(int) ans(n); + for (auto &c : connections) { + ans[c[0]].push_back(c[1]); + ans[c[1]].push_back(-c[0]); + } + return dfs(ans, vector<bool>(n) = {}, 0); + } + +private: + int dfs(vvd(int) & res, vector<bool> visited, int from) { + auto change = 0; + visited[from] = true; + for (auto to : res[from]) + if (!visited[abs(to)]) + change += dfs(res, visited, abs(to)) + (to > 0); + return change; + } +}; + +int main() { + Solution obj; + vvd(int) connections1 = {{0, 1}, {1, 3}, {2, 3}, {4, 0}, {4, 5}}; + vvd(int) connections2 = {{1, 0}, {1, 2}, {3, 2}, {3, 4}}; + vvd(int) connections3 = {{1, 0}, {2, 0}}; + cout << obj.minReorder(6, connections1) << endl; // expect: 3 + cout << obj.minReorder(5, connections2) << endl; // expect: 2 + cout << obj.minReorder(3, connections3) << endl; // expect: 0 +} diff --git a/reordered_power2.cpp b/reordered_power2.cpp new file mode 100644 index 0000000..d458052 --- /dev/null +++ b/reordered_power2.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + bool reorderedPowerOf2(int n) { + string ans1 = to_string(n); + sort(ans1.begin(), ans1.end()); + for (int i = 0; i < 30; i++) { + string ans2 = to_string(1 << i); + sort(ans2.begin(), ans2.end()); + if (ans1 == ans2) + return true; + } + return false; + } +}; + +int main() { + Solution obj; + if (obj.reorderedPowerOf2(10)) + cout << "true"; + else + cout << "false"; +} diff --git a/reorganise_string.c b/reorganise_string.c new file mode 100644 index 0000000..e4c0be4 --- /dev/null +++ b/reorganise_string.c @@ -0,0 +1,52 @@ +// 767. Reorganize String +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a string 's', rearrange the characters of 's' so that any two adjacent + * characters are not the same. return any possible arrangement of 's', or + * return "" if not possible. + */ + +char find_max(int hist[26], char c) { + int max = 0; + char out = '\0'; + for (int i = 0; i < 26; i++) + if (i + 'a' != c && hist[i] > max) { + max = hist[i]; + out = i + 'a'; + } + return out; +} + +char *reorganizeString(char *s) { + int hist[26] = {0}; + if (!strlen(s)) + return s; + for (int i = 0; i < strlen(s); i++) + hist[s[i] - 'a']++; + char max = find_max(hist, '\0'), last; + int idx = 0; + char *out = (char *)malloc(sizeof(char) * (strlen(s) + 1)); + while (max != '\0') { + out[idx++] = max; + last = max; + hist[last - 'a']--; + max = find_max(hist, last); + } + if (idx != strlen(s)) { + free(out); + return ""; + } + out[idx] = '\0'; + strcpy(s, out); + free(out); + return s; +} + +int main() { + char s1[] = {"aab"}, s2[] = {"aaab"}; + printf("%s\n", reorganizeString(s1)); // expect: aba + printf("%s\n", reorganizeString(s2)); // expect: +} diff --git a/reorganise_string.cpp b/reorganise_string.cpp new file mode 100644 index 0000000..7a42643 --- /dev/null +++ b/reorganise_string.cpp @@ -0,0 +1,41 @@ +// 767. Reorganize String +#include "leetcode.h" + +/* + * given a string 's', rearrange the characters of 's' so that any two adjacent + * characters are not the same. return any possible arrangement of 's', or + * return "" if not possible. + */ + +class Solution { +public: + string reorganizeString(string s) { + vector<int> cnt(26); + int most_freq = 0, i = 0; + for (char c : s) + if (++cnt[c - 'a'] > cnt[most_freq]) + most_freq = (c - 'a'); + if (2 * cnt[most_freq] - 1 > s.size()) + return ""; + while (cnt[most_freq]) { + s[i] = ('a' + most_freq); + i += 2; + cnt[most_freq]--; + } + for (int j = 0; j < 26; j++) + while (cnt[j]) { + if (i >= s.size()) + i = 1; + s[i] = ('a' + j); + cnt[j]--; + i += 2; + } + return s; + } +}; + +int main() { + Solution obj; + cout << obj.reorganizeString("aab"); // expect: aba + cout << obj.reorganizeString("aaab"); // expect: +} diff --git a/repeated_substring_pattern.c b/repeated_substring_pattern.c new file mode 100644 index 0000000..a5d2d52 --- /dev/null +++ b/repeated_substring_pattern.c @@ -0,0 +1,38 @@ +// 459. Repeated Substring Pattern +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +/* + * given a string 's', check if it can be constructed by taking a substring of + * it and appending multiple copies of the substring together. + */ + +bool repeatedSubstringPattern(char *s) { + int n = strlen(s), sub_len; + bool ans; + if (n == 1) + return false; + for (sub_len = 1; sub_len <= n / 2; sub_len++) { + if (n % sub_len) { + ans = false; + continue; + } + ans = true; + for (int i = 0; i < n; i += sub_len) + if (strncmp(s + i, s, sub_len)) { + ans = false; + break; + } + if (ans) + return true; + } + return ans; +} + +int main() { + char s1[] = {"abab"}, s2[] = {"aba"}, s3[] = {"abcabcabcabc"}; + printf("%d\n", repeatedSubstringPattern(s1)); // expect: 1 + printf("%d\n", repeatedSubstringPattern(s2)); // expect: 0 + printf("%d\n", repeatedSubstringPattern(s3)); // expect: 1 +} diff --git a/repeated_substring_pattern.cpp b/repeated_substring_pattern.cpp new file mode 100644 index 0000000..4e2d8d8 --- /dev/null +++ b/repeated_substring_pattern.cpp @@ -0,0 +1,31 @@ +// 459. Repeated Substring Pattern +#include "leetcode.h" + +/* + * given a string 's', check if it can be constructed by taking a substring of + * it and appending multiple copies of the substring together. + */ + +class Solution { +public: + bool repeatedSubstringPattern(string s) { + int i = 1, j = 0, n = s.size(); + vector<int> dp(n + 1, 0); + while (i < n) { + if (s[i] == s[j]) + dp[++i] = ++j; + else if (!j) + i++; + else + j = dp[j]; + } + return dp[n] && dp[n] % (n - dp[n]) == 0; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.repeatedSubstringPattern("abab")); // expect: 1 + printf("%d\n", obj.repeatedSubstringPattern("aba")); // expect: 0 + printf("%d\n", obj.repeatedSubstringPattern("abcabcabcabc")); // expect: 1 +} diff --git a/replace_digit_char.c b/replace_digit_char.c new file mode 100644 index 0000000..53f0c8f --- /dev/null +++ b/replace_digit_char.c @@ -0,0 +1,23 @@ +// 1844. Replace All Digits with Characters +#include "leetcode.h" + +/* + * given a 0-indexed string 's' that has lowercase english letters in its even + * indices and digits in its odd indices. there is a function 'shift(x, c)' + * where 'x' is a character and 'c' is an integer that returns the c'th + * character after 'x'. for every odd index 'i', you want to replace the digit + * 's[i]' with shift(s[i - 1], s[i]). return 's' after replacing all digits. + */ + +char *replaceDigits(char *s) { + int n = strlen(s); + for (int i = 1; i < n; i++) + s[i] += s[i - 1] - '0'; + return s; +} + +int main() { + char *s1 = "a1c1e1", *s2 = "a1b2c3d4e"; + printf("%s\n", replaceDigits(s1)); // expect: abcdef + printf("%s\n", replaceDigits(s2)); // expect: abbdcfdhe +} diff --git a/replace_words.c b/replace_words.c new file mode 100644 index 0000000..ed509d0 --- /dev/null +++ b/replace_words.c @@ -0,0 +1,98 @@ +// 648. Replace Words +#include "leetcode.h" + +/* + * in english we have a concept called root, which can be followed by some other + * word to form another longer word lets call this word derivative. for example + * when the root "help" is followed by the word "ful" we can form a derivative + * "helpful". given a dictionary consisting of many roots and a 'sentence' + * consisting of words separated by spaces, replace all the derivatives in the + * sentence with the root forming it. if a derivative can be replaced by more + * than one root, replace it with the root that has the shortest length. return + * the 'sentence' after the replacement + */ + +typedef struct Trie { + struct Trie *children[26]; + bool is_leaf; +} Trie; + +Trie *create() { + Trie *node = (Trie *)malloc(sizeof(Trie)); + for (int i = 0; i < 26; i++) + node->children[i] = NULL; + node->is_leaf = false; + return node; +} + +void insert(Trie *obj, char *word) { + Trie *tmp = obj; + for (int i = 0; word[i] != '\0'; i++) { + int idx = word[i] - 'a'; + if (!tmp->children[idx]) + tmp->children[idx] = create(); + tmp = tmp->children[idx]; + } + tmp->is_leaf = true; +} + +int trieSearch(Trie *obj, char *word) { + Trie *tmp = obj; + int curr = 0; + for (int i = 0; word[i] != '\0'; i++) { + if (word[i] == ' ') + return 0; + int idx = word[i] - 'a'; + if (!tmp->children[idx]) + return 0; + curr++; + if (tmp->children[idx]->is_leaf) + return curr; + tmp = tmp->children[idx]; + } + return 0; +} + +int substring(char *str) { + int l = strlen(str); + for (int i = 0; i < l; i++) + if (str[i] == ' ') { + str[i] = '\0'; + return i; + } + return l; +} + +char *replaceWords(char **dictionary, int dictionarySize, char *sentence) { + Trie *root = create(); + for (int i = 0; i < dictionarySize; i++) + insert(root, dictionary[i]); + int len = strlen(sentence), a_idx = 0, idx = 0; + char *ans = (char *)malloc((len + 1) * sizeof(char)); + while (idx < len) { + int d = substring(&sentence[idx]); + int l = trieSearch(root, &sentence[idx]); + if (l) { + strncpy(&ans[a_idx], &sentence[idx], l); + ans[a_idx + l] = ' '; + a_idx += l + 1; + } else { + strncpy(&ans[a_idx], &sentence[idx], d); + ans[a_idx + d] = ' '; + a_idx += d + 1; + } + idx += d + 1; + } + ans[a_idx - 1] = '\0'; + return ans; +} + +int main() { + char *d1[] = {"cat", "bat", "rat"}, *d2[] = {"a", "b", "c"}; + char *s1 = "the cattle was rattled by the battery", + *s2 = "aadsfasf absbs bbab cadsfafs"; + printf("%s\n", replaceWords((char **)d1, ARRAY_SIZE(d1), + s1)); // expect: the cat was rat by the bat + printf("%s\n", + replaceWords((char **)d2, ARRAY_SIZE(d2), s2)); // expect: a a b c +} diff --git a/replace_words.py b/replace_words.py new file mode 100644 index 0000000..e72f954 --- /dev/null +++ b/replace_words.py @@ -0,0 +1,57 @@ +# 648. Replace Words +from collections import defaultdict + +""" +in english we have a concept called root, which can be followed by some other +word to form another longer word lets call this word derivative. for example +when the root "help" is followed by the word "ful" we can form a derivative +"helpful". given a dictionary consisting of many roots and a 'sentence' +consisting of words separated by spaces, replace all the derivatives in the +sentence with the root forming it. if a derivative can be replaced by more +than one root, replace it with the root that has the shortest length. return +the 'sentence' after the replacement +""" + + +class Solution(object): + def replaceWords(self, dictionary, sentence): + """ + :type dictionary: List[str] + :type sentence: str + :rtype: str + """ + _trie = lambda: defaultdict(_trie) + trie = _trie() + end = True + for w in dictionary: + curr = trie + for l in w: + curr = curr[l] + curr[end] = w + + def replace(word): + curr = trie + for l in word: + if l not in curr: + break + curr = curr[l] + if end in curr: + return curr[end] + return word + + return "".join(map(replace, sentence.split())) + + +if __name__ == "__main__": + obj = Solution() + print( + obj.replaceWords( + dictionary=["cat", "bat", "rat"], + sentence="the cattle was rattled by the battery", + ) + ) + print( + obj.replaceWords( + dictionary=["a", "b", "c"], sentence="aadsfasf absbs bbab cadsfafs" + ) + ) diff --git a/restore_array.c b/restore_array.c new file mode 100644 index 0000000..16efddc --- /dev/null +++ b/restore_array.c @@ -0,0 +1,41 @@ +// 1416. Restore The Array +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * a progamme was supposed to print an array of integers. the programme forgot + * to print whitespace and the array is printing as a string of digits 's' and + * all we know is that all integers in the array were in the range [1, k] and + * there are no leading zeros in the array. given the string 's' and the integer + * 'k', return the number of possible arrays that can be printed as 's' using + * the mentioned programme. return modulo 10^9+7 + */ + +int numberOfArrays(char *s, int k) { + const int mod = 1e9 + 7; + int n = strlen(s); + int *dp = calloc(n + 1, sizeof(int)); + dp[n] = 1; + for (int i = n - 1; i >= 0; i--) { + if (s[i] == '0') + continue; + long long num = 0; + for (int j = i; j < n; j++) { + num = num * 10 + s[j] - '0'; + if (num > k) + break; + dp[i] = (dp[i] + dp[j + 1]) % mod; + } + } + int ans = dp[0]; + free(dp); + return ans; +} + +int main() { + char s1_2[] = {"1000"}, s3[] = {"1317"}; + printf("%d\n", numberOfArrays(s1_2, 10000)); // expect: 1 + printf("%d\n", numberOfArrays(s1_2, 10)); // expect: 0 + printf("%d\n", numberOfArrays(s3, 2000)); // expect: 8 +} diff --git a/restore_array.cpp b/restore_array.cpp new file mode 100644 index 0000000..4f4a59a --- /dev/null +++ b/restore_array.cpp @@ -0,0 +1,37 @@ +// 1416. Restore The Array +#include "leetcode.h" + +/* + * a progamme was supposed to print an array of integers. the programme forgot + * to print whitespace and the array is printing as a string of digits 's' and + * all we know is that all integers in the array were in the range [1, k] and + * there are no leading zeros in the array. given the string 's' and the integer + * 'k', return the number of possible arrays that can be printed as 's' using + * the mentioned programme. return modulo 10^9+7 + */ + +class Solution { +public: + int numberOfArrays(string s, int k) { + vector<int> dp(s.size() + 1); + dp[s.size()] = 1; + for (int i = s.size() - 1; i >= 0; --i) { + if (s[i] == '0') + continue; + for (long sz = 1, n = 0; i + sz <= s.size(); ++sz) { + n = n * 10 + s[i + sz - 1] - '0'; + if (n > k) + break; + dp[i] = (dp[i] + dp[i + sz]) % 1000000007; + } + } + return dp[0]; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.numberOfArrays("1000", 10000)); // expect: 1 + printf("%d\n", obj.numberOfArrays("1000", 10)); // expect: 0 + printf("%d\n", obj.numberOfArrays("1317", 2000)); // expect: 8 +} diff --git a/restore_array_adj_pair.c b/restore_array_adj_pair.c new file mode 100644 index 0000000..2d0ea12 --- /dev/null +++ b/restore_array_adj_pair.c @@ -0,0 +1,139 @@ +// 1743. Restore the Array From Adjacent Pairs +#include "leetcode.h" + +/* + * there is an integer array 'nums' that contains 'n' unique elements, but you + * have forgotten it. however, you do remember that every pair of adjacent + * elements in 'nums'. you are given a 2d integer array 'adjacent_pairs' of size + * 'n - 1' where each adjacent_pairs[i] = [ui, vi] indicates that the elements + * 'ui' and 'vi' are adjacent in 'nums'. it is guaranteed that every adjacent + * pair of elements 'nums[i]' and 'nums[i + 1]' will exist in 'adjacent_pairs' + * either as '[nums[i], nums[i + 1]]'. the pairs can appear in any order. return + * the original array 'nums'. if there are multiple solutions, return any of + * them. + */ + +typedef struct { + int key; + int size; + int *data; +} edge; + +int findFirst(int **adjacent_pairs, int adjacent_pairs_size, edge **hash, int n, + int *neighbor) { + int val, d; + for (int i = 0; i < adjacent_pairs_size; i++) { + val = adjacent_pairs[i][0]; + d = abs(val); + while (1) { + if (hash[d % n]->key == val) + if (hash[d % n]->size == 1) { + *neighbor = hash[d % n]->data[0]; + return val; + } else + break; + else + d++; + } + val = adjacent_pairs[i][1]; + d = abs(val); + while (1) { + if (hash[d % n]->key == val) + if (hash[d % n]->size == 1) { + *neighbor = hash[d % n]->data[0]; + return val; + } else + break; + else + d++; + } + } + return INT_MAX; +} + +void findnext(int **adjacent_pairs, int adjacent_pairs_size, edge **hash, int n, + int ptr, int *one, int *two) { + int d = abs(ptr); + while (1) { + if (hash[d % n]->key == ptr) { + *one = hash[d % n]->data[0]; + *two = hash[d % n]->data[1]; + return; + } else + d++; + } +} + +int *restoreArray(int **adjacent_pairs, int adjacent_pairs_size, + int *adjacent_pairsColSize, int *returnSize) { + int n = adjacent_pairs_size + 1; + int n = 10 * n; + edge **hash = calloc(n, sizeof(edge *)); + for (int i = 0; i < adjacent_pairs_size; i++) { + int a = adjacent_pairs[i][0]; + int b = adjacent_pairs[i][1]; + int val = a; + int d = abs(val); + + while (1) { + if (!hash[d % n]) { + hash[d % n] = malloc(sizeof(edge)); + hash[d % n]->data = malloc(2 * sizeof(int)); + hash[d % n]->key = val; + hash[d % n]->size = 1; + hash[d % n]->data[0] = b; + break; + } else if (hash[d % n]->key == val) { + hash[d % n]->size = 2; + hash[d % n]->data[1] = b; + break; + } else + d++; + } + + val = b; + d = abs(val); + while (1) { + if (!hash[d % n]) { + hash[d % n] = malloc(sizeof(edge)); + hash[d % n]->data = malloc(2 * sizeof(int)); + hash[d % n]->key = val; + hash[d % n]->size = 1; + hash[d % n]->data[0] = a; + break; + } else if (hash[d % n]->key == val) { + hash[d % n]->size = 2; + hash[d % n]->data[1] = a; + break; + } else + d++; + } + } + + int neighbor; + int first = + findFirst(adjacent_pairs, adjacent_pairs_size, hash, n, &neighbor); + + int *ans = malloc(n * sizeof(int)); + *returnSize = n; + ans[0] = first; + ans[1] = neighbor; + int ptr = neighbor; + int a, b; + for (int i = 2; i < n; i++) { + findnext(adjacent_pairs, adjacent_pairs_size, hash, n, ptr, &a, &b); + if (ans[i - 2] == a) + ans[i] = b; + else + ans[i] = a; + ptr = ans[i]; + } + + for (int i = 0; i < n; i++) + if (hash[i]) { + free(hash[i]->data); + free(hash[i]); + } + free(hash); + return ans; +} diff --git a/restore_array_adj_pair.py b/restore_array_adj_pair.py new file mode 100644 index 0000000..6cf6b63 --- /dev/null +++ b/restore_array_adj_pair.py @@ -0,0 +1,42 @@ +# 1743. Restore the Array From Adjacent Pairs + +""" +there is an integer array 'nums' that contains 'n' unique elements, but you +have forgotten it. however, you do remember that every pair of adjacent +elements in 'nums'. you are given a 2d integer array 'adjacent_pairs' of size +'n - 1' where each adjacent_pairs[i] = [ui, vi] indicates that the elements +'ui' and 'vi' are adjacent in 'nums'. it is guaranteed that every adjacent +pair of elements 'nums[i]' and 'nums[i + 1]' will exist in 'adjacent_pairs' +either as '[nums[i], nums[i + 1]]'. the pairs can appear in any order. return +the original array 'nums'. if there are multiple solutions, return any of +them. +""" + + +class Solution(object): + def restoreArray(self, vals): + pairs = defaultdict(list) + + for val in vals: + pairs[val[0]].append(val[1]) + pairs[val[1]].append(val[0]) + + ans = [] + start = -1000000 + + for entry in pairs: + if len(pairs[entry]) == 1: + start = entry + break + + left = -1000000 + ans.append(start) + + for i in range(1, len(vals) + 1): + val = pairs[start] + newval = val[0] if val[0] != left else val[1] + ans.append(newval) + left = start + start = newval + + return ans diff --git a/restore_ip_addr.c b/restore_ip_addr.c new file mode 100644 index 0000000..e814691 --- /dev/null +++ b/restore_ip_addr.c @@ -0,0 +1,74 @@ +// 93. Restore IP Addresses +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#define IN_RANGE(c, m, n) ((c) >= (m) && c <= (n)) + +/* + * a valid ip address consists of exactly 4 integers separated by single dots + * each integer is between 0 and 255 (inclusive) and cannot have leading 0's + * given: string 's' containing only digits, return all possible valid ip + * addresses that can be formed by insert dots into 's'. digits cannot be + * reordered or removed. return addresses in any order. + */ + +int isValidPart(char *s, int l) { + switch (l) { + case 1: + return IN_RANGE(s[0], '0', '9'); + break; + case 2: + return IN_RANGE(s[0], '1', '9') && IN_RANGE(s[1], '0', '9'); + break; + case 3: + return (s[0] == '1' && IN_RANGE(s[1], '0', '9') && + IN_RANGE(s[2], '0', '9')) || + (s[0] == '2' && + (IN_RANGE(s[1], '0', '4') && IN_RANGE(s[2], '0', '9') || + s[1] == '5' && IN_RANGE(s[2], '0', '5'))); + break; + default: + return 0; + } +} + +char *getAddr(char *s, int l, int a, int b, int c) { + if (isValidPart(s, a) && isValidPart(s + a, b - a) && + isValidPart(s + b, c - b) && isValidPart(s + c, l - c)) { + char *addr = malloc(sizeof(char) * (l + 4)); + memcpy(addr, s, a); + memcpy(addr + a + 1, s + a, b - a); + memcpy(addr + b + 2, s + b, c - b); + memcpy(addr + c + 3, s + c, l - c); + addr[a] = addr[b + 1] = addr[c + 2] = '.'; + addr[l + 3] = '\0'; + return addr; + } else + return NULL; +} + +char **restoreIpAddresses(char *s, int *returnSize) { + *returnSize = 0; + int l = strlen(s), a, b, c; + if (l < 4 || l > 12) + return NULL; + char **addrs = malloc(sizeof(char *) * ((l - 1) * (l - 2) * (l - 3) / 6)), + *addr; + for (a = 1; a < 4; a++) { + if (a > l - 3 || a < l - 9) + continue; + for (b = a + 1; b < a + 4; b++) { + if (b > l - 2 || b < l - 6) + continue; + for (c = b + 1; c < b + 4; c++) { + if (c > l - 1 || c < l - 3) + continue; + if (addr = getAddr(s, l, a, b, c)) + addrs[(*returnSize)++] = addr; + } + } + } + return addrs; +} + +int main() { char s1[] = {"25525511135"}, s2[] = {"0000"}, s3[] = {"101023"}; } diff --git a/restore_ip_addr.cpp b/restore_ip_addr.cpp new file mode 100644 index 0000000..eba5de2 --- /dev/null +++ b/restore_ip_addr.cpp @@ -0,0 +1,56 @@ +// 93. Restore IP Addresses +#include "leetcode.h" + +/* + * a valid ip address consists of exactly 4 integers separated by single dots + * each integer is between 0 and 255 (inclusive) and cannot have leading 0's + * given: string 's' containing only digits, return all possible valid ip + * addresses that can be formed by insert dots into 's'. digits cannot be + * reordered or removed. return addresses in any order. + */ + +class Solution { +public: + vector<string> restoreIpAddresses(string s) { + vector<string> ans; + string ip; + dfs(s, 0, 0, ip, ans); + return ans; + } + +private: + void dfs(string s, int start, int step, string ip, vector<string> &res) { + if (start == s.size() && step == 4) { + ip.erase(ip.end() - 1); + res.push_back(ip); + return; + } + if (s.size() - start > (4 - step) * 3) + return; + if (s.size() - start < (4 - step)) + return; + int num = 0; + for (int i = start; i < start + 3; i++) { + num = num * 10 + (s[i] - '0'); + if (num <= 255) { + ip += s[i]; + dfs(s, i + 1, step + 1, ip + '.', res); + } + if (num == 0) + break; + } + } +}; + +int main() { + Solution obj; + for (auto i : obj.restoreIpAddresses("25525511135")) + cout << i; // expect: 255.255.11.135","255.255.111.35 + cout << endl; + for (auto i : obj.restoreIpAddresses("0000")) + cout << i; // expect: 0.0.0.0 + cout << endl; + for (auto i : obj.restoreIpAddresses("101023")) + cout << i; // expect: 1.0.10.23,1.0.102.3,10.1.0.23,10.10.2.3,101.0.2.3 + cout << endl; +} diff --git a/reveal_cards_incr_order.c b/reveal_cards_incr_order.c new file mode 100644 index 0000000..eab5c20 --- /dev/null +++ b/reveal_cards_incr_order.c @@ -0,0 +1,72 @@ +// 950. Reveal Cards In Increasing Order +#include "leetcode.h" + +/* + * given an integer array 'deck'. there is a deck of cards where every card has + * a unique integer. the integer on the i'th card is 'deck[i]'. you can order + * the deck in any order you want. initially, all the cards start face down + * (unrevealed) in one deck. you will do the following steps repeatedly until + * all cards are revealed. take the top card of the deck, reveal it, and take it + * out of the deck. if there are still cards in the deck, then put the next top + * card of the deck at the bottom of the deck. if there are still unrevealed + * cards, go back to step 1, otherwise stop. return an ordering of the deck that + * would reveal the cards in increasing order. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +typedef struct ListNode l_node; + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int *deckRevealedIncreasing(int *deck, int deckSize, int *returnSize) { + l_node *head = malloc(sizeof(l_node)); + head->val = 0; + l_node *tmp = head; + for (int i = 1; i < deckSize; i++) { + l_node *n = malloc(sizeof(l_node)); + n->val = i; + tmp->next = n; + tmp = n; + } + l_node *tail = tmp; + tail->next = NULL; + tmp = head; + l_node *post; + while (tmp->next && tmp->next->next) { + post = tmp->next; + tmp->next = tmp->next->next; + tail->next = post; + tail = post; + tail->next = NULL; + tmp = tmp->next; + } + int *ans = malloc(deckSize * sizeof(int)); + qsort(deck, deckSize, sizeof(int), cmp); + tmp = head; + l_node *ptr; + for (int i = 0; i < deckSize; i++) { + ans[tmp->val] = deck[i]; + ptr = tmp; + tmp = tmp->next; + free(ptr); + } + *returnSize = deckSize; + return ans; +} + +int main() { + int d1[] = {17, 13, 11, 2, 3, 5, 7}, d2[] = {1, 1000}, rs1, rs2; + int *dri1 = deckRevealedIncreasing(d1, ARRAY_SIZE(d1), &rs1); + int *dri2 = deckRevealedIncreasing(d2, ARRAY_SIZE(d2), &rs2); + for (int i = 0; i < rs1; i++) + printf("%d ", dri1[i]); // expect: 2,13,3,11,5,17,7 + printf("\n"); + for (int i = 0; i < rs2; i++) + printf("%d ", dri2[i]); // expect: 1,1000 + printf("\n"); + free(dri1), free(dri2); +} diff --git a/reveal_cards_incr_order.py b/reveal_cards_incr_order.py new file mode 100644 index 0000000..2a1ca55 --- /dev/null +++ b/reveal_cards_incr_order.py @@ -0,0 +1,33 @@ +# 950. Reveal Cards In Increasing Order +from collections import deque + +""" +given an integer array 'deck'. there is a deck of cards where every card has +a unique integer. the integer on the i'th card is 'deck[i]'. you can order +the deck in any order you want. initially, all the cards start face down +(unrevealed) in one deck. you will do the following steps repeatedly until +all cards are revealed. take the top card of the deck, reveal it, and take it +out of the deck. if there are still cards in the deck, then put the next top +card of the deck at the bottom of the deck. if there are still unrevealed +cards, go back to step 1, otherwise stop. return an ordering of the deck that +would reveal the cards in increasing order. +""" + + +class Solution(object): + def deckRevealedIncreasing(self, deck): + """ + :type deck: List[int] + :rtype: List[int] + """ + d = deque() + for i in sorted(deck)[::-1]: + d.rotate() + d.appendleft(i) + return list(d) + + +if __name__ == "__main__": + obj = Solution() + print(obj.deckRevealedIncreasing(deck=[17, 13, 11, 2, 3, 5, 7])) + print(obj.deckRevealedIncreasing(deck=[1, 1000])) diff --git a/reverse_integer.c b/reverse_integer.c new file mode 100644 index 0000000..71d9c20 --- /dev/null +++ b/reverse_integer.c @@ -0,0 +1,63 @@ +// 7. Reverse Integer +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a signed 32-bit integer 'x', return 'x' with its digits reversed. if + * reversing 'x' causes the value to go outside the signed 32-bit integer range, + * then return 0 + */ + +int reverse(int x) { + int negative = 0, len, tmp; + if (x) { + if (x < INT_MAX - 1) { + } else { + return 0; + } + } else { + if (x > INT_MIN + 1) { + } else { + return 0; + } + } + if (x < 0) { + negative = 1; + x = -x; + } + char str[1000]; + sprintf(str, "%d", x); + len = strlen(str); + if (x < 0) { + negative = 1; + x = -x; + } + for (int i = 0; i < len / 2; i++) { + tmp = str[len - 1 - i]; + str[len - 1 - i] = str[i]; + str[i] = tmp; + } + long long ans = strtol(str, (char **)NULL, 10); + if (ans) { + if (ans < INT_MAX - 1) { + } else { + return 0; + } + } else { + if (ans > INT_MIN + 1) { + } else { + return 0; + } + } + if (negative == 1) + ans = -ans; + return (int)ans; +} + +int main() { + printf("%d --> %d\n", 123, reverse(123)); + printf("%d --> %d\n", -123, reverse(-123)); + printf("%d --> %d\n", 120, reverse(120)); +} diff --git a/reverse_integer.cpp b/reverse_integer.cpp new file mode 100644 index 0000000..14f55cd --- /dev/null +++ b/reverse_integer.cpp @@ -0,0 +1,30 @@ +// 7. Reverse Integer +#include "leetcode.h" + +/* + * given a signed 32-bit integer 'x', return 'x' with its digits reversed. if + * reversing 'x' causes the value to go outside the signed 32-bit integer range, + * then return 0 + */ + +class Solution { +public: + int reverse(int x) { + int ans = 0; + while (x) { + int tmp = ans * 10 + x % 10; + if (tmp / 10 != ans) + return 0; + ans = tmp; + x /= 10; + } + return ans; + } +}; + +int main() { + Solution obj; + printf("%d --> %d\n", 123, obj.reverse(123)); + printf("%d --> %d\n", -123, obj.reverse(-123)); + printf("%d --> %d\n", 120, obj.reverse(120)); +} diff --git a/reverse_linked_list.c b/reverse_linked_list.c new file mode 100644 index 0000000..89358f8 --- /dev/null +++ b/reverse_linked_list.c @@ -0,0 +1,28 @@ +// 206. Reverse Linked List +#include "leetcode.h" + +/* + * given the 'head' of a singly linked list, reverse the list, and return the + * reversed list. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +struct ListNode *reverseList(struct ListNode *head) { + if (!head || !head->next) + return head; + struct ListNode *new = (struct ListNode *)malloc(sizeof(struct ListNode)); + new->val = head->val; + new->next = NULL; + head = head->next; + while (head) { + struct ListNode *tmp = new; + new = head; + head = head->next; + new->next = tmp; + } + return new; +} diff --git a/reverse_linked_list.cpp b/reverse_linked_list.cpp new file mode 100644 index 0000000..e3a1793 --- /dev/null +++ b/reverse_linked_list.cpp @@ -0,0 +1,16 @@ +#include "leetcode.h" + +class Solution { +public: + ListNode *reverseList(ListNode *head) { + ListNode *pre = new ListNode(0), *curr = head; + pre->next = head; + while (curr && curr->next) { + ListNode *tmp = pre->next; + pre->next = curr->next; + curr->next = curr->next->next; + pre->next->next = tmp; + } + return pre->next; + } +}; diff --git a/reverse_linked_list.py b/reverse_linked_list.py new file mode 100644 index 0000000..53a8481 --- /dev/null +++ b/reverse_linked_list.py @@ -0,0 +1,35 @@ +# 206. Reverse Linked List + +""" +given the 'head' of a singly linked list, reverse the list, and return the +reversed list. +""" + + +# Definition for singly-linked list. +class ListNode(object): + def __init__(self, val=0, next=None): + self.val = val + self.next = next + + +class Solution(object): + def reverseList(self, head): + """ + :type head: ListNode + :rtype: ListNode + """ + prev = None + while head: + curr = head + head = head.next + curr.next = prev + prev = curr + return prev + + +if __name__ == "__main__": + obj = Solution() + print(obj.reverseList(head=[1, 2, 3, 4, 5])) + print(obj.reverseList(head=[1, 2])) + print(obj.reverseList(head=[])) diff --git a/reverse_linked_list2.cpp b/reverse_linked_list2.cpp new file mode 100644 index 0000000..dbbb261 --- /dev/null +++ b/reverse_linked_list2.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + ListNode *reverseBetween(ListNode *head, int left, int right) { + if (head == NULL || head->next == NULL) + return head; + ListNode *tmp = new ListNode(-1); + tmp->next = head; + ListNode *itL = tmp, *preL = NULL; + for (int i = 0; i < left; i++) { + preL = itL; + itL = itL->next; + } + ListNode *itR = itL, *preR = preL; + for (int i = left; i <= right; i++) { + ListNode *forward = itR->next; + itR->next = preR; + preR = itR; + itR = forward; + } + preL->next = preR; + itL->next = itR; + return tmp->next; + } +}; diff --git a/reverse_node_k.cpp b/reverse_node_k.cpp new file mode 100644 index 0000000..e57291a --- /dev/null +++ b/reverse_node_k.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + ListNode *reverseKGroup(ListNode *head, int k) { + ListNode *cursor = head; + for (int i = 0; i < k; i++) { + if (cursor == nullptr) + return head; + cursor = cursor->next; + } + ListNode *curr = head; + ListNode *prev = nullptr; + ListNode *next = nullptr; + for (int i = 0; i < k; i++) { + next = curr->next; + curr->next = prev; + prev = curr; + curr = next; + } + head->next = reverseKGroup(curr, k); + return prev; + } +}; + +int main() {} diff --git a/reverse_prefix_word.c b/reverse_prefix_word.c new file mode 100644 index 0000000..079d9fe --- /dev/null +++ b/reverse_prefix_word.c @@ -0,0 +1,33 @@ +// 2000. Reverse Prefix of Word +#include "leetcode.h" + +/* + * given a 0-indexed string 'word' and a character 'ch', reverse the segment of + * 'word' that starts at index 0 and ends at the index of the first occurence of + * 'ch' (inclusively). if the character 'ch' does not exist in 'word', do + * nothing. return the resulting string. + */ + +char *reversePrefix(char *word, char ch) { + int n = strlen(word), loc = -1; + for (int i = 0; i < n; i++) + if (word[i] == ch) { + loc = i; + break; + } + if (loc == -1) + return word; + for (int i = 0; i <= loc / 2; i++) { + char tmp = word[i]; + word[i] = word[loc - i]; + word[loc - i] = tmp; + } + return word; +} + +int main() { + char *w1 = "abcdefd", *w2 = "xyxzxe", *w3 = "abcd"; + printf("%s\n", reversePrefix(w1, 'd')); // expect: dcbaefd + printf("%s\n", reversePrefix(w2, 'z')); // expect: zxyxxe + printf("%s\n", reversePrefix(w3, 'z')); // expect: abcd +} diff --git a/reverse_prefix_word.py b/reverse_prefix_word.py new file mode 100644 index 0000000..008d53d --- /dev/null +++ b/reverse_prefix_word.py @@ -0,0 +1,28 @@ +# 2000. Reverse Prefix of Word + +""" +given a 0-indexed string 'word' and a character 'ch', reverse the segment of +'word' that starts at index 0 and ends at the index of the first occurence of +'ch' (inclusively). if the character 'ch' does not exist in 'word', do +nothing. return the resulting string. +""" + + +class Solution(object): + def reversePrefix(self, word, ch): + """ + :type word: str + :type ch: str + :rtype: str + """ + idx = word.find(ch) + if idx: + return word[: idx + 1][::-1] + word[idx + 1 :] + return word + + +if __name__ == "__main__": + obj = Solution() + print(obj.reversePrefix("abcdefd", "d")) + print(obj.reversePrefix("xyxzxe", "z")) + print(obj.reversePrefix("abcd", "z")) diff --git a/reverse_string.c b/reverse_string.c new file mode 100644 index 0000000..c94403f --- /dev/null +++ b/reverse_string.c @@ -0,0 +1,25 @@ +// 344. Reverse String +#include "leetcode.h" + +/* + * write a function that reverses a string. the input string is given as an + * array of characters 's'. you must do this by modifying teh input array in + * place with 'O(1)' extra memroy + */ + +void reverseString(char *s, int sSize) { + char *ptr = s + sSize - 1, tmp = *s; + if (sSize <= 1) + return; + *s = *ptr; + *ptr = tmp; + reverseString(s + 1, sSize - 2); +} + +int main() { + char *s1 = "hello", *s2 = "Hannah"; + reverseString(s1, strlen(s1)); + reverseString(s2, strlen(s2)); + printf("%s\n", s1); // expect: olleh + printf("%s\n", s2); // expect: hannaH +} diff --git a/reverse_string.cpp b/reverse_string.cpp new file mode 100644 index 0000000..f5940a0 --- /dev/null +++ b/reverse_string.cpp @@ -0,0 +1,15 @@ +#include "leetcode.h" + +class Solution { +public: + void reverseString(vector<char> &s) { + int i = 0, j = s.size() - 1; + while (i <= j) { + char tmp = s[i]; + s[i] = s[j]; + s[j] = tmp; + i++; + j--; + } + } +}; diff --git a/reverse_string.py b/reverse_string.py new file mode 100644 index 0000000..be1853d --- /dev/null +++ b/reverse_string.py @@ -0,0 +1,26 @@ +# 344. Reverse String + +""" +write a function that reverses a string. the input string is given as an +array of characters 's'. you must do this by modifying teh input array in +place with 'O(1)' extra memroy +""" + + +class Solution(object): + def reverseString(self, s): + """ + :type s: List[str] + :rtype: None Do not return anything, modify s in-place instead. + """ + s[:] = s[::-1] + + +if __name__ == "__main__": + obj = Solution() + s1 = "hello" + s2 = "Hannah" + obj.reverseString(s1) + obj.reverseString(s2) + print(s1) + print(s2) diff --git a/reverse_string2.cpp b/reverse_string2.cpp new file mode 100644 index 0000000..839a26f --- /dev/null +++ b/reverse_string2.cpp @@ -0,0 +1,34 @@ +#include "leetcode.h" + +class Solution { +public: + string reverseStr(string s, int k) { + int len = s.size(), rem = len % (2 * k); + int start = 0, end = 2 * k, actual = len - rem; + string ans = ""; + while (actual) { + string tmp = s.substr(start, end); + reverse(tmp.begin(), tmp.begin() + k); + start += 2 * k; + ans += tmp; + actual -= 2 * k; + } + if (rem > 0) { + if (rem < k) { + string tmp = s.substr(len - rem, rem); + reverse(tmp.begin(), tmp.end()); + ans += tmp; + } else if (rem <= 2 * k) { + string tmp = s.substr(len - rem, rem); + reverse(tmp.begin(), tmp.begin() + k); + ans += tmp; + } + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.reverseStr("abcdefg", 2); +} diff --git a/reverse_string3.cpp b/reverse_string3.cpp new file mode 100644 index 0000000..0cc2cf5 --- /dev/null +++ b/reverse_string3.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + string reverseWords(string s) { + int i = 0; + for (int j = 0; j < s.size(); ++j) { + if (s[j] == ' ') { + reverse(s.begin() + i, s.begin() + j); + i = j + 1; + } + } + reverse(s.begin() + i, s.end()); + return s; + } +}; + +int main() { + Solution obj; + cout << obj.reverseWords("Let's take LeetCode contest"); +} diff --git a/reverse_subarr_max_arr_val.c b/reverse_subarr_max_arr_val.c new file mode 100644 index 0000000..6f4234d --- /dev/null +++ b/reverse_subarr_max_arr_val.c @@ -0,0 +1,29 @@ +// 1330. Reverse Subarray To Maximize Array Value +#include "leetcode.h" + +/* + * given an intger array 'nums'. the value of this array is defined as the sum + * of '| nums[i] - nums[i + 1] |' for all '0 <= i < nums.len - 1'. you are + * allowed to select any subarray of the given array and reverse it. you can + * perform this operation only once. find maximum possible value of the final + * array. + */ + +int maxValueAfterReverse(int *nums, int numsSize) { + int total = 0, sum = 0, min2 = 123456, max2 = -123456, n = numsSize; + for (int i = 0; i < n - 1; ++i) { + int a = nums[i], b = nums[i + 1]; + total += abs(a - b); + sum = fmax(sum, abs(nums[0] - b) - abs(a - b)); + sum = fmax(sum, abs(nums[n - 1] - a) - abs(a - b)); + min2 = fmin(min2, fmax(a, b)); + max2 = fmax(max2, fmin(a, b)); + } + return total + fmax(sum, (max2 - min2) * 2); +} + +int main() { + int n1[] = {2, 3, 1, 5, 4}, n2[] = {2, 4, 9, 24, 2, 1, 10}; + printf("%d\n", maxValueAfterReverse(n1, ARRAY_SIZE(n1))); // expect: 10 + printf("%d\n", maxValueAfterReverse(n2, ARRAY_SIZE(n2))); // expect: 68 +} diff --git a/reverse_subarr_max_arr_val.py b/reverse_subarr_max_arr_val.py new file mode 100644 index 0000000..f1f1e7e --- /dev/null +++ b/reverse_subarr_max_arr_val.py @@ -0,0 +1,30 @@ +# 1330. Reverse Subarray To Maximize Array Value + +""" +given an intger array 'nums'. the value of this array is defined as the sum +of '| nums[i] - nums[i + 1] |' for all '0 <= i < nums.len - 1'. you are +allowed to select any subarray of the given array and reverse it. you can +perform this operation only once. find maximum possible value of the final +array. +""" + + +class Solution(object): + def maxValueAfterReverse(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + total, sum, min2, max2 = 0, 0, float("inf"), -float("inf") + for a, b in zip(nums, nums[1:]): + total += abs(a - b) + sum = max(sum, abs(nums[0] - b) - abs(a - b)) + sum = max(sum, abs(nums[-1] - a) - abs(a - b)) + min2, max2 = min(min2, max(a, b)), max(max2, min(a, b)) + return total + max(sum, (max2 - min2) * 2) + + +if __name__ == "__main__": + obj = Solution() + print(obj.maxValueAfterReverse(nums=[2, 3, 1, 5, 4])) + print(obj.maxValueAfterReverse(nums=[2, 4, 9, 24, 2, 1, 10])) diff --git a/reverse_vowel_string.cpp b/reverse_vowel_string.cpp new file mode 100644 index 0000000..aa9a039 --- /dev/null +++ b/reverse_vowel_string.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + string reverseVowels(string s) { + int i = 0, j = s.size() - 1; + while (i < j) { + i = s.find_first_of("aeiouAEIOU", i); + j = s.find_last_of("aeiouAEIOU", j); + if (i < j) + swap(s[i++], s[j--]); + } + return s; + } +}; + +int main() { + Solution obj; + cout << obj.reverseVowels("hello"); +} diff --git a/reverse_vowel_string.rs b/reverse_vowel_string.rs new file mode 100644 index 0000000..4ae282d --- /dev/null +++ b/reverse_vowel_string.rs @@ -0,0 +1,33 @@ +struct Solution; + +impl Solution { + pub fn reverse_vowels(s: String) -> String { + let (mut i, mut j) = (0, s.len().checked_sub(1).unwrap_or(0)); + let mut cs = s.chars().collect::<Vec<char>>(); + while i < j { + if !Self::is_vowel(cs[i].to_ascii_lowercase()) { + i += 1; + continue + } + if !Self::is_vowel(cs[j].to_ascii_lowercase()) { + j -= 1; + continue + } + cs.swap(i, j); + i += 1; + j -= 1; + } + cs.iter().collect() + } + fn is_vowel(c: char) -> bool { + match c { + 'a' | 'e' | 'i' | 'o' | 'u' => true, + _ => false + } + } +} + +fn main() { + let s = "hello".to_string(); + print!("{}", Solution::reverse_vowels(s)); +} diff --git a/reverse_word_string.c b/reverse_word_string.c new file mode 100644 index 0000000..1fe60a4 --- /dev/null +++ b/reverse_word_string.c @@ -0,0 +1,35 @@ +// 557. Reverse Words in a String III +#include <stdio.h> +#include <string.h> + +/* + * given a string 's', reverse the order of characters in each word within a + * sentence while still preserving whitespace and initial word order + */ + +void reverse(int b, int e, char *s) { + while (b < e) { + s[b] ^= s[e]; + s[e] ^= s[b]; + s[b] ^= s[e]; + b++; + e--; + } +} + +char *reverseWords(char *s) { + int s_len = strlen(s), idx = 0; + for (int i = 0; i <= s_len; i++) + if (s[i] == ' ' || s[i] == '\0') { + reverse(idx, i - 1, s); + idx = i + 1; + } + return s; +} + +int main() { + char s1[] = {"Let's take Leetcode contest"}; + char s2[] = {"God Ding"}; + printf("%s\n", reverseWords(s1)); // expect: s'teL ekat edoCteeL tsetnoc + printf("%s\n", reverseWords(s2)); // expect: doG gniD +} diff --git a/reverse_word_string.cpp b/reverse_word_string.cpp new file mode 100644 index 0000000..0259e04 --- /dev/null +++ b/reverse_word_string.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + string reverseWords(string s) { + reverse(s.begin(), s.end()); + int l = 0, r = 0, i = 0, n = s.size(); + while (i < n) { + while (i < n && s[i] != ' ') + s[r++] = s[i++]; + if (l < r) { + reverse(s.begin() + l, s.begin() + r); + if (r == n) + break; + s[r++] = ' '; + l = r; + } + ++i; + } + if (r > 0 && s[r - 1] == ' ') + --r; + s.resize(r); + return s; + } +}; + +int main() { + Solution obj; + cout << obj.reverseWords("the sky is blue"); +} diff --git a/reverse_word_string.py b/reverse_word_string.py new file mode 100644 index 0000000..0c57902 --- /dev/null +++ b/reverse_word_string.py @@ -0,0 +1,17 @@ +# 557. Reverse Words in a String III + +""" +given a string 's', reverse the order of characters in each word within a +sentence while still preserving whitespace and initial word order +""" + + +class Solution(object): + def reverseWords(self, s): + return " ".join(map(lambda word: word[::-1], s.split())) + + +if __name__ == "__main__": + obj = Solution() + print(obj.reverseWords("Let's take Leetcode contest")) + print(obj.reverseWords("God Ding")) diff --git a/reverse_word_string.rs b/reverse_word_string.rs new file mode 100644 index 0000000..6acc9a4 --- /dev/null +++ b/reverse_word_string.rs @@ -0,0 +1,31 @@ +struct Solution; + +impl Solution { + pub fn reverse_words(s: String) -> String { + let mut s: Vec<char> = s.trim().chars().rev().collect(); + s.push(' '); + let mut i: usize = 0; + for j in 0..s.len() { + if s[j] == ' ' { + s[i..j].reverse(); + i = j + 1; + } + } + s.pop(); + let mut i = 1; + for j in 1..s.len() { + if s[j] == ' ' && s[j - 1] == ' ' { + continue; + } + s[i] = s[j]; + i += 1; + } + s.truncate(i); + s.into_iter().collect() + } +} + +fn main() { + let s = "the sky is blue".to_string(); + print!("{}", Solution::reverse_words(s)); +} diff --git a/rle_iterator.c b/rle_iterator.c new file mode 100644 index 0000000..27f42ed --- /dev/null +++ b/rle_iterator.c @@ -0,0 +1,74 @@ +// 900. RLE Iterator +#include "leetcode.h" + +/* + * we can use run length encoding to encode a sequence of integers. in a run + * length encoded array of even length encoding, for all even 'i', 'encoding[i]' + * tells us the number of times that the non negative integer value 'encoding[i + * + 1]' is repeated in the sequence. given that a run length encoded array, + * design an iterator that iterates through it. + */ + +typedef struct { + int *val; + int *cnt; + int size; + int curr; +} RLEIterator; + +RLEIterator *rLEIteratorCreate(int *encoding, int encodingSize) { + int size = encodingSize / 2, idx = 0; + int *val = (int *)malloc(size * sizeof(int)); + int *cnt = (int *)malloc(size * sizeof(int)); + for (int i = 0; i < size; i++) { + if (!encoding[2 * i]) + continue; + val[idx] = encoding[2 * i + 1]; + cnt[idx] = encoding[2 * i]; + idx++; + } + val = realloc(val, idx * sizeof(int)); + cnt = realloc(cnt, idx * sizeof(int)); + RLEIterator *res = malloc(sizeof(RLEIterator)); + res->val = val; + res->cnt = cnt; + res->size = idx; + res->curr = 0; + return res; +} + +int rLEIteratorNext(RLEIterator *obj, int n) { + if (obj->curr >= obj->size) + return -1; + int res = -1, items = n, p = obj->curr, *cnt = obj->cnt; + while (items && p < obj->size) { + if (cnt[p] > items) { + cnt[p] -= items; + items = 0; + res = obj->val[p]; + } else { + items -= cnt[p]; + if (!items) + res = obj->val[p]; + cnt[p] = 0; + p++; + } + } + obj->curr = p; + return res; +} + +void rLEIteratorFree(RLEIterator *obj) { + free(obj->val); + free(obj->cnt); + free(obj); +} + +int main() { + int e1[] = {3, 8, 0, 9, 2, 5}; + RLEIterator *obj = rLEIteratorCreate(e1, ARRAY_SIZE(e1)); + printf("%d\n", rLEIteratorNext(obj, 2)); // expect: 8 + printf("%d\n", rLEIteratorNext(obj, 1)); // expect: 8 + printf("%d\n", rLEIteratorNext(obj, 1)); // expect: 5 + printf("%d\n", rLEIteratorNext(obj, 2)); // expect: -1 +} diff --git a/rle_iterator.py b/rle_iterator.py new file mode 100644 index 0000000..c7692e7 --- /dev/null +++ b/rle_iterator.py @@ -0,0 +1,41 @@ +# 900. RLE Iterator + +""" +we can use run length encoding to encode a sequence of integers. in a run +length encoded array of even length encoding, for all even 'i', 'encoding[i]' +tells us the number of times that the non negative integer value 'encoding[i ++ 1]' is repeated in the sequence. given that a run length encoded array, +design an iterator that iterates through it. +""" + + +class RLEIterator(object): + + def __init__(self, encoding): + """ + :type encoding: List[int] + """ + self.vals = encoding + self.i = 0 + + def next(self, n): + """ + :type n: int + :rtype: int + """ + while n > 0 and self.i < len(self.vals): + if n > self.vals[self.i]: + n -= self.vals[self.i] + self.i += 2 + else: + self.vals[self.i] -= n + return self.vals[self.i + 1] + return -1 + + +if __name__ == "__main__": + obj = RLEIterator([3, 8, 0, 9, 2, 5]) + print(obj.next(2)) + print(obj.next(1)) + print(obj.next(1)) + print(obj.next(2)) diff --git a/roman_2_int.cpp b/roman_2_int.cpp new file mode 100644 index 0000000..1389754 --- /dev/null +++ b/roman_2_int.cpp @@ -0,0 +1,43 @@ +#include "leetcode.h" + +class Solution { +public: + int romanToInt(string s) { + int ans = 0, num = 0; + for (int i = s.size() - 1; ~i; i--) { + switch (s[i]) { + case 'I': + num = 1; + break; + case 'V': + num = 5; + break; + case 'X': + num = 10; + break; + case 'L': + num = 50; + break; + case 'C': + num = 100; + break; + case 'D': + num = 500; + break; + case 'M': + num = 1000; + break; + } + if (4 * num < ans) + ans -= num; + else + ans += num; + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.romanToInt("MCMXCIVMCMXCIV"); +} diff --git a/rotate_function.cpp b/rotate_function.cpp new file mode 100644 index 0000000..d764feb --- /dev/null +++ b/rotate_function.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +class Solution { +public: + int maxRotateFunction(vector<int> &nums) { + long sum = 0, fn = 0; + int len = nums.size(); + for (int i = 0; i < len; i++) { + sum += nums[i]; + fn += (i * nums[i]); + } + long l = 1, r, newFn = fn; + while (l < len) { + r = l + len - 1; + long removed = (l - 1) * nums[l - 1]; + long added = r * nums[r % len]; + newFn -= newFn - removed + added - sum; + fn = max(fn, newFn); + l++; + } + return (int)fn; + } +}; + +int main() { + Solution obj; + vector<int> nums = {4, 3, 2, 6}; + cout << obj.maxRotateFunction(nums); +} diff --git a/rotate_image.cpp b/rotate_image.cpp new file mode 100644 index 0000000..10d0638 --- /dev/null +++ b/rotate_image.cpp @@ -0,0 +1,18 @@ +#include "leetcode.h" + +class Solution { +public: + void rotate(vector<vector<int>> &matrix) { + int n = matrix.size(), depth = n / 2; + for (int i = 0; i < depth; i++) { + int len = n - 2 * i - 1, opp = n - 1 - i; + for (int j = 0; j < len; j++) { + int tmp = matrix[i][i + j]; + matrix[i][i + j] = matrix[opp - j][i]; + matrix[opp - j][i] = matrix[opp][opp - j]; + matrix[opp][opp - j] = matrix[i + j][opp]; + matrix[i + j][opp] = tmp; + } + } + } +}; diff --git a/rotate_image.rs b/rotate_image.rs new file mode 100644 index 0000000..376545d --- /dev/null +++ b/rotate_image.rs @@ -0,0 +1,27 @@ +struct Solution; + +impl Solution { + pub fn rotate(mut matrix: Vec<Vec<i32>>) { + let n = matrix.len(); + let depth = n / 2; + for i in 0..depth { + let (len, opp) = (n - 2 * i - 1, n - 1 - i); + for j in 0..len { + let tmp = matrix[i][i + j]; + matrix[i][i + j] = matrix[opp - j][i]; + matrix[opp - j][i] = matrix[opp][opp - j]; + matrix[opp][opp - j] = matrix[i + j][opp]; + matrix[i + j][opp] = tmp; + } + } + } +} + +fn main() { + let matrix = vec![ + vec![1,2,3], + vec![4,5,6], + vec![7,8,9] + ]; + print!("{:?}", Solution::rotate(matrix)); +} diff --git a/running_sum_1d_array.cpp b/running_sum_1d_array.cpp new file mode 100644 index 0000000..b82e0ad --- /dev/null +++ b/running_sum_1d_array.cpp @@ -0,0 +1,18 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> runningSum(vector<int> &nums) { + vector<int> ans; + int count = 0, n = nums.size(); + for (int i = 0; i < n; i++) + count += nums[i], ans.push_back(count); + return ans; + } +}; + +int main() { + vector<int> nums = {1, 2, 3, 4}; + Solution obj; + obj.runningSum(nums); +} diff --git a/russian_doll_envelopes.cpp b/russian_doll_envelopes.cpp new file mode 100644 index 0000000..fce0aa3 --- /dev/null +++ b/russian_doll_envelopes.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" + +class Solution { +public: + int maxEnvelopes(vector<vector<int>> &envelopes) { + int n = envelopes.size(); + sort(envelopes.begin(), envelopes.end(), compare); + vector<int> ans; + for (int i = 0; i < envelopes.size(); i++) { + int candidate = envelopes[i][1]; + int idx = lower_bound(ans.begin(), ans.end(), candidate) - ans.begin(); + if (idx >= ans.size()) + ans.push_back(candidate); + else + ans[idx] = candidate; + } + return ans.size(); + } + +private: + static bool compare(vector<int> &a, vector<int> &b) { + if (a[0] == b[0]) + return a[1] > b[1]; + return a[0] < b[0]; + } +}; + +int main() {} diff --git a/same_tree.c b/same_tree.c new file mode 100644 index 0000000..98320c5 --- /dev/null +++ b/same_tree.c @@ -0,0 +1,23 @@ +// 100. Same Tree +#include "leetcode.h" + +/* + * given the roots of two binary trees 'p' and 'q', write a function to check if + * they are the same or not. two binary trees are considered the same if they + * are structurally identical, and the nodes have the same value. + */ + +struct TreeNode { + int val; + struct TreeNode *left, *right; +}; + +bool isSameTree(struct TreeNode *p, struct TreeNode *q) { + if (!p && !q) + return 1; + else if (!p || !q) + return 0; + return p->val == q->val + ? isSameTree(p->left, q->left) && isSameTree(p->right, q->right) + : 0; +} diff --git a/same_tree.cpp b/same_tree.cpp new file mode 100644 index 0000000..71c2563 --- /dev/null +++ b/same_tree.cpp @@ -0,0 +1,14 @@ +#include "leetcode.h" + +class Solution { +public: + bool isSameTree(TreeNode *p, TreeNode *q) { + if (p == NULL && q == NULL) + return true; + if (p == NULL || q == NULL) + return false; + if (p->val != q->val) + return false; + return isSameTree(p->right, q->right) && isSameTree(p->left, q->left); + } +}; diff --git a/same_tree.py b/same_tree.py new file mode 100644 index 0000000..e42b63a --- /dev/null +++ b/same_tree.py @@ -0,0 +1,31 @@ +# 100. Same Tree + +""" +given the roots of two binary trees 'p' and 'q', write a function to check if +they are the same or not. two binary trees are considered the same if they +are structurally identical, and the nodes have the same value. +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def isSameTree(self, p, q): + """ + :type p: TreeNode + :type q: TreeNode + :rtype: bool + """ + if p is None and q is None: + return True + if p is None or q is None: + return False + if p.val == q.val: + return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right) + return False diff --git a/same_tree.rs b/same_tree.rs new file mode 100644 index 0000000..3d94ffb --- /dev/null +++ b/same_tree.rs @@ -0,0 +1,71 @@ +use std::rc::Rc; +use std::cell::Ref; +use std::cell::RefCell; +use std::collections::VecDeque; +type NodeRef = Option<Rc<RefCell<TreeNode>>>; +#[derive(Debug, PartialEq, Eq)] +pub struct TreeNode { + pub val: i32, + pub left: NodeRef, + pub right: NodeRef +} + +impl TreeNode { + #[inline] + pub fn new(val: i32) -> Self { + TreeNode { + val, + left: None, + right: None + } + } +} + +struct Solution; + +impl Solution { + pub fn is_same_tree(p: NodeRef, q: NodeRef) -> bool { + //p == q + let mut dq: VecDeque<(NodeRef, NodeRef)> = VecDeque::new(); + match (p, q) { + (Some(p), Some(q)) => { + dq.push_back((Some(Rc::clone(&p)), Some(Rc::clone(&q)))); + } + (None, None) => return true, + _ => return false + } + while !dq.is_empty() { + let (p, q) = dq.pop_front().unwrap(); + if !match (&p, &q) { + (Some(p), Some(q)) => p.borrow().val == q.borrow().val, + (None, None) => true, + _ => false + } { + return false; + } + if let (Some(p), Some(q)) = (p, q) { + let (p, q) = ( + Solution::clone_nodes(p.borrow()), + Solution::clone_nodes(q.borrow()) + ); + dq.push_back((p.0, q.0)); + dq.push_back((p.1, q.1)); + } + } + true + } + fn clone_nodes(tree: Ref<TreeNode>) -> (NodeRef, NodeRef) { + ( + if tree.left.is_some() { + Some(Rc::clone(tree.left.as_ref().unwrap())) + } else { + None + }, + if tree.right.is_some() { + Some(Rc::clone(tree.right.as_ref().unwrap())) + } else { + None + } + ) + } +} diff --git a/satisfiability_eqaulity.cpp b/satisfiability_eqaulity.cpp new file mode 100644 index 0000000..b0a1f8b --- /dev/null +++ b/satisfiability_eqaulity.cpp @@ -0,0 +1,33 @@ +#include "leetcode.h" + +class Solution { +public: + bool equationsPossible(vector<string> &equations) { + for (int i = 0; i < 26; ++i) + uf[i] = i; + for (string e : equations) + if (e[1] == '=') + uf[find(e[0] - 'a')] = find(e[3] - 'a'); + for (string e : equations) + if (e[1] == '!' && find(e[0] - 'a') == find(e[3] - 'a')) + return false; + return true; + } + +private: + int uf[26]; + int find(int x) { + if (x != uf[x]) + uf[x] = find(uf[x]); + return uf[x]; + } +}; + +int main() { + Solution obj; + vector<string> equations = {"a==b", "b!=a"}; + if (obj.equationsPossible(equations)) + cout << "true"; + else + cout << "false"; +} diff --git a/score_after_flipping_matrix.c b/score_after_flipping_matrix.c new file mode 100644 index 0000000..bde1b04 --- /dev/null +++ b/score_after_flipping_matrix.c @@ -0,0 +1,49 @@ +// 861. Score After Flipping Matrix +#include "leetcode.h" + +/* + * given an 'm * n' binary matrix 'grid'. a move consists of choosing any row or + * column and toggling each value in thatrow or column. every row of the matrix + * is interpreted as a binary number, and the score of the matrix is the sum of + * these numbers. return the highest possible score after making any number of + * moves, including zero. + */ + +int matrixScore(int **grid, int gridSize, int *gridColSize) { + int m = gridSize, n = *gridColSize; + // flip rows to obtain msb = 1 + for (int i = 0; i < m; ++i) { + if (grid[i][0]) + continue; + for (int j = 0; j < n; ++j) + grid[i][j] = !grid[i][j]; + } + // flip columns + for (int i = 0; i < n; ++i) { + int zeros = 0, ones = 0; + for (int j = 0; j < m; ++j) { + if (!grid[j][i]) + ++zeros; + else + ++ones; + } + if (ones >= zeros) + continue; + for (int j = 0; j < m; ++j) + grid[j][i] = !grid[j][i]; + } + int ans = 0; + // form binary string and convert to integer + char *bin_str = (char *)malloc((n + 1) * sizeof(char)); + for (int i = 0; i < m; i++) { + int k = 0; + for (int j = 0; j < n; ++j) { + bin_str[k] = grid[i][j] + '0'; + ++k; + } + k = 0; + ans += strtol(bin_str, NULL, 2); + } + free(bin_str); + return ans; +} diff --git a/score_after_flipping_matrix.py b/score_after_flipping_matrix.py new file mode 100644 index 0000000..7f80f58 --- /dev/null +++ b/score_after_flipping_matrix.py @@ -0,0 +1,29 @@ +# 861. Score After Flipping Matrix + +""" +given an 'm n' binary matrix 'grid'. a move consists of choosing any row or +column and toggling each value in thatrow or column. every row of the matrix +is interpreted as a binary number, and the score of the matrix is the sum of +these numbers. return the highest possible score after making any number of +moves, including zero. +""" + + +class Solution(object): + def matrixScore(self, grid): + """ + :type grid: List[List[int]] + :rtype: int + """ + m, n = len(grid), len(grid[0]) + ans = (1 << n - 1) * m + for i in range(1, n): + curr = sum(grid[j][i] == grid[j][0] for j in range(m)) + ans += max(curr, m - curr) * (1 << n - 1 - i) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.matrixScore(grid=[[0, 0, 1, 1], [1, 0, 1, 0], [1, 1, 0, 0]])) + print(obj.matrixScore(grid=[[0]])) diff --git a/score_of_string.c b/score_of_string.c new file mode 100644 index 0000000..c415f9e --- /dev/null +++ b/score_of_string.c @@ -0,0 +1,26 @@ +// 3110. Score of a String +#include "leetcode.h" + +/* + * you are given a string 's'. the score of a string is defined as the sume of + * the absolute different between the ascii values of adjacent characters. + * return the score of 's'. + */ + +int scoreOfString(char *s) { + int ans = 0, val = 0, n = strlen(s); + while (--n) { + val = *s - *(s + 1); + if (val < 0) + val = -val; + ans += val; + s++; + } + return ans; +} + +int main() { + char *s1 = "hello", *s2 = "zaz"; + printf("%d\n", scoreOfString(s1)); // expect: 13 + printf("%d\n", scoreOfString(s2)); // expect: 50 +} diff --git a/score_of_string.py b/score_of_string.py new file mode 100644 index 0000000..5de786e --- /dev/null +++ b/score_of_string.py @@ -0,0 +1,22 @@ +# 3110. Score of a String + +""" +you are given a string 's'. the score of a string is defined as the sume of +the absolute different between the ascii values of adjacent characters. +return the score of 's'. +""" + + +class Solution(object): + def scoreOfString(self, s): + """ + :type s: str + :rtype: int + """ + return sum(abs(ord(s[i]) - ord(s[i + 1])) for i in range(len(s) - 1)) + + +if __name__ == "__main__": + obj = Solution() + print(obj.scoreOfString("hello")) + print(obj.scoreOfString("zaz")) diff --git a/scramble_string.c b/scramble_string.c new file mode 100644 index 0000000..e031211 --- /dev/null +++ b/scramble_string.c @@ -0,0 +1,45 @@ +// 87. Scramble String +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * string 's' can be scrambled to get string 't' using the following algorithm: + * if length of string is 1, exit + * if lenght of string is > 1: + * split string into two non-empty substrings at random index + * randomly decide to swap two substrings or to keep them in same order + * apply step 1 recursively + * given two strings 's1' and 's2' of the same length, return true if 's2' is a + * scrambled string of 's1', otherwise return false + */ + +bool prune(char *s1, char *s2, int len) { + int cnt[256] = {0}; + for (int i = 0; i < len; i++) { + cnt[s1[i] - 'a']++; + cnt[s2[i] - 'a']--; + } + for (int i = 1; i < len; i++) + if (prune(s1, s2, i) && prune(s1 + i, s2 + i, len - i) || + prune(s1, s2 + len - i, i) && prune(s1 + i, s2, len - i)) + return true; + return false; +} + +bool isScramble(char *s1, char *s2) { + int len = strlen(s1); + if (!strncmp(s1, s2, len)) + return false; + return prune(s1, s2, len); +} + +int main() { + char s1_1[] = {"great"}, s2_1[] = {"rgeat"}; + char s1_2[] = {"abcde"}, s2_2[] = {"caebd"}; + char s1_3[] = {"a"}, s2_3[] = {"a"}; + printf("%d\n", isScramble(s1_1, s2_1)); // expect: 1 + printf("%d\n", isScramble(s1_2, s2_2)); // expect: 0 + printf("%d\n", isScramble(s1_3, s2_3)); // expect: 1 +} diff --git a/scramble_string.cpp b/scramble_string.cpp new file mode 100644 index 0000000..da6b92d --- /dev/null +++ b/scramble_string.cpp @@ -0,0 +1,55 @@ +// 87. Scramble String +#include "leetcode.h" + +/* + * string 's' can be scrambled to get string 't' using the following algorithm: + * if length of string is 1, exit + * if lenght of string is > 1: + * split string into two non-empty substrings at random index + * randomly decide to swap two substrings or to keep them in same order + * apply step 1 recursively + * given two strings 's1' and 's2' of the same length, return true if 's2' is a + * scrambled string of 's1', otherwise return false + */ + +class Solution { +public: + bool isScramble(string s1, string s2) { + if (s1.size() != s2.size()) + return false; + return is_scrambled(s1, s2); + } + +private: + unordered_map<string, bool> um; + bool is_scrambled(string s1, string s2) { + int n = s1.size(); + if (s1 == s2 || n == 0) + return true; + string key = s1 + ' ' + s2; + if (um.find(key) != um.end()) + return um[key]; + bool flag = false; + for (int i = 1; i < n; i++) { + if (is_scrambled(s1.substr(0, i), s2.substr(n - i, i)) && + is_scrambled(s1.substr(i, n - i), s2.substr(0, n - i))) { + flag |= true; + break; + } + if (is_scrambled(s1.substr(0, i), s2.substr(0, i)) && + is_scrambled(s1.substr(i, n - i), s2.substr(i, n - i))) { + flag |= true; + break; + } + } + um[key] = flag; + return flag; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.isScramble("great", "rgeat")); // expect: 1 + printf("%d\n", obj.isScramble("abcde", "caebd")); // expect: 0 + printf("%d\n", obj.isScramble("a", "a")); // expect: 1 +} diff --git a/search_2d_matrix.c b/search_2d_matrix.c new file mode 100644 index 0000000..7e8e7fe --- /dev/null +++ b/search_2d_matrix.c @@ -0,0 +1,35 @@ +// 74. Search a 2D Matrix +#include <stdbool.h> +#include <stdio.h> + +/* + * given an 'm x n' integer matrix 'matrxi' with the following two properties: + * - each row is sorted in non-decreasing order. + * - the first integer of each row is greater than the last integer of the + * previous row. given an integer 'target', return true if 'target' is in + * 'matrix', or false otherwise. you must write a solution in 'O(log(m * n))' + * time complexity + */ + +bool searchMatrix(int **matrix, int matrix_size, int *matrix_col_size, + int target) { + int i = 0, j = *matrix_col_size * matrix_size - 1; + while (i <= j) { + int mid = (i + j) / 2; + int row = mid / *matrix_col_size; + int col = mid % *matrix_col_size; + if (matrix[row][col] < target) + i = mid + 1; + else if (matrix[row][col] > target) + j = mid - 1; + else + return true; + } + return false; +} + +int main() { + int matrix[3][4] = {{1, 3, 5, 7}, {10, 11, 16, 20}, {23, 30, 34, 60}}; + printf("%d\n", searchMatrix(matrix, 4, NULL, 3)); // expect: 1 + printf("%d\n", searchMatrix(matrix, 4, NULL, 13)); // expect: 0 +} diff --git a/search_2d_matrix.cpp b/search_2d_matrix.cpp new file mode 100644 index 0000000..44c42d4 --- /dev/null +++ b/search_2d_matrix.cpp @@ -0,0 +1,35 @@ +// 74. Search a 2D Matrix +#include "leetcode.h" + +/* + * given an 'm x n' integer matrix 'matrxi' with the following two properties: + * - each row is sorted in non-decreasing order. + * - the first integer of each row is greater than the last integer of the + * previous row. given an integer 'target', return true if 'target' is in + * 'matrix', or false otherwise. you must write a solution in 'O(log(m * n))' + * time complexity + */ + +class Solution { +public: + bool searchMatrix(vvd(int) & matrix, int target) { + int rows = matrix.size(), cols = matrix[0].size(), row = 0, col = cols - 1; + while (row < rows && col > -1) { + int curr = matrix[row][col]; + if (curr == target) + return true; + if (target > curr) + row++; + else + col--; + } + return false; + } +}; + +int main() { + Solution obj; + vvd(int) matrix = {{1, 3, 5, 7}, {10, 11, 16, 20}, {23, 30, 34, 60}}; + printf("%d\n", obj.searchMatrix(matrix, 3)); // expect: 1 + printf("%d\n", obj.searchMatrix(matrix, 13)); // expect: 0 +} diff --git a/search_2d_matrix2.cpp b/search_2d_matrix2.cpp new file mode 100644 index 0000000..9834431 --- /dev/null +++ b/search_2d_matrix2.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + bool searchMatrix(vector<vector<int>> &matrix, int target) { + int m = matrix.size(), n = matrix[0].size(); + if (m == 0) + return false; + int i = 0, j = n - 1; + while (i < m && j >= 0) { + if (matrix[i][j] == target) + return true; + else if (matrix[i][j] > target) + j--; + else + i++; + } + return false; + } +}; diff --git a/search_BST.cpp b/search_BST.cpp new file mode 100644 index 0000000..9d06727 --- /dev/null +++ b/search_BST.cpp @@ -0,0 +1,16 @@ +#include "leetcode.h" + +class Solution { +public: + TreeNode *searchBST(TreeNode *root, int val) { + if (root == NULL) + return NULL; + if (root->val == val) + return root; + if (root->val > val) + return searchBST(root->left, val); + return searchBST(root->right, val); + } +}; + +int main() {} diff --git a/search_insert_pos.c b/search_insert_pos.c new file mode 100644 index 0000000..cbbdcd9 --- /dev/null +++ b/search_insert_pos.c @@ -0,0 +1,28 @@ +// 35. Search Insert Position +#include <stdio.h> +#include <stdlib.h> + +/* + * given a sorted array of distinct intergers and a target value, return the + * index if the target is found. if not, return the index where it would be if + * it were inserted in order. must be o(ln) compexity + */ + +int searchInsert(int *nums, int numsSize, int target) { + int left = 0, right = numsSize, mid; + while (left < right) { + mid = left + (right - left) / 2; + if (nums[mid] >= target) + right = mid; + else + left = mid + 1; + } + return left; +} + +int main() { + int nums[] = {1, 3, 5, 6}, ns = 4; + printf("%d\n", searchInsert(nums, ns, 5)); // expect: 2 + printf("%d\n", searchInsert(nums, ns, 2)); // expect: 1 + printf("%d\n", searchInsert(nums, ns, 7)); // expect: 4 +} diff --git a/search_insert_pos.cpp b/search_insert_pos.cpp new file mode 100644 index 0000000..f6768a5 --- /dev/null +++ b/search_insert_pos.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + int searchInsert(vector<int> &nums, int target) { + int low = 0, high = nums.size() - 1; + while (low <= high) { + int mid = low + (high - low) / 2; + if (nums[mid] == target) + return mid; + else if (nums[mid] > target) + high = mid - 1; + else + low = mid + 1; + } + return low; + } +}; + +int main() {} diff --git a/search_rotated_array.c b/search_rotated_array.c new file mode 100644 index 0000000..bdd3304 --- /dev/null +++ b/search_rotated_array.c @@ -0,0 +1,43 @@ +// 33. Search in Rotated Sorted Array +#include <stdio.h> +#include <stdlib.h> + +/* + * there is an integer array 'nums' sorted in ascending order (with distinct + * values). prior to being passed to your function, 'nums' is possibly rotated + * at an unknown pivot index 'k(1 <= k < nums.length)' such tht the resulting + * array is '[nums[k], nums[k + 1], ..., nums[n - 1], nums[0], nums[1], ..., + * nums[k - 1]]' (0-indxed). for example, '[0,1,2,4,5,6,7]' might be rotated at + * pivot index 3 and become '[4,5,6,7,0,1,2]'. given the array 'nums' after the + * possible rotation and an integer 'target', return the index of 'target' if it + * is in 'nums', or -1 otherwise. you must write an algorithm with 'O(log n)' + * runtime complexity + */ + +int search(int *nums, int nums_size, int target) { + int left, right; + for (left = 0, right = nums_size - 1; left <= right;) { + int mid = (left + right) / 2; + if (nums[mid] == target) + return mid; + if (nums[left] <= nums[mid]) { + if (nums[left] <= target && target < nums[mid]) + right = mid - 1; + else + left = mid + 1; + } else { + if (nums[mid] < target && target <= nums[right]) + left = mid + 1; + else + right = mid - 1; + } + } + return -1; +} + +int main() { + int n1[] = {4, 5, 6, 7, 0, 1, 2}, n2[] = {4, 5, 6, 7, 0, 1, 2}, n3[] = {1}; + printf("%d\n", search(n1, 7, 0)); // expect: 4 + printf("%d\n", search(n2, 7, 3)); // expect: -1 + printf("%d\n", search(n3, 1, 0)); // expect: -1 +} diff --git a/search_rotated_array.cpp b/search_rotated_array.cpp new file mode 100644 index 0000000..7001f32 --- /dev/null +++ b/search_rotated_array.cpp @@ -0,0 +1,37 @@ +// 33. Search in Rotated Sorted Array +#include "leetcode.h" + +/* + * there is an integer array 'nums' sorted in ascending order (with distinct + * values). prior to being passed to your function, 'nums' is possibly rotated + * at an unknown pivot index 'k(1 <= k < nums.length)' such tht the resulting + * array is '[nums[k], nums[k + 1], ..., nums[n - 1], nums[0], nums[1], ..., + * nums[k - 1]]' (0-indxed). for example, '[0,1,2,4,5,6,7]' might be rotated at + * pivot index 3 and become '[4,5,6,7,0,1,2]'. given the array 'nums' after the + * possible rotation and an integer 'target', return the index of 'target' if it + * is in 'nums', or -1 otherwise. you must write an algorithm with 'O(log n)' + * runtime complexity + */ + +class Solution { +public: + int search(vector<int> &nums, int target) { + int left = 0, right = nums.size() - 1; + while (left < right) { + int mid = (left + right) / 2; + if ((nums[0] > target) ^ (nums[0] > nums[mid]) ^ (target > nums[mid])) + left = mid + 1; + else + right = mid; + } + return left == right && nums[left] == target ? left : -1; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {4, 5, 6, 7, 0, 1, 2}, n2 = {4, 5, 6, 7, 0, 1, 2}, n3 = {1}; + printf("%d\n", obj.search(n1, 0)); // expect: 4 + printf("%d\n", obj.search(n2, 3)); // expect: -1 + printf("%d\n", obj.search(n3, 0)); // expect: -1 +} diff --git a/search_rotated_array2.c b/search_rotated_array2.c new file mode 100644 index 0000000..cf38e3a --- /dev/null +++ b/search_rotated_array2.c @@ -0,0 +1,56 @@ +// 81. Search in Rotated Sorted Array II +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * there is an integer array 'nums' sorted in non-decreasing order (not + * necessarily with distinct values). before being passed to your function, + * 'nums' is rotated at an unknown pivot index 'k(0 <= k < nums.length)' such + * that the resulting array is '[nums[k], nums[k + 1], ..., nums[n - 1], + * nums[0], nums[1], ..., nums[k - 1]]' (0-indexed). for example + * '[0,1,2,4,4,4,5,6,6,7]' might be rotated at a pivot index 5 and become + * '[4,5,6,6,7,0,1,2,4,4]'. given the array 'nums' after the rotation and an + * integer 'target', return true if 'target' is in 'nums' of 'false' if it is + * not in 'nums'. you must decrease the overall operation steps as much as + * possible. + */ + +int find_min(int *nums, int nums_size) { + int min_idx = 0; + for (int i = 0; i + 1 < nums_size; i++) + if (nums[i + 1] < nums[i]) { + min_idx = i + 1; + break; + } + return min_idx; +} + +bool search(int *nums, int nums_size, int target) { + if (nums_size == 1) + return nums[0] == target ? 1 : 0; + int start = find_min(nums, nums_size), end = start + nums_size; + int arr_size = 2 * nums_size; + int *arr = (int *)malloc(arr_size * sizeof(int)); + for (int i = 0; i < arr_size; i++) + arr[i] = nums[i % nums_size]; + bool is_find = false; + while (start < end) { + int mid = start + (end - start) / 2; + if (target == arr[mid]) { + is_find = true; + break; + } else if (target < arr[mid]) + end = mid; + else + start = mid + 1; + } + free(arr); + return is_find; +} + +int main() { + int nums[] = {2, 5, 6, 0, 0, 1, 2}, nums_size = 7; + printf("%d\n", search(nums, nums_size, 0)); // expect: 1 + printf("%d\n", search(nums, nums_size, 3)); // expect: 0 +} diff --git a/search_rotated_array2.cpp b/search_rotated_array2.cpp new file mode 100644 index 0000000..0054f04 --- /dev/null +++ b/search_rotated_array2.cpp @@ -0,0 +1,48 @@ +// 81. Search in Rotated Sorted Array II +#include "leetcode.h" + +/* + * there is an integer array 'nums' sorted in non-decreasing order (not + * necessarily with distinct values). before being passed to your function, + * 'nums' is rotated at an unknown pivot index 'k(0 <= k < nums.length)' such + * that the resulting array is '[nums[k], nums[k + 1], ..., nums[n - 1], + * nums[0], nums[1], ..., nums[k - 1]]' (0-indexed). for example + * '[0,1,2,4,4,4,5,6,6,7]' might be rotated at a pivot index 5 and become + * '[4,5,6,6,7,0,1,2,4,4]'. given the array 'nums' after the rotation and an + * integer 'target', return true if 'target' is in 'nums' of 'false' if it is + * not in 'nums'. you must decrease the overall operation steps as much as + * possible. + */ + +class Solution { +public: + bool search(vector<int> &nums, int target) { + int left = 0, right = nums.size() - 1; + while (left <= right) { + int mid = left + (right - left) / 2; + if (nums[mid] == target) + return true; + if (nums[left] == nums[mid] && nums[right] == nums[mid]) + left++, right--; + else if (nums[left] <= nums[mid]) { + if (nums[left] <= target && nums[mid] > target) + right = mid - 1; + else + left = mid + 1; + } else { + if (nums[mid] < target && nums[right] >= target) + left = mid + 1; + else + right = mid - 1; + } + } + return false; + } +}; + +int main() { + Solution obj; + vector<int> nums = {2, 5, 6, 0, 0, 1, 2}; + printf("%d\n", obj.search(nums, 0)); // expect: 1 + printf("%d\n", obj.search(nums, 3)); // expect: 0 +} diff --git a/search_suggestion_sys.cpp b/search_suggestion_sys.cpp new file mode 100644 index 0000000..404c987 --- /dev/null +++ b/search_suggestion_sys.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" +#include <vector> + +class Solution { +public: + vector<vector<string>> suggestedProducts(vector<string> &products, + string searchWord) { + auto it = products.begin(); + sort(it, products.end()); + vector<vector<string>> ans; + string curr = ""; + for (char c : searchWord) { + curr += c; + vector<string> suggested; + it = lower_bound(it, products.end(), curr); + for (int i = 0; i < 3 && it + i != products.end(); i++) { + string &s = *(it + i); + if (s.find(curr)) + break; + suggested.push_back(s); + } + ans.push_back(suggested); + } + return ans; + } +}; diff --git a/seat_reservation_manager.c b/seat_reservation_manager.c new file mode 100644 index 0000000..bd1c874 --- /dev/null +++ b/seat_reservation_manager.c @@ -0,0 +1,66 @@ +// 1845. Seat Reservation Manager +#include "leetcode.h" + +/* + * design a system that manages the reservation state of 'n' seats that are + * numbered 1 to 'n'. implement the 'SeatManager' class + * - seatManagerCreate(int n) initalises a SeatManager object that will manage + * 'n' seats numbered from 1 to 'n'. all seats are initially available + * - seatManagerReserve() fetches the smallest-numbered unreserved seat, + * reserves it, and returns its number + * - seatManagerUnreserve(int seat_num) unreserves the seat with the given + * 'seat_num' + */ + +typedef struct { + int *un_array; + int un_size; + int curr; +} SeatManager; + +SeatManager *seatManagerCreate(int n) { + SeatManager *res = malloc(sizeof(SeatManager)); + res->un_size = 0; + res->curr = 0; + res->un_array = (int *)malloc(n * sizeof(int)); + return res; +} + +int seatManagerReserve(SeatManager *obj) { + if (!obj->un_size) { + obj->curr++; + return obj->curr; + } else { + int min = obj->un_array[0], min_id = 0; + for (int i = 1; i < obj->un_size; i++) + if (obj->un_array[i] < min) { + min = obj->un_array[i]; + min_id = i; + } + int tmp = obj->un_array[min_id]; + obj->un_array[min_id] = obj->un_array[obj->un_size - 1]; + return tmp; + } +} + +void seatManagerUnreserve(SeatManager *obj, int seat_num) { + obj->un_size++; + obj->un_array[obj->un_size - 1] = seat_num; +} + +void seatManagerFree(SeatManager *obj) { + free(obj->un_array); + free(obj); +} + +int main() { + SeatManager *obj = seatManagerCreate(5); + printf("%d\n", seatManagerReserve(obj)); // expect: 1 + printf("%d\n", seatManagerReserve(obj)); // expect: 2 + seatManagerUnreserve(obj, 2); + printf("%d\n", seatManagerReserve(obj)); // expect: 2 + printf("%d\n", seatManagerReserve(obj)); // expect: 3 + printf("%d\n", seatManagerReserve(obj)); // expect: 4 + printf("%d\n", seatManagerReserve(obj)); // expect: 5 + seatManagerUnreserve(obj, 5); +} diff --git a/seat_reservation_manager.py b/seat_reservation_manager.py new file mode 100644 index 0000000..41f3b0f --- /dev/null +++ b/seat_reservation_manager.py @@ -0,0 +1,25 @@ +# 1845. Seat Reservation Manager + +""" +design a system that manages the reservation state of 'n' seats that are +numbered 1 to 'n'. implement the 'SeatManager' class +- seatManagerCreate(int n) initalises a SeatManager object that will manage +'n' seats numbered from 1 to 'n'. all seats are initially available +- seatManagerReserve() fetches the smallest-numbered unreserved seat, +reserves it, and returns its number +- seatManagerUnreserve(int seat_num) unreserves the seat with the given +'seat_num' +""" + +import heapq + + +class SeatManager(object): + def __init__(self, n): + self.heap = list(range(1, n + 1)) + + def reserve(self): + return heapq.heappop(self.heap) + + def unreserve(self, seatNumber): + heapq.heappush(self.heap, seatNumber) diff --git a/sender_largest_word_cnt.c b/sender_largest_word_cnt.c new file mode 100644 index 0000000..7635b63 --- /dev/null +++ b/sender_largest_word_cnt.c @@ -0,0 +1,145 @@ +// 2284. Sender With Largest Word Count +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * you have a chat log of 'n' messages. you are given two string arrays + * 'messages' and 'senders' where 'messages[i]' is a message sent by + * 'senders[i]'. a message is a list of words that are separated by a single + * space with no leading or trailing spaces. the word count of a sender is the + * total number of words sent by the sender. note that a sender may send more + * than one message. return the sender with the largest word count. if there is + * more than one sender with the largest word count, return the one with the + * lexicographically largest name + */ + +typedef struct { + uint val; + char *str; + int cnt; +} dict; + +uint rs_hash(char *str) { + uint a = 63689, b = 378551, hash = 0; + while (*str) { + hash = hash * a + (*str++); + a *= b; + } + return (hash & 0x7FFFFFFF); +} + +int cmp(const void *a, const void *b) { + dict aa = **(dict **)a; + dict bb = **(dict **)b; + if (aa.cnt == bb.cnt) + return strcmp(aa.str, bb.str); + return aa.cnt - bb.cnt; +} + +char *largestWordCount(char **messages, int messages_size, char **senders, + int senders_size) { + int n = senders_size, *words = calloc(n, sizeof(int)); + for (int i = 0; i < n; i++) { + int len = strlen(messages[i]); + if (!len) { + words[i] = 0; + continue; + } + words[i] = 1; + for (int j = 0; j < len; j++) + if (messages[i][j] == ' ') + words[i]++; + dict **hash = malloc(n * sizeof(dict *)); + for (int i = 0; i < n; i++) { + hash[i] = malloc(sizeof(dict)); + hash[i]->cnt = 0; + } + int max = 0, pos = 0; + dict **max_data = malloc(n * sizeof(dict *)); + for (int i = 0; i < n; i++) { + uint h = rs_hash(senders[i]); + if (!hash[h % n]->cnt) { + hash[h % n]->cnt = words[i]; + int len = strlen(senders[i]); + hash[h % n]->str = malloc((len + 1) * sizeof(char)); + strcpy(hash[h % n]->str, senders[i]); + hash[h % n]->val = h; + if (hash[h % n]->cnt == max) { + max_data[pos] = hash[h % n]; + pos++; + } + if (hash[h % n]->cnt > max) { + pos = 0; + max = hash[h % n]->cnt; + max_data[pos] = hash[h % n]; + pos++; + } + } else if (hash[h % n]->val == h) { + hash[h % n]->cnt += words[i]; + if (hash[h % n]->cnt == max) { + max_data[pos] = hash[h % n]; + pos++; + } + if (hash[h % n]->cnt > max) { + pos = 0; + max = hash[h % n]->cnt; + max_data[pos] = hash[h % n]; + pos++; + } + } else { + int k = (h + 1) % n; + bool done = false; + while (hash[k]->cnt) { + if (hash[k]->val == h) { + hash[k]->cnt += words[i]; + if (hash[k]->cnt == max) { + max_data[pos] = hash[k]; + pos++; + } + if (hash[k]->cnt > max) { + pos = 0; + max = hash[k]->cnt; + max_data[pos] = hash[k]; + pos++; + } + done = true; + break; + } + k = (k + 1) % n; + } + if (!done) { + hash[k]->val = h; + hash[k]->cnt = words[i]; + int len = strlen(senders[i]); + hash[k]->str = malloc((len + 1) * sizeof(char)); + strcpy(hash[k]->str, senders[i]); + if (hash[k]->cnt == max) { + max_data[pos] = hash[k]; + pos++; + } + if (hash[k]->cnt > max) { + pos = 0; + max = hash[k]->cnt; + max_data[pos] = hash[k]; + pos++; + } + } + } + } + qsort(max_data, pos, sizeof(dict *), cmp); + return max_data[pos - 1]->str; + } +} + +int main() { + char m1[4][19] = {"Hello userTwooo", "Hi userThree", "Wonderful day Alice", + "Nice day userThree"}; + char s1[4][9] = {"Alice", "userTwo", "userThree", "Alice"}; + char m2[2][31] = {"How is leetcode for everyone", + "Leetcode is useful for practice"}; + char s2[2][7] = {"Bob", "Charlie"}; + printf("%s\n", largestWordCount(m1, 4, s1, 4)); // expect: Alice + printf("%s\n", largestWordCount(m2, 2, s2, 2)); // expect: Charlie +} diff --git a/sender_largest_word_cnt.py b/sender_largest_word_cnt.py new file mode 100644 index 0000000..6e7f993 --- /dev/null +++ b/sender_largest_word_cnt.py @@ -0,0 +1,46 @@ +# 2284. Sender With Largest Word Count +from collections import defaultdict + +""" +you have a chat log of 'n' messages. you are given two string arrays +'messages' and 'senders' where 'messages[i]' is a message sent by +'senders[i]'. a message is a list of words that are separated by a single +space with no leading or trailing spaces. the word count of a sender is the +total number of words sent by the sender. note that a sender may send more +than one message. return the sender with the largest word count. if there is +more than one sender with the largest word count, return the one with the +lexicographically largest name +""" + + +class Solution(object): + def largestWordCount(self, messages, senders): + word_cnt = defaultdict(int) + for m, person in zip(messages, senders): + word_cnt[person] += len(m.split()) + max_len = max(word_cnt.values()) + names = sorted( + [name for name, words in word_cnt.items() if words == max_len], reverse=True + ) + return names[0] + + +if __name__ == "__main__": + obj = Solution() + print( + obj.largestWordCount( + [ + "Hello userTwooo", + "Hi userThree", + "Wonderful day Alice", + "Nice day userThree", + ], + ["Alice", "userTwo", "userThree", "Alice"], + ) + ) # expect: Alice + print( + obj.largestWordCount( + ["How is leetcode for everyone", "Leetcode is useful for practice"], + ["Bob", "Charlie"], + ) + ) # expect: Charlie diff --git a/sentence_similartiy3.c b/sentence_similartiy3.c new file mode 100644 index 0000000..5a78d37 --- /dev/null +++ b/sentence_similartiy3.c @@ -0,0 +1,62 @@ +// 1813. Sentence Similarity III +#include "leetcode.h" + +/* + * a sentence is a list of words that are separated by a single space with no + * leading or trailing spaces. for example, "hello world", "hello", and + * "hellohello world world" are all sentences. words consist of only uppercase + * and lowercase english letters. two sentences 's1' and 's2' are similar if it + * is possible to insert an arbitrary sentence possibly empty inside one of + * these sentences such that the two sentences become equal. given two sentences + * 's1' and 's2', return true if 's1' and 's2' are similar, otherwise return + * false. + */ + +bool cmp_str(char *s1, char *s2) { + int i, n1 = strlen(s1), n2 = strlen(s2); + for (i = 0; i < n1; i++) + if (s1[i] != s2[i]) + break; + if (i == n1 && s2[i] == ' ') + return true; + i--; + while (i >= 0 && s2[i] != ' ') + i--; + i = fmax(0, i); + int d = 1; + for (int j = n1 - 1; j >= i; j--) { + if (s1[j] != s2[n2 - d]) + return false; + if (j == i) { + if (!i) { + if (s2[n2 - d - 1] != ' ') + return false; + } else { + if (s2[n2 - d] != ' ') + return false; + } + } + d++; + } + return true; +} + +bool areSentencesSimilar(char *s1, char *s2) { + int n1 = strlen(s1), n2 = strlen(s2); + if (n1 == n2) { + for (int i = 0; i < n1; i++) + if (s1[i] != s2[i]) + return false; + return true; + } + return n1 < n2 ? cmp_str(s1, s2) : cmp_str(s2, s1); +} + +int main() { + char *s11 = "My name is Haley", *s21 = "My Haley"; + char *s12 = "of", *s22 = "A lot of words"; + char *s13 = "Eating right now", *s23 = "Eating"; + printf("%d\n", areSentencesSimilar(s11, s21)); // expect: 1 + printf("%d\n", areSentencesSimilar(s12, s22)); // expect: 0 + printf("%d\n", areSentencesSimilar(s13, s23)); // expect: 1 +} diff --git a/sentence_similartiy3.py b/sentence_similartiy3.py new file mode 100644 index 0000000..11d5c4d --- /dev/null +++ b/sentence_similartiy3.py @@ -0,0 +1,42 @@ +# 1813. Sentence Similarity III + +""" +a sentence is a list of words that are separated by a single space with no +leading or trailing spaces. for example, "hello world", "hello", and +"hellohello world world" are all sentences. words consist of only uppercase +and lowercase english letters. two sentences 's1' and 's2' are similar if it +is possible to insert an arbitrary sentence possibly empty inside one of +these sentences such that the two sentences become equal. given two sentences +'s1' and 's2', return true if 's1' and 's2' are similar, otherwise return +false. +""" + + +class Solution(object): + def areSentencesSimilar(self, sentence1, sentence2): + """ + :type sentence1: str + :type sentence2: str + :rtype: bool + """ + s1 = sentence1.split() + s2 = sentence2.split() + if len(s1) > len(s2): + s1, s2 = s2, s1 + while s1: + if s2[0] == s1[0]: + s2.pop(0) + s1.pop(0) + elif s2[-1] == s1[-1]: + s2.pop() + s1.pop() + else: + return False + return True + + +if __name__ == "__main__": + obj = Solution() + print(obj.areSentencesSimilar(sentence1="My name is Haley", sentence2="My Haley")) + print(obj.areSentencesSimilar(sentence1="of", sentence2="A lot of words")) + print(obj.areSentencesSimilar(sentence1="Eating right now", sentence2="Eating")) diff --git a/sequential_digits.c b/sequential_digits.c new file mode 100644 index 0000000..ae97e44 --- /dev/null +++ b/sequential_digits.c @@ -0,0 +1,43 @@ +// 1291. Sequential Digits +#include "leetcode.h" + +/* + * an integer has sequential digits if and only if each digit in the number is + * one more than the previous digit. return a sorted list of all the integers in + * the range '[low, high]' inclusive that have sequential digits. + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int *sequentialDigits(int low, int high, int *return_size) { + int *ans = NULL; + *return_size = 0; + for (int i = 1; i <= 9; i++) { + int num = i; + for (int j = i + 1; j <= 9; j++) { + num *= 10 + j; + if (low <= num && num <= high) { + (*return_size)++; + ans = realloc(ans, sizeof(int) * (*return_size)); + ans[(*return_size) - 1] = num; + } + } + } + if (!ans) + return NULL; + qsort(ans, *return_size, sizeof(int), cmp); + return ans; +} + +int main() { + int rs1[] = {}, rs2[] = {}; + int *sd1 = sequentialDigits(100, 300, rs1); + int *sd2 = sequentialDigits(1000, 13000, rs2); + for (int i = 0; i < 2; i++) + printf("%d ", sd1[i]); + printf("\n"); + for (int i = 0; i < 7; i++) + printf("%d ", sd2[i]); + printf("\n"); + free(sd1), free(sd2); +} diff --git a/sequential_digits.py b/sequential_digits.py new file mode 100644 index 0000000..f84dfcc --- /dev/null +++ b/sequential_digits.py @@ -0,0 +1,32 @@ +# 1291. Sequential Digits + +""" +an integer has sequential digits if and only if each digit in the number is +one more than the previous digit. return a sorted list of all the integers in +the range '[low, high]' inclusive that have sequential digits. +""" + + +class Solution(object): + def sequentialDigits(self, low, high): + """ + :type low: int + :type high: int + :rtype: List[int] + """ + ans = [] + queue = deque(range(1, 10)) + while queue: + idx = queue.popleft() + if low <= idx <= high: + ans.append(idx) + last = idx % 10 + if last < 9: + queue.append(idx * 10 + last + 1) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.sequentialDigits(low=100, high=300)) + print(obj.sequentialDigits(low=1000, high=13000)) diff --git a/set_matrix_0.rs b/set_matrix_0.rs new file mode 100644 index 0000000..78c434a --- /dev/null +++ b/set_matrix_0.rs @@ -0,0 +1,44 @@ +// 73. Set Matrix Zeroes +// given an 'm x n' integer matrix 'matrix', if an element is 0, +// set its entire row and column to 0's. must be done in place +// (https://en.wikipedia.org/wiki/In-place_algorithm) + +impl Solution { + pub fn set_zeroes(matrix: &mut Vec<Vec<i32>>) { + let n_rows = matrix.len(); + let n_cols = matrix[0].len(); + let mut first_row = false; + let mut first_col = false; + for row in 0..n_rows { + for col in 0..n_cols { + if matrix[row][col] == 0 { + if row == 0 { + first_row = true; + } + if col == 0 { + first_col = true; + } + matrix[0][col] = 0; + matrix[row][0] = 0; + } + } + } + for row in 1..n_rows { + for col in 1..n_cols { + if matrix[row][0] == 0 || matrix[0][col] == 0 { + matrix[row][col] = 0 + } + } + } + if first_row { + for col in 0..n_cols { + matrix[0][col] = 0; + } + } + if first_col { + for row in 0..n_rows { + matrix[row][0] = 0; + } + } + } +} diff --git a/set_mismatch.c b/set_mismatch.c new file mode 100644 index 0000000..3cdb584 --- /dev/null +++ b/set_mismatch.c @@ -0,0 +1,39 @@ +// 645. Set Mismatch +#include "leetcode.h" + +/* + * you have a set of integers 's' which originally contains all the numbers from + * 1 to 'n'. unfortunately, due to some error, one of the numbers in 's' was + * duplicated to another number in the sett, which results in reptition of one + * number and loss of another number. given an integer array 'nums' representing + * the data state of this set after the error. find the number that occurs twice + * and the number that is missing and return them in the form of an array + */ + +int *findErrorNums(int *nums, int nums_size, int *return_size) { + int a[10001] = {0}; + int *ans = (int *)malloc(sizeof(int) * 2); + *return_size = 2; + for (int i = 0; i < nums_size; i++) + if (++a[nums[i]] == 2) + ans[0] = nums[i]; + for (int i = 1; i <= nums_size; i++) + if (!a[i]) { + ans[1] = i; + return ans; + } + return ans; +} + +int main() { + int n1[] = {1, 2, 2, 4}, n2[] = {1, 1}; + int rs1[] = {}, rs2[] = {}; + int *fen1 = findErrorNums(n1, ARRAY_SIZE(n1), rs1); + int *fen2 = findErrorNums(n2, ARRAY_SIZE(n2), rs2); + for (int i = 0; i < ARRAY_SIZE(n1) / 2; i++) + printf("%d ", fen1[i]); // expect: 2 3 + printf("\n"); + for (int i = 0; i < ARRAY_SIZE(n2); i++) + printf("%d ", fen2[i]); // expect: 1 2 + printf("\n"); +} diff --git a/set_mismatch.cpp b/set_mismatch.cpp new file mode 100644 index 0000000..8c216bc --- /dev/null +++ b/set_mismatch.cpp @@ -0,0 +1,19 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> findErrorNums(vector<int> &nums) { + int p = 0, ac1 = 0, ac2 = 0; + for (uint i = 0; i < nums.size(); ++i) + p ^= (i + 1) ^ nums[i]; + p &= -p; + for (uint i = 0; i < nums.size(); ++i) { + ((nums[i] & p) == 0) ? ac1 ^= nums[i] : ac2 ^= nums[i]; + (((i + 1) & p) == 0) ? ac1 ^= i + 1 : ac2 ^= i + 1; + } + for (auto n : nums) + if (n == ac1) + return {ac1, ac2}; + return {ac2, ac1}; + } +}; diff --git a/set_mismatch.py b/set_mismatch.py new file mode 100644 index 0000000..4c6899b --- /dev/null +++ b/set_mismatch.py @@ -0,0 +1,40 @@ +# 645. Set Mismatch + +""" +you have a set of integers 's' which originally contains all the numbers from +1 to 'n'. unfortunately, due to some error, one of the numbers in 's' was +duplicated to another number in the sett, which results in reptition of one +number and loss of another number. given an integer array 'nums' representing +the data state of this set after the error. find the number that occurs twice +and the number that is missing and return them in the form of an array +""" + + +class Solution(object): + def findErrorNums(self, nums): + """ + :type nums: List[int] + :rtype: List[int] + + given that we have numbers from 1 to 'n' and some number 'x' is here + twice and another number 'y' is missing. let us calculate the sum of all + numbers and sum of squares of all numbers and given this information we can + get our answer using pure math. facts: + 1. 1 + 2 + ... + n = n * (n + 1) // 2 + 2. 1^2 + 2^2 + ... + n^2 = n * (n + 1) * (2 * n + 1) // 6 + now let us consider number 'a = -sum(nums) + n * (n + 1) // 2'. it is + equal to 'y - x', because each element not equal to 'x' and 'y' will be + canceled out. in similar way if we define 'b = -sum(i * i for i in nums) + n + * (n + 1) * (2 * n + 1) // 6', it will be equal to 'y * y - x * x'. so, we + have system of equations: 'a = y - x' and 'b = y * y - x * x' + """ + n = len(nums) + a = -sum(nums) + n * (n + 1) // 2 + b = -sum(i * i for i in nums) + n * (n + 1) * (2 * n + 1) // 6 + return [(b - a * a) // 2 // a, (b + a * a) // 2 // a] + + +if __name__ == "__main__": + obj = Solution() + print(obj.findErrorNums([1, 2, 2, 4])) + print(obj.findErrorNums([1, 1])) diff --git a/set_mismatch.rs b/set_mismatch.rs new file mode 100644 index 0000000..b490f8e --- /dev/null +++ b/set_mismatch.rs @@ -0,0 +1,37 @@ +struct Solution; + +impl Solution { + pub fn find_error_nums(nums: Vec<i32>) -> Vec<i32> { + let mut xor = nums.iter().zip(1..=nums.len() as i32).fold(0, |acc, (&num, i)| acc ^ num ^ i); + xor &= -xor; + let (mut n0, mut n1) = (0, 0); + for &n in &nums { + if n & xor == 0 { + n0 ^= n; + } else { + n1 ^= n; + } + } + for i in 1..=nums.len() as i32 { + if i & xor == 0 { + n0 ^= i; + } else { + n1 ^= i; + } + } + for &n in &nums { + if n == n0 { + return vec![n0, n1]; + } + if n == n1 { + return vec![n1, n0]; + } + } + unreachable!() + } +} + +fn main() { + let nums = vec![1,2,2,4]; + print!("{:?}", Solution::find_error_nums(nums)); +} diff --git a/shift_2d_grid.cpp b/shift_2d_grid.cpp new file mode 100644 index 0000000..b6b06f2 --- /dev/null +++ b/shift_2d_grid.cpp @@ -0,0 +1,19 @@ +#include <bits/stdc++.h> +using namespace std; + +class Solution { +public: + vector<vector<int>> shiftGrid(vector<vector<int>> &grid, int k) { + int n = grid.size(), m = grid[0].size(); + vector<vector<int>> ans(n, vector<int>(m)); + for (int i = 0; i < n; i++) + for (int j = 0; j < m; j++) { + int newJ = (j + k) % m; + int newI = (i + (j + k) / m) % n; + ans[newI][newJ] = grid[i][j]; + } + return ans; + } +}; + +int main() {} diff --git a/short_encoding_words.cpp b/short_encoding_words.cpp new file mode 100644 index 0000000..528191f --- /dev/null +++ b/short_encoding_words.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + int minimumLengthEncoding(vector<string> &words) { + unordered_set<string> us(words.begin(), words.end()); + for (string w : us) + for (int i = 1; i < w.size(); ++i) + us.erase(w.substr(i)); + int ans = 0; + for (string w : us) + ans += w.size() + 1; + return ans; + } +}; + +int main() { + Solution obj; + vector<string> words = {"time", "me", "bell"}; + cout << obj.minimumLengthEncoding(words); +} diff --git a/shortest_bridge.c b/shortest_bridge.c new file mode 100644 index 0000000..7c1a86f --- /dev/null +++ b/shortest_bridge.c @@ -0,0 +1,105 @@ +// 934. Shortest Bridge +#include <stdio.h> +#include <stdlib.h> + +/* + * given an 'n x n' binary matrix grid where 1 represents land and 0 represents + * water. an island is a 4 directionally connected group of 1's not connected to + * any other 1's. there are exactly two islands in a 'grid'. you may change 0's + * to 1's to connect the two islands to form one island. return the smallest + * numbe of 0's you must flip to connect the two islands. + */ + +typedef struct { + int x; + int y; + int step; +} point_t; + +point_t *bfs(int grid_size, int grid[grid_size][grid_size], int grid_col_size, + point_t p, int *size) { + point_t *ans = (point_t *)malloc(10000 * sizeof(point_t)); + *size = 1; + ans[0] = p; + int head = 0; + grid[p.x][p.y] = 2; + int dir[][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + while (head < *size) { + point_t curr = ans[head++]; + for (int i = 0; i < 4; i++) { + int dx = dir[i][0]; + int dy = dir[i][1]; + point_t new = {curr.x + dx, curr.y + dy, 0}; + if (0 <= new.x &&new.x < grid_size && + 0 <= new.y &&new.y < grid_col_size && grid[new.x][new.y] == 1) { + grid[new.x][new.y] = 2; + ans[*size] = new; + (*size)++; + } + } + } + return ans; +} + +int shortestBridge(int grid_size, int grid[grid_size][grid_size], + int *grid_col_size) { + if (!grid || grid_size <= 0 || *grid_col_size <= 0) + return 0; + point_t *lands; + int *size = (int *)malloc(sizeof(int)); + *size = -1; + int flag = 0; + for (int i = 0; i < grid_size; i++) { + for (int j = 0; j < *grid_col_size; j++) { + if (!grid[i][j]) + continue; + point_t tmp = {i, j, 0}; + lands = bfs(grid_size, grid, *grid_col_size, tmp, size); + flag = 1; + break; + } + if (flag) + break; + } + int head = 0, dir[][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + while (head < *size) { + point_t curr = lands[head++]; + for (int i = 0; i < 4; i++) { + int dx = dir[i][0]; + int dy = dir[i][1]; + point_t new = {curr.x + dx, curr.y + dy, curr.step + 1}; + if (0 <= new.x &&new.x < grid_size && + 0 <= new.y &&new.y < *grid_col_size && grid[new.x][new.y] != 3) { + if (grid[new.x][new.y] == 1) { + free(size); + free(lands); + lands = NULL; + return curr.step; + } + if (!grid[new.x][new.y]) { + lands[*size] = new; + (*size)++; + grid[new.x][new.y] = 3; + } + } + } + } + free(size); + free(lands); + lands = NULL; + return -1; +} + +int main() { + int g1[2][2] = {{0, 1}, {1, 0}}, gs1 = 2, gcs1[] = {2, 2}; + int g2[3][3] = {{0, 1, 0}, {0, 0, 0}, {0, 0, 1}}, gs2 = 3, gcs2[] = {3, 3, 3}; + int g3[5][5] = {{1, 1, 1, 1, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 1, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 1, 1, 1, 1}}, + gs3 = 5, gcs3[] = {5, 5, 5, 5, 5}; + printf("%d\n", shortestBridge(gs1, g1, gcs1)); // expect: 1 + printf("%d\n", shortestBridge(gs2, g2, gcs2)); // expect: 2 + printf("%d\n", shortestBridge(gs3, g3, gcs3)); // expect: 1 +} diff --git a/shortest_bridge.cpp b/shortest_bridge.cpp new file mode 100644 index 0000000..632f246 --- /dev/null +++ b/shortest_bridge.cpp @@ -0,0 +1,82 @@ +// 934. Shortest Bridge +#include "leetcode.h" + +/* + * given an 'n x n' binary matrix grid where 1 represents land and 0 represents + * water. an island is a 4 directionally connected group of 1's not connected to + * any other 1's. there are exactly two islands in a 'grid'. you may change 0's + * to 1's to connect the two islands to form one island. return the smallest + * numbe of 0's you must flip to connect the two islands. + */ + +class Solution { + queue<pair<int, int>> qp; + void dfs(vvd(int) & grid, int i, int j) { + if (i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size() || + grid[i][j] == 2 || !grid[i][j]) + return; + grid[i][j] = 2; + qp.push({i, j}); + dfs(grid, i + 1, j); + dfs(grid, i - 1, j); + dfs(grid, i, j + 1); + dfs(grid, i, j - 1); + } + int bfs(vvd(int) & grid) { + int d = 0, min_dist = INT_MAX; + vvd(int) dir = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + while (!qp.empty()) { + int n = qp.size(); + while (n--) { + auto a = qp.front(); + qp.pop(); + for (int h = 0; h < 4; h++) { + int x = dir[h][0] + a.first; + int y = dir[h][1] + a.second; + if (x >= 0 && x < grid.size() && y >= 0 && y < grid[0].size() && + grid[x][y]) + min_dist = min(min_dist, d); + else if (x >= 0 && x < grid.size() && y >= 0 && y < grid[0].size() && + !grid[x][y]) { + qp.push({x, y}); + grid[x][y] = 2; + } + } + } + d++; + } + return min_dist; + } + +public: + int shotestBridge(vvd(int) & grid) { + bool flag = false; + for (int i = 0; i < grid.size(); i++) { + for (int j = 0; j < grid[0].size(); j++) { + if (grid[i][j] && !flag) { + dfs(grid, i, j); + qp.push({i, j}); + flag = true; + break; + } + } + if (flag) + break; + } + return bfs(grid); + } +}; + +int main() { + Solution obj; + vvd(int) g1 = {{0, 1}, {1, 0}}; + vvd(int) g2 = {{0, 1, 0}, {0, 0, 0}, {0, 0, 1}}; + vvd(int) g3 = {{1, 1, 1, 1, 1}, + {1, 0, 0, 0, 1}, + {1, 0, 1, 0, 1}, + {1, 0, 0, 0, 1}, + {1, 1, 1, 1, 1}}; + printf("%d\n", obj.shotestBridge(g1)); // expect: 1 + printf("%d\n", obj.shotestBridge(g2)); // expect: 2 + printf("%d\n", obj.shotestBridge(g3)); // expect: 1 +} diff --git a/shortest_common_subseq.c b/shortest_common_subseq.c new file mode 100644 index 0000000..ddc9906 --- /dev/null +++ b/shortest_common_subseq.c @@ -0,0 +1,61 @@ +// 1092. Shortest Common Supersequence +#include "leetcode.h" + +/* + * given two strings 'str1' and 'str2', return the shortest string that has both + * str1 and str2 as subsequences. if there are multiple valid strings, return + * any of them. a string 's' is a supersequence if string 't' if deleting some + * number of characters from 't' (possibly 0) results in string 's'. + */ + +void reverse(char *s) { + int n = strlen(s); + for (int i = 0; i < n / 2; i++) { + char tmp = s[i]; + s[i] = s[n - 1 - i]; + s[n - 1 - i] = tmp; + } +} + +char *shortestCommonSupersequence(char *s1, char *s2) { + int m = strlen(s1), n = strlen(s2); + int dp[m + 1][n + 1]; + for (int i = 0; i <= m; i++) + for (int j = 0; j <= n; j++) { + if (!i) + dp[i][j] = j; + else if (!j) + dp[i][j] = i; + else if (s1[i - 1] == s2[j - 1]) + dp[i][j] = 1 + dp[i - 1][j - 1]; + else + dp[i][j] = 1 + fmin(dp[i - 1][j], dp[i][j - 1]); + } + char *ans = calloc(4000, sizeof(char)); + int idx = 0, i = m, j = n; + while (i && j) { + if (s1[i - 1] == s2[j - 1]) { + ans[idx++] = s1[i - 1]; + i--; + j--; + } else if (dp[i - 1][j] > dp[i][j - 1]) { + ans[idx++] = s2[j - 1]; + j--; + } else { + ans[idx++] = s1[i - 1]; + i--; + } + } + while (i) + ans[idx++] = s1[i - 1], i--; + while (j) + ans[idx++] = s2[j - 1], j--; + reverse(ans); + return ans; +} + +int main() { + char *s11 = "abac", *s21 = "cab", *s12 = "aaaaaaaa", *s22 = "aaaaaaaa"; + printf("%s\n", shortestCommonSupersequence(s11, s21)); // expect: cabac + printf("%s\n", shortestCommonSupersequence(s12, s22)); // expect: aaaaaaaa +} diff --git a/shortest_common_subseq.py b/shortest_common_subseq.py new file mode 100644 index 0000000..63081d1 --- /dev/null +++ b/shortest_common_subseq.py @@ -0,0 +1,45 @@ +# 1092. Shortest Common Supersequence + +""" +given two strings 's1' and 's2', return the shortest string that has both +s1 and s2 as subsequences. if there are multiple valid strings, return +any of them. a string 's' is a supersequence if string 't' if deleting some +number of characters from 't' (possibly 0) results in string 's'. +""" + + +class Solution(object): + def lcs(self, s1, s2): + n, m = len(s1), len(s2) + dp = [["" for i in range(m + 1)] for j in range(n + 1)] + for i in range(n): + for j in range(m): + if s1[i] == s2[j]: + dp[i + 1][j + 1] = dp[i][j] + s1[i] + else: + dp[i + 1][j + 1] = max(dp[i + 1][j], dp[i][j + 1], key=len) + return dp[-1][-1] + + def shortestCommonSupersequence(self, s1, s2): + """ + :type s1: str + :type s2: str + :rtype: str + """ + ans, i, j = "", 0, 0 + for c in self.lcs(s1, s2): + while s1[i] != c: + ans += s1[i] + i += 1 + while s2[j] != c: + ans += s2[j] + j += 1 + ans += c + i, j = i + 1, j + 1 + return ans + s1[i:] + s2[j:] + + +if __name__ == "__main__": + obj = Solution() + print(obj.shortestCommonSupersequence(s1="abac", s2="cab")) + print(obj.shortestCommonSupersequence(s1="aaaaaaaa", s2="aaaaaaaa")) diff --git a/shortest_path_alternate_color.cpp b/shortest_path_alternate_color.cpp new file mode 100644 index 0000000..5122fef --- /dev/null +++ b/shortest_path_alternate_color.cpp @@ -0,0 +1,56 @@ +// 1129. Shortest Path with Alternating Colors +#include "leetcode.h" + +class Solution { +public: + vector<int> shortestAlternatingPaths(int n, vvd(int) & redEdges, + vvd(int) & blueEdges) { + vector<int> ans(n, -1), v1(n, 0), v2(n, 0); + vector<vector<pair<int, int>>> vvp(n); + queue<pair<int, int>> qp; + for (auto &it : redEdges) + vvp[it[0]].push_back({it[1], 1}); + for (auto &it : blueEdges) + vvp[it[0]].push_back({it[1], 2}); + ans[0] = 0, v1[0] = 1, v2[0] = 1; + int tmp = 1; + for (auto &it : vvp[0]) { + qp.push(it); + if (ans[it.first] == -1) + ans[it.first] = tmp; + } + while (!qp.empty()) { + int len = qp.size(); + tmp++; + for (int i = 0; i < len; ++i) { + auto val = qp.front(); + qp.pop(); + if (val.second == 1) + v1[val.first] = 1; + else + v2[val.first] = 1; + for (auto &it : vvp[val.first]) { + if (val.second == 1 && (v2[it.first] || it.second == 1)) + continue; + if (val.second == 2 && (v1[it.first] || it.second == 2)) + continue; + qp.push(it); + if (ans[it.first] == -1) + ans[it.first] = tmp; + } + } + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) re1 = {{0, 1}, {1, 2}}, be1 = {}; + vvd(int) re2 = {{0, 1}}, be2 = {{2, 1}}; + for (auto i : obj.shortestAlternatingPaths(3, re1, be1)) + cout << i << ' '; // expect: 0 1 -1 + cout << endl; + for (auto i : obj.shortestAlternatingPaths(3, re2, be2)) + cout << i << ' '; // expect: 0 1 -1 +} diff --git a/shortest_path_binary_matrix.c b/shortest_path_binary_matrix.c new file mode 100644 index 0000000..28da729 --- /dev/null +++ b/shortest_path_binary_matrix.c @@ -0,0 +1,115 @@ +// 1091. Shortest Path in Binary Matrix +#include <assert.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given an n x n binary matrix 'grid', return the length of the shortest clear + * path in the matrix. if there is no clear path, return -1. a clear path in a + * binary matrix is a path from the top-left cell (ie. 0,0) to the bottom-right + * cell (ie. n - 1, n - 1) such thatyt + * - all the visited cells are of the path 0 + * - all the adjacent cells of the path are 8-directionally connected (ie. they + * are different and they share an edge of a corner) the length of a clear path + * is the number of visited cells of this path + */ + +typedef struct pair { + int x; + int y; +} pair_t; + +typedef pair_t queue_data_t; + +typedef enum queue { + QUEUE_OK, + QUEUE_EMPTY, + QUEUE_FULL, + QUEUE_ERROR = 0xFF +} queue_er_em; + +typedef struct queue_t { + queue_data_t *value; + int buf_size; + int offer_i; + int poll_i; + int cnt; +} queue_t; + +queue_t *create_queue(int buf_size) { + queue_t *q = malloc(sizeof(queue_t)); + memset(q, 0, sizeof(queue_t)); + q->buf_size = buf_size; + q->value = malloc(buf_size * sizeof(queue_data_t)); + memset(q->value, 0, buf_size * sizeof(queue_data_t)); + return q; +} + +queue_er_em offer_queue(queue_t *q, queue_data_t *data) { + assert(q->cnt < q->buf_size); + if (q->cnt >= q->buf_size) + return QUEUE_ERROR; + memcpy(&q->value[q->offer_i++], data, sizeof(queue_data_t)); + if (q->offer_i == q->buf_size) + q->offer_i = 0; + q->cnt++; + return QUEUE_OK; +} + +queue_er_em poll_queue(queue_t *q, queue_data_t *data) { + assert(q->cnt); + if (q->cnt < 1) + return QUEUE_EMPTY; + memcpy(data, &q->value[q->poll_i++], sizeof(queue_data_t)); + if (q->poll_i == q->buf_size) + q->poll_i = 0; + q->cnt--; + return QUEUE_OK; +} + +inline int get_data(queue_t *q) { return q->cnt; } + +bool empty(queue_t *q) { return (q->cnt); } + +int shortestPathBinaryMatrix(int **grid, int grid_size, int *grid_col_size) { + if (grid[0][0] == 1) + return -1; + queue_t *buf = create_queue(500); + int dirr[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, + {0, 1}, {1, -1}, {1, 0}, {1, 1}}; + pair_t p = {.x = 0, .y = 0}; + pair_t tmp; + int cnt = 0; + offer_queue(buf, &p); + while (!empty(buf)) { + int c = get_data(buf); + cnt++; + for (int i = 0; i < c; i++) { + poll_queue(buf, &p); + if (p.x == grid_size - 1 && p.y == grid_col_size[0] - 1) + return cnt; + for (int j = 0; j < 8; j++) { + int tr = p.x + dirr[j][0]; + int tc = p.y + dirr[j][1]; + if (tr >= 0 && tr < grid_size && tc >= 0 && tc < grid_col_size[0] && + !grid[tr][tc]) { + tmp.x = tr; + tmp.y = tc; + offer_queue(buf, &tmp); + grid[tr][tc] = -1; + } + } + } + } + return -1; +} + +int main() int g1[2][2] = {{0, 1}, {1, 0}}, gs1 = 2, gcs1[] = { 2, 2 }; +int g2[3][3] = {{0, 0, 0}, {1, 1, 0}, {1, 1, 1}}, gs2 = 3, gcs[] = {3, 3, 3}; +int g3[3][3] = {{1, 0, 0}, {1, 1, 0}, {1, 1, 0}}, gs3 = 3, gc3[] = {3, 3, 3}; +printf("%d\n", shortestPathBinaryMatrix(g1, gs1, gc1)); // expect: 2 +printf("%d\n", shortestPathBinaryMatrix(g2, gs2, gc2)); // expect: 4 +printf("%d\n", shortestPathBinaryMatrix(g3, gs3, gc3)); // expect: -1 +} diff --git a/shortest_path_binary_matrix.cpp b/shortest_path_binary_matrix.cpp new file mode 100644 index 0000000..67cd095 --- /dev/null +++ b/shortest_path_binary_matrix.cpp @@ -0,0 +1,40 @@ +#include "leetcode.h" +#include <algorithm> +#include <queue> +#include <utility> +#include <vector> + +class Solution { +public: + int shortestPathBinaryMatrix(vector<vector<int>> &grid) { + if (grid[0][0] || grid.back().back()) + return -1; + int ans = 2, len = 1, nX = grid[0].size() - 1, nY = grid.size() - 1; + queue<pair<int, int>> qp; + if (!nX && !nY) + return 1 - (grid[0][0] << 1); + qp.push({0, 0}); + grid[0][0] = -1; + while (len) { + while (len--) { + auto [cX, cY] = qp.front(); + qp.pop(); + for (int i = max(0, cX - 1), lmtX = min(cX + 1, nX); i <= lmtX; i++) { + for (int j = max(0, cY - 1), lmtY = min(cY + 1, nY); j <= lmtY; j++) { + if (i == nX && j == nY) + return ans; + if (!grid[j][i]) { + grid[j][i] = -1; + qp.push({i, j}); + } + } + } + } + ans++; + len = qp.size(); + } + return -1; + } +}; + +int main() {} diff --git a/shortest_path_grid_obstacle.cpp b/shortest_path_grid_obstacle.cpp new file mode 100644 index 0000000..a023bc3 --- /dev/null +++ b/shortest_path_grid_obstacle.cpp @@ -0,0 +1,48 @@ +#include "leetcode.h" + +class Solution { +public: + int shortestPath(vvd(int) & grid, int k) { + int rows = grid.size(), cols = grid[0].size(); + int minStep = max(0, rows + cols - 2), obstacles = minStep - 1, + minStepNext = minStep; + if (obstacles <= k) + return minStep; + vvd(int) dirs = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + list<vector<int>> togo; + togo.push_back({0, 0, k}); + vector<int> visited(rows * cols, -1); + visited[0] = k; + int steps = 0; + while (togo.size()) { + steps++; + minStep = minStepNext; + for (int i = togo.size(); i > 0; i--) { + int a = togo.front()[0], b = togo.front()[1], c = togo.front()[2]; + togo.pop_front(); + for (auto &d : dirs) { + int aa = a + d[0], bb = b + d[1]; + if (aa < 0 || aa >= rows || bb < 0 || bb >= cols) + continue; + int cc = c - grid[aa][bb]; + if (visited[aa * cols + bb] >= cc) + continue; + int stepsToTarget = rows - aa - 1 + cols - bb - 1; + if (stepsToTarget - 1 <= cc && stepsToTarget == minStep - 1) + return steps + stepsToTarget; + togo.push_back({aa, bb, cc}); + visited[aa * cols + bb] = cc; + minStepNext = min(minStepNext, stepsToTarget); + } + } + } + return -1; + } +}; + +int main() { + Solution obj; + vvd(int) grid = {{0, 0, 0}, {1, 1, 0}, {0, 0, 0}, {0, 1, 1}, {0, 0, 0}}; + int k = 1; + cout << obj.shortestPath(grid, k); +} diff --git a/shortest_path_grid_obstacle.rs b/shortest_path_grid_obstacle.rs new file mode 100644 index 0000000..ba35681 --- /dev/null +++ b/shortest_path_grid_obstacle.rs @@ -0,0 +1,38 @@ +use std::collections::VecDeque; +struct Solution; + +impl Solution { + pub fn shortest_path(grid: Vec<Vec<i32>>, k: i32) -> i32 { + let m = grid.len() as i32; let n = grid[0].len() as i32; + let dir = [-1, 0, 1, 0, -1]; + let mut dq = VecDeque::new(); + let mut visited = vec![vec![0; n as usize]; m as usize]; + let mut ans = 0; + dq.push_back((0,0,k)); + visited[0][0] = k + 1; + while !dq.is_empty() { + for _ in 0..dq.len() { + let (row, col, left) = dq.pop_front().unwrap(); + if row == m - 1 && col == n - 1 { + return ans; + } + for (&i, &j) in dir.iter().zip(dir.iter().skip(1)){ + let (new_row, new_col) = (row + i, col + j); + if new_row < 0 || new_row >= m || new_col < 0 || new_col >= n + || visited[new_row as usize][new_col as usize] >= left + 1 { + continue; + } + if grid[new_row as usize][new_col as usize] == 0 { + dq.push_back((new_row, new_col, left)); + visited[new_row as usize][new_col as usize] = left + 1; + } else if left > 0 { + dq.push_back((new_row, new_col, left - 1)); + visited[new_row as usize][new_col as usize] = left; + } + } + } + ans += 1; + } + -1 + } +} diff --git a/shortest_path_keys.cpp b/shortest_path_keys.cpp new file mode 100644 index 0000000..7a3cd7d --- /dev/null +++ b/shortest_path_keys.cpp @@ -0,0 +1,109 @@ +// 864. Shortest Path to Get All Keys +#include "leetcode.h" + +/* + * given an 'm x n' grid 'grid' where: + * - '.' is an empty cell + * - '#' is a wall + * - '@' is the starting point + * - lowercase letters represent keys + * - uppercase letters represent locks + * you start at the starting point and one move consists of walking one space in + * one of the four cardinal directions. you cannot walk outside the grid, or + * walk into a wall. if you walk over a key, you can pick it up and you cannot + * walk over a lock unless you have its corresponding key. for some '1 <= k <= + * 6', there is exactly one lowercase and one uppercase letter of the first 'k' + * letters of the english alphabet in the grid. this means that there is exactly + * one key for each lock, and one lock for each key; and also that the letters + * used to represent the keys and locks were chosen in the same order as the + * english alphabet. return the lowest number of moves to acquire all keys. if + * it is impossible, return -1 + */ + +class Info { +public: + pair<int, int> p; + vector<int> keys; + int cnt; + Info(pair<int, int> p, vector<int> keys, int cnt) { + this->p = p; + this->keys = keys; + this->cnt = cnt; + } + int get_state() { + int state = 0; + for (int i = 0; i < keys.size(); i++) { + state <<= 1; + state += keys[i]; + } + return state; + } +}; + +class Solution { +public: + int shortestPathAllKeys(vector<string> &grid) { + pair<int, int> start; + int m = grid.size(), n = grid[0].size(), key_cnt = 0; + if (!m) + return -1; + for (int i = 0; i < m; i++) + for (int j = 0; j < n; j++) { + if (grid[i][j] == '@') + start = make_pair(i, j); + else if (grid[i][j] >= 'a' && grid[i][j] <= 'f') + key_cnt++; + } + queue<Info> q; + vector<int> keys_start(key_cnt, 0); + q.push(Info(start, keys_start, 0)); + int ans = -1; + vector<vector<vector<int>>> vis; + for (int i = 0; i < 1 << key_cnt; i++) { + vvd(int) tmp(m, vector<int>(n, 0)); + vis.push_back(tmp); + } + while (!q.empty()) { + auto curr = q.front(); + q.pop(); + int state = curr.get_state(); + if (state == (1 << key_cnt) - 1) { + ans = curr.cnt; + break; + } + if (vis[state][curr.p.first][curr.p.second]) + continue; + vis[state][curr.p.first][curr.p.second] = 1; + int dx[] = {0, 1, 0, -1}; + int dy[] = {1, 0, -1, 0}; + for (int i = 0; i < 4; i++) { + int xx = curr.p.first + dx[i]; + int yy = curr.p.second + dy[i]; + auto keys = curr.keys; + auto cnt = curr.cnt + 1; + if (xx >= 0 && xx < m && yy >= 0 && yy < n) { + if (grid[xx][yy] >= 'a' && grid[xx][yy] <= 'f') { + int no = grid[xx][yy] - 'a'; + keys[no] = 1; + } else if (grid[xx][yy] >= 'A' && grid[xx][yy] <= 'F') { + int no = grid[xx][yy] - 'A'; + if (!keys[no]) + continue; + } else if (grid[xx][yy] == '#') + continue; + q.push(Info(make_pair(xx, yy), keys, cnt)); + } + } + } + return ans; + } +}; + +int main() { + Solution obj; + vector<string> g1 = {"@.a..", "###.#", "b.A.B"}, + g2 = {"@..aA", "..B#.", "....b"}, g3 = {"@Aa"}; + printf("%d\n", obj.shortestPathAllKeys(g1)); // expect: 8 + printf("%d\n", obj.shortestPathAllKeys(g2)); // expect: 6 + printf("%d\n", obj.shortestPathAllKeys(g3)); // expect: -1 +} diff --git a/shortest_path_vis_nodes.cpp b/shortest_path_vis_nodes.cpp new file mode 100644 index 0000000..8ac5587 --- /dev/null +++ b/shortest_path_vis_nodes.cpp @@ -0,0 +1,62 @@ +// 847. Shortest Path Visiting All Nodes +#include "leetcode.h" + +/* + * you have an undirected, connected graph of 'n' nodes labeled from 0 to 'n - + * 1'. you are given an array 'graph' where 'graph[i]' is a list of all the + * nodes connected with node 'i' by an edge. return the length of the shortest + * path that visits every node. you may start and stop any any node. you may + * revisit nodes multiple times and you may reused edges. + */ + +class Solution { +public: + class tuple { + public: + int node; + int mask; + int cost; + tuple(int node, int mask, int cost) { + this->node = node; + this->mask = mask; + this->cost = cost; + } + }; + + int shortestPathLength(vvd(int) & graph) { + int n = graph.size(); + queue<tuple> q; + set<pair<int, int>> vis; + int all = (1 << n) - 1; + for (int i = 0; i < n; i++) { + int mask_val = 1 << i; + tuple curr(i, mask_val, 1); + q.push(curr); + vis.insert({i, mask_val}); + } + while (!q.empty()) { + tuple curr = q.front(); + q.pop(); + if (curr.mask == all) + return curr.cost - 1; + for (auto adj : graph[curr.node]) { + int both_vis = curr.mask; + both_vis = both_vis | (1 << adj); + tuple node(adj, both_vis, curr.cost + 1); + if (vis.find({adj, both_vis}) == vis.end()) { + vis.insert({adj, both_vis}); + q.push(node); + } + } + } + return -1; + } +}; + +int main() { + Solution obj; + vvd(int) g1 = {{1, 2, 3}, {0}, {0}}, + g2 = {{1}, {0, 2, 4}, {1, 3, 4}, {2}, {1, 2}}; + printf("%d\n", obj.shortestPathLength(g1)); // expect: 4 + printf("%d\n", obj.shortestPathLength(g2)); // expect: 4 +} diff --git a/shortest_path_vis_nodes.py b/shortest_path_vis_nodes.py new file mode 100644 index 0000000..f9ef5a3 --- /dev/null +++ b/shortest_path_vis_nodes.py @@ -0,0 +1,43 @@ +# 847. Shortest Path Visiting All Nodes +from math import inf +from collections import deque + +""" +you have an undirected, connected graph of 'n' nodes labeled from 0 to 'n - +1'. you are given an array 'graph' where 'graph[i]' is a list of all the +nodes connected with node 'i' by an edge. return the length of the shortest +path that visits every node. you may start and stop any any node. you may +revisit nodes multiple times and you may reused edges. +""" + + +class Solution(object): + def shortestPathLength(self, graph): + node_cnt = len(graph) + masks = [1 << i for i in range(node_cnt)] + all_vis = (1 << node_cnt) - 1 + queue = deque([(i, masks[i]) for i in range(node_cnt)]) + steps = 0 + vis_state = [{masks[i]} for i in range(node_cnt)] + while queue: + cnt = len(queue) + while cnt: + curr_node, vis = queue.popleft() + if vis == all_vis: + return steps + for nb in graph[curr_node]: + new_vis = vis | masks[nb] + if new_vis == all_vis: + return steps + 1 + if new_vis not in vis_state[nb]: + vis_state[nb].add(new_vis) + queue.append((nb, new_vis)) + cnt -= 1 + steps += 1 + return inf + + +if __name__ == "__main__": + obj = Solution() + print(obj.shortestPathLength([[1, 2, 3], [0], [0], [0]])) # expect: 4 + print(obj.shortestPathLength([[1], [0, 2, 4], [1, 3, 4], [2], [1, 2]])) # expect: 4 diff --git a/shortest_unsorted_subarr.cpp b/shortest_unsorted_subarr.cpp new file mode 100644 index 0000000..849f524 --- /dev/null +++ b/shortest_unsorted_subarr.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + int findUnsortedSubarray(vector<int> &nums) { + int end = -1, start = 0; + int max = nums[0], min = nums[nums.size() - 1]; + for (int i = 1; i < nums.size(); i++) { + if (max > nums[i]) + end = i; + else + max = nums[i]; + } + for (int i = nums.size() - 2; i >= 0; i--) { + if (min < nums[i]) + start = i; + else + min = nums[i]; + } + return end - start + 1; + } +}; + +int main() { + vector<int> nums = {2, 6, 4, 8, 10, 9, 15}; + Solution obj; + for (int i = 0; i < nums.size(); i++) + cout << nums[i] << ' '; + cout << endl << obj.findUnsortedSubarray(nums); +} diff --git a/shortest_unsorted_subarray.cpp b/shortest_unsorted_subarray.cpp new file mode 100644 index 0000000..ab56ec6 --- /dev/null +++ b/shortest_unsorted_subarray.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + int findUnsortedSubarray(vector<int> &nums) { + int l = -1, r = -1, n = nums.size(); + for (int i = 0; i < n - 1; i++) + if (nums[i] > nums[i + 1]) { + l = i; + break; + } + for (int i = n - 1; i <= 1; i--) + if (nums[i] < nums[i - 1]) { + r = i; + break; + } + if (l == -1) + return 0; + int minI = nums[l], maxI = nums[l]; + for (int i = l; i <= r; i++) { + minI = min(minI, nums[i]); + maxI = max(maxI, nums[i]); + } + l = upper_bound(nums.begin(), nums.begin() + l, minI) - nums.begin(); + r = lower_bound(nums.begin() + r + 1, nums.end(), maxI) - nums.begin(); + return r - l; + } +}; + +int main() {} diff --git a/shuffle_array.c b/shuffle_array.c new file mode 100644 index 0000000..0192604 --- /dev/null +++ b/shuffle_array.c @@ -0,0 +1,31 @@ +// 1470. Shuffle the Array +#include <stdio.h> +#include <stdlib.h> + +/* + * given array 'nums' consisting of '2n' elements in the form + * [x1, x2, ..., xn, y1, y2, ..., yn] + * return the array in the form [x1, y1, x2, y2, ..., xn, yn] + */ + +int *shuffle(int *nums, int numsSize, int n, int *returnSize) { + int i = 0, j = n, k = 0; + int *ans = (int *)malloc(numsSize * sizeof(int)); + while (i < n && j < numsSize) { + ans[k++] = nums[i]; + ans[k++] = nums[j]; + i++; + j++; + } + *returnSize = numsSize; + return ans; +} + +int main() { + int nums1[] = {2, 5, 1, 3, 4, 7}, rs1[] = {6}, ns1 = 6, n1 = 3; + int nums2[] = {1, 2, 3, 4, 4, 3, 2, 1}, rs2[] = {8}, ns2 = 8, n2 = 4; + int nums3[] = {1, 1, 2, 2}, rs3[] = {4}, ns3 = 4, n3 = 2; + printf("%d\n", *shuffle(nums1, ns1, n1, rs1)); + printf("%d\n", *shuffle(nums2, ns2, n2, rs2)); + printf("%d\n", *shuffle(nums3, ns3, n3, rs3)); +} diff --git a/shuffle_array.cpp b/shuffle_array.cpp new file mode 100644 index 0000000..f7dddea --- /dev/null +++ b/shuffle_array.cpp @@ -0,0 +1,39 @@ +// 1470. Shuffle the Array +#include "leetcode.h" + +/* + * given array 'nums' consisting of '2n' elements in the form + * [x1, x2, ..., xn, y1, y2, ..., yn] + * return the array in the form [x1, y1, x2, y2, ..., xn, yn] + */ + +class Solution { +public: + vector<int> shuffle(vector<int> &nums, int n) { + int len = nums.size(); + for (int i = n; i < len; i++) + nums[i] = (nums[i] << 10) | nums[i - n]; + int idx = 0; + for (int i = n; i < len; i++, idx += 2) { + nums[idx] = nums[i] & 1023; + nums[idx + 1] = nums[i] >> 10; + } + return nums; + } +}; + +int main() { + Solution obj; + vector<int> nums1 = {2, 5, 1, 3, 4, 7}; + vector<int> nums2 = {1, 2, 3, 4, 4, 3, 2, 1}; + vector<int> nums3 = {1, 1, 2, 2}; + for (auto i : obj.shuffle(nums1, 3)) + cout << i << ' '; // expect: 2,3,5,4,1,7 + cout << endl; + for (auto i : obj.shuffle(nums2, 4)) + cout << i << ' '; // expect: 1,4,2,3,3,2,4,1 + cout << endl; + for (auto i : obj.shuffle(nums3, 2)) + cout << i << ' '; // expect: 1,2,1,2 + cout << endl; +} diff --git a/similar_string_group.c b/similar_string_group.c new file mode 100644 index 0000000..b8ed3f9 --- /dev/null +++ b/similar_string_group.c @@ -0,0 +1,59 @@ +// 839. Similar String Groups +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * two strings 'x' and 'y' are similar if we can swap two letters + * of 'x' so that it equals 'y'. also two strings 'x' and 'y' are + * given a list of 'strs' of strings where every string in 'strs' + * is an anagram of every other string in 'strs'. how many groups? + */ + +bool similar(char *a, char *b) { + int len = strlen(a), diff_count = 0; + for (int i = 0; i < strlen(a); i++) { + if (a[i] != b[i]) + diff_count++; + if (diff_count > 2) + return false; + } + return true; +} + +void dfs(char **a, int a_size, char *string) { + char *tmp = NULL; + for (int i = 0; i < a_size; i++) { + if (!a[i]) + continue; + if (similar(a[i], string)) { + tmp = a[i]; + a[i] = NULL; + dfs(a, a_size, tmp); + } + } +} + +int numSimilarGroups(char **strs, int strs_size) { + int cnt = 0; + char *tmp = NULL; + if (!strs || strs_size) + return 0; + for (int i = 0; i < strs_size; i++) { + if (!strs[i]) + continue; + tmp = strs[i]; + strs[i] = NULL; + cnt++; + dfs(strs, strs_size, tmp); + } + return cnt; +} + +int main() { + char s1[][4] = {{"tars"}, {"rats"}, {"arts"}, {"star"}}; + char s2[][3] = {{"omv"}, {"ovm"}}; + printf("%d\n", numSimilarGroups(s1, 4)); + printf("%d\n", numSimilarGroups(s2, 2)); +} diff --git a/similar_string_group.cpp b/similar_string_group.cpp new file mode 100644 index 0000000..273df4f --- /dev/null +++ b/similar_string_group.cpp @@ -0,0 +1,63 @@ +// 839. Similar String Groups +#include "leetcode.h" + +/* + * two strings 'x' and 'y' are similar if we can swap two letters + * of 'x' so that it equals 'y'. also two strings 'x' and 'y' are + * given a list of 'strs' of strings where every string in 'strs' + * is an anagram of every other string in 'strs'. how many groups? + */ + +class disjointSet { + vector<int> v; + int sz; + +public: + void make_set(int n) { + v.resize(n); + iota(v.begin(), v.end(), 0); + sz = n; + } + disjointSet(int n) { make_set(n); } + int find(int i) { + if (i != v[i]) + v[i] = find(v[i]); + return v[i]; + } + void join(int i, int j) { + int r_i = find(i), r_j = find(j); + if (r_i != r_j) { + v[r_i] = r_j; + sz--; + } + } + int size() { return sz; } +}; + +class Solution { + bool similar(string a, string b) { + int n = 0; + for (int i = 0; i < a.size(); i++) + if (a[i] != b[i] && ++n > 2) + return false; + return true; + } + +public: + int numSimilarGroups(vector<string> &strs) { + disjointSet ds(strs.size()); + for (int i = 0; i < strs.size(); i++) + for (int j = i + 1; j < strs.size(); j++) + if (similar(strs[i], strs[j])) + ds.join(i, j); + return ds.size(); + } +}; + +int main() { + Solution obj; + vector<string> s1 = {"tars", "rats", "arts", "star"}; + vector<string> s2 = {"omv", "ovm"}; + printf("%d\n", obj.numSimilarGroups(s1)); + printf("%d\n", obj.numSimilarGroups(s2)); +} diff --git a/simplify_path.c b/simplify_path.c new file mode 100644 index 0000000..6617a54 --- /dev/null +++ b/simplify_path.c @@ -0,0 +1,63 @@ +// 71. Simplify Path +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +// given a string 'path', which is an absolute path (starting with a slash) to a +// file or directory in a unix-style file system, convert it to the simplified +// canonical path + +char *go_upper(char *head, char *tail) { + for (; *tail != '/' && tail != head; tail--) + ; + if (tail == head) { + *head = '/'; + tail++; + } + *tail = '\0'; + return tail; +} + +char *go_lower(char *tail, char *level) { + while ((*tail++ = *level++) != '\0') + ; + return tail - 1; +} + +char *next_level(char **level, char *path) { + *level = malloc(sizeof(char) * 200); + int l = 0; + (*level)[l++] = *path++; + for (; *path == '/'; path++) + ; + for (; *path != '/' && *path != '\0'; path++) + (*level)[l++] = *path; + (*level)[l] = '\0'; + return path; +} + +char *simplifyPath(char *path) { + char *head = malloc(sizeof(char) * strlen(path)); + char *tail = head, *level; + *tail++ = '/'; + while (*path != '\0') { + path = next_level(&level, path); + if (!strcmp(level, "/.") || !strcmp(level, "/")) + continue; + else if (!strcmp(level, "/..")) + tail = go_upper(head, tail); + else + tail = go_lower(tail, level); + free(level); + } + while (*(head + 1) == '/') + head++; + return head; +} + +int main() { + char p1[] = {"/home/"}, p2[] = {"/../"}, p3[] = {"/home//foo/"}; + printf("%s\n", simplifyPath(p1)); // expect: /home + printf("%s\n", simplifyPath(p2)); // expect: / + printf("%s\n", simplifyPath(p3)); // expect: /home/foo +} diff --git a/simplify_path.cpp b/simplify_path.cpp new file mode 100644 index 0000000..09852f3 --- /dev/null +++ b/simplify_path.cpp @@ -0,0 +1,33 @@ +// 71. Simplify Path +#include "leetcode.h" + +// given a string 'path', which is an absolute path (starting with a slash) to a +// file or directory in a unix-style file system, convert it to the simplified +// canonical path + +class Solution { +public: + string simplifyPath(string path) { + vector<string> stack; + string ans, tmp; + stringstream p(path); + while (getline(p, tmp, '/')) { + if (tmp == "" || tmp == ".") + continue; + if (!stack.empty() && tmp == "..") + stack.pop_back(); + else if (tmp != "..") + stack.push_back(tmp); + } + for (auto s : stack) + ans += "/" + s; + return stack.empty() ? "/" : ans; + } +}; + +int main() { + Solution obj; + cout << obj.simplifyPath("/home/") << endl; // expect: /home/ + cout << obj.simplifyPath("/../") << endl; // expect: / + cout << obj.simplifyPath("/home//foo/") << endl; // expect: /home/foo +} diff --git a/single_element_sorted_arr.c b/single_element_sorted_arr.c new file mode 100644 index 0000000..f8ecdaa --- /dev/null +++ b/single_element_sorted_arr.c @@ -0,0 +1,51 @@ +// 540. Single Element in a Sorted Array +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given a sorted array consisting of only integers where very element appears + * exactly twice, except for one element which appears exactly once. return the + * single element that appears only once. solution func must be o(ln) time and + * o(1) space complexity. + */ + +int singleNonDuplicate(int *nums, int nums_size) { + if (nums_size == 1) + return nums[0]; + if (nums[0] != nums[1]) + return nums[0]; + if (nums[nums_size - 1] != nums[nums_size - 2]) + return nums[nums_size - 1]; + int left = 2, right = nums_size - 3, mid; + bool ptr_l, ptr_r; + while (left < right) { + mid = (left + right) / 2; + ptr_l = (nums[mid] == nums[mid - 1]) ? true : false; + ptr_r = (nums[mid] == nums[mid + 1]) ? true : false; + // if ((ptr_l == false) && (ptr_r == false)) + if (!ptr_l && !ptr_r) + return nums[mid]; + if (mid % 2 == 0) { + if (ptr_l) + right = mid - 2; + else + left = mid + 2; + } else { + if (ptr_r) + right = mid - 1; + else + left = mid + 1; + } + } + if (nums[left] != nums[left - 1] || nums[left] != nums[left + 1]) + return nums[left]; + else + return nums[right]; +} + +int main() { + int nums1[] = {1, 1, 2, 3, 3, 4, 4, 8, 8}, nums2[] = {3, 3, 7, 7, 10, 11, 11}; + printf("%d\n", singleNonDuplicate(nums1, 9)); // expect: 2 + printf("%d\n", singleNonDuplicate(nums2, 9)); // expect: 10 +} diff --git a/single_element_sorted_arr.cpp b/single_element_sorted_arr.cpp new file mode 100644 index 0000000..e9bd894 --- /dev/null +++ b/single_element_sorted_arr.cpp @@ -0,0 +1,33 @@ +// 540. Single Element in a Sorted Array +#include "leetcode.h" + +/* + * given a sorted array consisting of only integers where very element appears + * exactly twice, except for one element which appears exactly once. return the + * single element that appears only once. solution func must be o(ln) time and + * o(1) space complexity. + */ + +class Solution { +public: + int singleNonDuplicate(vector<int> &nums) { + int low = 0, high = nums.size() - 1, mid; + while (low < high) { + mid = (low + high) / 2; + if ((mid % 2 && nums[mid - 1] == nums[mid]) || + (!(mid % 2) && nums[mid] == nums[mid + 1])) + low = mid + 1; + else + high = mid; + } + return nums[low]; + } +}; + +int main() { + Solution obj; + vector<int> nums1 = {1, 1, 2, 3, 3, 4, 4, 8, 8}, + nums2 = {3, 3, 7, 7, 10, 11, 11}; + cout << obj.singleNonDuplicate(nums1) << endl; // expect: 2 + cout << obj.singleNonDuplicate(nums2) << endl; // expect: 10 +} diff --git a/single_number.cpp b/single_number.cpp new file mode 100644 index 0000000..e9a5878 --- /dev/null +++ b/single_number.cpp @@ -0,0 +1,38 @@ +#include "leetcode.h" + +class Solution { +public: + int singleNumber(vector<int> &nums) { + int ans; + /* + * unordered_map to track frequency + * unordered_map<key data type, value data type> + * both are int in this case. + */ + unordered_map<int, int> freq; + for (int i = 0; i < nums.size(); i++) + /* + * store frequency + * given 4, 1, 2, 1, 2 + * 4 -> once + * 1 -> twice + * 2 -> twice + * output: 4 + */ + freq[nums[i]]++; + for (auto i : freq) // traverse map + if (i.second == 1) { // if frequency of any element is 1... + ans = i.first; // that's the answer + break; // exit loop because we have our answer + } + return ans; + } +}; + +int main() { + vector<int> nums = {4, 1, 2, 1, 2}; + Solution obj; + for (int i = 0; i < nums.size(); i++) + cout << nums[i] << ' '; + cout << endl << obj.singleNumber(nums); +} diff --git a/single_number.rs b/single_number.rs new file mode 100644 index 0000000..c724ebf --- /dev/null +++ b/single_number.rs @@ -0,0 +1,22 @@ +struct Solution; + +impl Solution { + pub fn single_number(nums: Vec<i32>) -> i32 { + let mut n = nums; + n.sort(); + let mut tmp = vec![n[0]]; + for i in 1..n.len() { + if tmp.len() == 0 || tmp[tmp.len() - 1] != n[i] { + tmp.push(n[i]); + } else { + tmp.pop(); + } + } + tmp[0] + } +} + +fn main() { + let nums = vec![2,2,1]; + print!("{}", Solution::single_number(nums)); +} diff --git a/single_number2.c b/single_number2.c new file mode 100644 index 0000000..b170ad7 --- /dev/null +++ b/single_number2.c @@ -0,0 +1,30 @@ +// 137. Single Number II +#include <stdio.h> + +/* + * given an integer array 'nums' where every element appears three times except + * for one, which appears exactly once. find the single element and return it. + * you must implement a solution with a linear runtime complexity and use only + * constant extra space. + */ + +int singleNumber(int *nums, int nums_size) { + int ans = 0, sum; + for (int i = 0; i < 32; i++) { + long long mask = 1 << i; + sum = 0; + for (int j = 0; j < nums_size; j++) + if (mask & nums[j]) + sum++; + if (sum % 3) + ans |= mask; + } + return ans; +} + +int main() { + int n1[] = {2, 2, 3, 2}; + int n2[] = {0, 1, 0, 1, 0, 1, 99}; + printf("%d\n", singleNumber(n1, 4)); // expect: 3 + printf("%d\n", singleNumber(n2, 7)); // expect: 99 +} diff --git a/single_number2.cpp b/single_number2.cpp new file mode 100644 index 0000000..907fee0 --- /dev/null +++ b/single_number2.cpp @@ -0,0 +1,29 @@ +// 137. Single Number II +#include "leetcode.h" + +/* + * given an integer array 'nums' where every element appears three times except + * for one, which appears exactly once. find the single element and return it. + * you must implement a solution with a linear runtime complexity and use only + * constant extra space. + */ + +class Solution { +public: + int singleNumber(vector<int> &nums) { + unordered_map<int, int> um; + for (auto i : nums) + um[i]++; + for (auto i : um) + if (i.second == 1) + return i.first; + return -1; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {2, 2, 3, 2}, n2 = {0, 1, 0, 1, 0, 1, 99}; + printf("%d\n", obj.singleNumber(n1)); // expect: 3 + printf("%d\n", obj.singleNumber(n2)); // expect: 99 +} diff --git a/single_number3.c b/single_number3.c new file mode 100644 index 0000000..16a24bb --- /dev/null +++ b/single_number3.c @@ -0,0 +1,42 @@ +// 260. Single Number III +#include "leetcode.h" + +/* + * given an integer array 'nums' in which exactly two elements appear only once + * and all the otherelements appear exactly twice. find the two elements that + * appear only once. you can return the answer in any order. you must write an + * algorithm that runs linear runtime complexity and uses only constant extra + * space. + */ + +int *singleNumber(int *nums, int numsSize, int *returnSize) { + *returnSize = 2; + int *ans = (int *)calloc(2, sizeof(int)); + long long tmp = 0; + for (int i = 0; i < numsSize; i++) + tmp ^= nums[i]; + tmp &= -tmp; + for (int i = 0; i < numsSize; i++) + if (!(tmp & nums[i])) + ans[0] ^= nums[i]; + else + ans[1] ^= nums[i]; + return ans; +} + +int main() { + int n1[] = {1, 2, 1, 3, 2, 5}, n2[] = {-1, 0}, n3[] = {0, 1}, rs1, rs2, rs3; + int *sn1 = singleNumber(n1, ARRAY_SIZE(n1), &rs1); // expect: 3 5 + int *sn2 = singleNumber(n2, ARRAY_SIZE(n2), &rs2); // expect: -1 0 + int *sn3 = singleNumber(n3, ARRAY_SIZE(n3), &rs3); // expect: 1 0 + for (int i = 0; i < rs1; i++) + printf("%d ", sn1[i]); + printf("\n"); + for (int i = 0; i < rs2; i++) + printf("%d ", sn2[i]); + printf("\n"); + for (int i = 0; i < rs3; i++) + printf("%d ", sn3[i]); + printf("\n"); + free(sn1), free(sn2), free(sn3); +} diff --git a/single_number3.py b/single_number3.py new file mode 100644 index 0000000..2bd4ed2 --- /dev/null +++ b/single_number3.py @@ -0,0 +1,28 @@ +# 260. Single Number III + +""" +given an integer array 'nums' in which exactly two elements appear only once +and all the otherelements appear exactly twice. find the two elements that +appear only once. you can return the answer in any order. you must write an +algorithm that runs linear runtime complexity and uses only constant extra +space. +""" + + +class Solution(object): + def singleNumber(self, nums): + """ + :type nums: List[int] + :rtype: List[int] + """ + s = reduce(xor, nums) + nz = s & (s - 1) ^ s + n1 = reduce(xor, filter(lambda n: n & nz, nums)) + return (n1, s ^ n1) + + +if __name__ == "__main__": + obj = Solution() + print(obj.singleNumber([1, 2, 1, 3, 2, 5])) + print(obj.singleNumber([-1, 0])) + print(obj.singleNumber([0, 1])) diff --git a/single_product_array.c b/single_product_array.c new file mode 100644 index 0000000..b63ccd4 --- /dev/null +++ b/single_product_array.c @@ -0,0 +1,31 @@ +// 1822. Sign of the Product of an Array +#include <stdio.h> + +/* + * there is a function signFunc(x) that returns + * 1 if x is positive + * -1 if x is negative + * 0 if x is equal to 0 + * given an integer array 'nums', let 'product' be the product + * of all values in the array 'nums' return signFunc(product) + */ + +int arraySign(int *nums, int nums_size) { + int sign = 1; + for (int i = 0; i < nums_size; i++) { + if (!nums[i]) + return 0; + else if (nums[i] < 0) + sign = -sign; + } + return sign; +} + +int main() { + int n1[] = {-1, -2, -3, -4, 3, 2, 1}; + int n2[] = {1, 5, 0, 2, -3}; + int n3[] = {-1, 1, -1, 1, -1}; + printf("%d\n", arraySign(n1, 7)); // expect: 1 + printf("%d\n", arraySign(n2, 5)); // expect: 0 + printf("%d\n", arraySign(n3, 5)); // expect: -1 +} diff --git a/single_product_array.cpp b/single_product_array.cpp new file mode 100644 index 0000000..262bd0e --- /dev/null +++ b/single_product_array.cpp @@ -0,0 +1,35 @@ +// 1822. Sign of the Product of an Array +#include "leetcode.h" + +/* + * there is a function signFunc(x) that returns + * 1 if x is positive + * -1 if x is negative + * 0 if x is equal to 0 + * given an integer array 'nums', let 'product' be the product + * of all values in the array 'nums' return signFunc(product) + */ + +class Solution { +public: + int arraySign(vector<int> &nums) { + int sign = 1; + for (auto n : nums) { + if (!n) + return 0; + else if (n < 0) + sign = -sign; + } + return sign; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {-1, -2, -3, -4, 3, 2, 1}; + vector<int> n2 = {1, 5, 0, 2, -3}; + vector<int> n3 = {-1, 1, -1, 1, -1}; + printf("%d\n", obj.arraySign(n1)); // expect: 1 + printf("%d\n", obj.arraySign(n2)); // expect: 0 + printf("%d\n", obj.arraySign(n3)); // expect: -1 +} diff --git a/single_threaded_cpu.cpp b/single_threaded_cpu.cpp new file mode 100644 index 0000000..aaa3598 --- /dev/null +++ b/single_threaded_cpu.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> getOrder(vvd(int) & tasks) { + vector<int> ans, idx(tasks.size()); + priority_queue<pair<int, int>> pqp; + iota(begin(idx), end(idx), 0); + sort(begin(idx), end(idx), + [&](int i, int j) { return tasks[i][0] < tasks[j][0]; }); + for (long i = 0, time = 1; i < idx.size() || !pqp.empty();) { + for (; i < idx.size() && tasks[idx[i]][0] <= time; ++i) + pqp.push({-tasks[idx[i]][1], -idx[i]}); + if (!pqp.empty()) { + auto [procTime, j] = pqp.top(); + pqp.pop(); + time -= procTime; + ans.push_back(-j); + } else + time = tasks[idx[i]][0]; + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) tasks = {{1, 2}, {2, 4}, {3, 2}, {4, 1}}; + for (auto i : obj.getOrder(tasks)) + cout << i << ' '; // expect 0,2,3,1 +} diff --git a/single_threaded_cpu.rs b/single_threaded_cpu.rs new file mode 100644 index 0000000..4defcb7 --- /dev/null +++ b/single_threaded_cpu.rs @@ -0,0 +1,59 @@ +use std::collections::BinaryHeap; +use std::cmp::Ordering; +struct Solution; +#[derive(PartialEq, Eq, Copy, Clone)] +struct Task { + pub enqueue_time: i32, + pub processing_time: i32, + pub initial_idx: usize +} + +impl PartialOrd for Task { + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { + if other.processing_time == self.processing_time { + return Some(other.initial_idx.cmp(&self.initial_idx)); + } + Some(other.processing_time.cmp(&self.processing_time)) + } +} + +impl Ord for Task { + fn cmp(&self, other: &Self) -> Ordering { + if other.processing_time == self.processing_time { + return other.initial_idx.cmp(&self.initial_idx); + } + other.processing_time.cmp(&self.processing_time) + } +} + +impl Solution { + pub fn get_order(tasks: Vec<Vec<i32>>) -> Vec<i32> { + let mut tasks = tasks.into_iter().enumerate().map(|(idx, task)| { + Task { + enqueue_time: task[0], + processing_time: task[1], + initial_idx: idx + } + }).collect::<Vec<Task>>(); + let (mut output, mut current_time) = (vec![], 0); + let mut available_tasks: BinaryHeap<Task> = BinaryHeap::new(); + while tasks.len() > 0 || available_tasks.len() > 0 { + while tasks.len() > 0 && tasks[tasks.len() - 1].enqueue_time <= current_time { + let task = tasks.pop().unwrap(); + available_tasks.push(task); + } + if let Some(task) = available_tasks.pop() { + output.push(task.initial_idx as i32); + current_time += task.processing_time; + } else { + current_time = tasks[tasks.len() - 1].enqueue_time; + } + } + output + } +} + +fn main() { + let tasks = vec![vec![1,2],vec![2,4],vec![3,2],vec![4,1]]; + print!("{:?}", Solution::get_order(tasks)); +} diff --git a/skyline_problem.cpp b/skyline_problem.cpp new file mode 100644 index 0000000..1828978 --- /dev/null +++ b/skyline_problem.cpp @@ -0,0 +1,28 @@ +#include "leetcode.h" + +class Solution { +public: + vvd(int) getSkyline(vvd(int) & buildings) { + vvd(int) ans; + map<int, vector<pair<int, int>>> mvp; + for (auto &b : buildings) { + mvp[b[0]].push_back({b[2], 0}); + mvp[b[1]].push_back({b[2], 1}); + } + multiset<int> m; + for (auto &[pos, heights] : mvp) { + for (auto &[height, type] : heights) { + if (type == 0) + m.insert(height); + else + m.erase(m.find(height)); + } + int newHeight = m.empty() ? 0 : *m.begin(); + if (!ans.empty() && ans.back()[1] == newHeight) + continue; + else + ans.push_back(vector<int>({pos, newHeight})); + } + return ans; + } +}; diff --git a/sliding_window_max.c b/sliding_window_max.c new file mode 100644 index 0000000..f02cc3b --- /dev/null +++ b/sliding_window_max.c @@ -0,0 +1,87 @@ +// 239. Sliding Window Maximum +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array of integers 'nums', there is a sliding window of size 'k', + * which is moving from the very left of the array to the very right. you can + * only see the 'k' numbers in each window. each time the sliding window moves + * right by one position. return the max sliding window. + */ + +void pushQueue(int *queue, int *head, int *tail, int val) { + if (val <= queue[*tail - 1]) { + queue[*tail] = val; + *tail = *tail + 1; + return; + } + int left = *head, right = *tail - 1; + while (left < right) { + int mid = left + (right - left) / 2; + if (queue[mid] < val) + right = mid; + else + left = mid + 1; + } + queue[left] = val; + *tail = left + 1; +} +int *maxSlidingWindow(int *nums, int numsSize, int k, int *returnSize) { + int N = k + 1; + int n = numsSize; + int *ans = malloc((numsSize - k + 1) * sizeof(int)); + int *queue = malloc(n * sizeof(int)); + queue[0] = nums[0]; + int head = 0, tail = 1; + int i, j; + for (i = 1; i < k; i++) { + if (nums[i] <= queue[tail - 1]) { + queue[tail] = nums[i]; + tail++; + continue; + } + for (j = head; j < tail; j++) { + if (nums[i] > queue[j]) { + queue[j] = nums[i]; + tail = j + 1; + break; + } + } + if (j == tail) { + queue[tail] = nums[i]; + tail = tail + 1; + } + } + ans[0] = queue[0]; + int idx = 1; + for (int i = k; i < n; i++) { + if (nums[i] > queue[head]) { + queue[head] = nums[i]; + ans[idx] = queue[head]; + tail = head + 1; + } else { + pushQueue(queue, &head, &tail, nums[i]); + if (nums[i - k] == queue[head]) + head = head + 1; + ans[idx] = queue[head]; + } + idx++; + } + *returnSize = idx; + return ans; +} + +int main() { + int n1[] = {1, 3, -1, -3, 5, 3, 6, 7}, n2[] = {1}; + int ns1 = 8, ns2 = 1; + int k1 = 3, k2 = 1; + int rs1[] = {}, rs2[] = {}; + int *msw1 = maxSlidingWindow(n1, ns1, k1, rs1); + int *msw2 = maxSlidingWindow(n2, ns2, k2, rs2); + for (int i = 0; i < 6; i++) + printf("%d ", msw1[i]); // expect: 3,3,5,5,6,7 + printf("\n"); + for (int i = 0; i < 1; i++) + printf("%d ", msw2[i]); // expect: 1 + printf("\n"); +} diff --git a/sliding_window_max.cpp b/sliding_window_max.cpp new file mode 100644 index 0000000..8468604 --- /dev/null +++ b/sliding_window_max.cpp @@ -0,0 +1,38 @@ +// 239. Sliding Window Maximum +#include "leetcode.h" + +/* + * given an array of integers 'nums', there is a sliding window of size 'k', + * which is moving from the very left of the array to the very right. you can + * only see the 'k' numbers in each window. each time the sliding window moves + * right by one position. return the max sliding window. + */ + +class Solution { +public: + vector<int> maxSlidingWindow(vector<int> &nums, int k) { + deque<int> dq; + vector<int> ans; + for (int i = 0; i < nums.size(); i++) { + if (!dq.empty() && dq.front() == i - k) + dq.pop_front(); + while (!dq.empty() && nums[dq.back()] < nums[i]) + dq.pop_back(); + dq.push_back(i); + if (i >= k - 1) + ans.push_back(nums[dq.front()]); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 3, -1, -3, 5, 3, 6, 7}, n2 = {1}; + for (auto i : obj.maxSlidingWindow(n1, 3)) + printf("%d ", i); // expect: 3,3,5,5,6,7 + printf("\n"); + for (auto i : obj.maxSlidingWindow(n2, 1)) + printf("%d ", i); // expect: 1 + printf("\n"); +} diff --git a/smallest_num_set.c b/smallest_num_set.c new file mode 100644 index 0000000..dabe17e --- /dev/null +++ b/smallest_num_set.c @@ -0,0 +1,100 @@ +// 2336. Smallest Number in Infinite Set +#include <stdbool.h> +#include <stdlib.h> + +/* + * you have a set which contains all positive integers [1,2,3,...] + * implement the SmallestInfiniteSet class: + * - SmallestInfiniteSet() initialises the SmallestInfiniteSet + * object to contain all positive integers + * - int popSmallest() removes and returns the smallest integer + * contained in the infinite set + * - void addBack(int num) adds a positive integer num back into + * the infinite set, if it is not already in the infinite set + */ + +typedef struct { + int *heap; + bool *hash; + int heap_size; +} SmallestInfiniteSet; + +SmallestInfiniteSet *SmallestInfiniteSetCreate() { + SmallestInfiniteSet *res = malloc(sizeof(SmallestInfiniteSet)); + res->heap = malloc(1001 * sizeof(int)); + res->hash = malloc(1000 * sizeof(bool)); + for (int i = 0; i < 1000; i++) { + res->heap[i] = i + 1; + res->hash[i] = true; + } + res->heap_size = 1000; + return res; +} + +int SmallestInfiniteSetPopSmallest(SmallestInfiniteSet *obj) { + if (!obj->heap_size) + return -1; + int res = obj->heap[0]; + obj->hash[res - 1] = false; + obj->heap[0] = obj->heap[obj->heap_size - 1]; + obj->heap_size--; + int pos = 0, tmp; + while (pos < obj->heap_size) { + if ((2 * pos + 1) >= obj->heap_size) + break; + if (2 * pos + 1 == obj->heap_size - 1) { + if (obj->heap[pos] > obj->heap[2 * pos + 1]) { + tmp = obj->heap[pos]; + obj->heap[pos] = obj->heap[2 * pos + 1]; + obj->heap[2 * pos + 1] = tmp; + pos = 2 * pos + 1; + } + break; + } + if (obj->heap[pos] > obj->heap[2 * pos + 1] || + obj->heap[pos] > obj->heap[2 * pos + 1]) { + if (obj->heap[2 * pos + 1] <= obj->heap[2 * pos + 1]) { + tmp = obj->heap[2 * pos + 1]; + obj->heap[2 * pos + 1] = obj->heap[pos]; + obj->heap[pos] = tmp; + pos = 2 * pos + 1; + } else { + tmp = obj->heap[2 * pos + 2]; + obj->heap[2 * pos + 2] = obj->heap[pos]; + obj->heap[pos] = tmp; + pos = 2 * pos + 2; + } + } else + break; + } + return res; +} + +void SmallestInfiniteSetAddBack(SmallestInfiniteSet *obj, int num) { + if (obj->hash[num - 1]) + return; + else + obj->hash[num - 1] = true; + obj->heap[obj->heap_size] = num; + int pos = obj->heap_size; + obj->heap_size++; + int tmp; + while (pos && (obj->heap[pos] < obj->heap[(pos - 1) / 2])) { + tmp = obj->heap[(pos - 1) / 2]; + obj->heap[(pos - 1) / 2] = obj->heap[pos]; + obj->heap[pos] = tmp; + pos = (pos - 1) / 2; + } +} + +void SmallestInfiniteSetFree(SmallestInfiniteSet *obj) { + free(obj->heap); + free(obj); +} + +int main() { + SmallestInfiniteSet *obj = SmallestInfiniteSetCreate(); + int param_1 = SmallestInfiniteSetPopSmallest(obj); + SmallestInfiniteSetAddBack(obj, 2); + SmallestInfiniteSetFree(obj); +} diff --git a/smallest_num_set.cpp b/smallest_num_set.cpp new file mode 100644 index 0000000..f05147b --- /dev/null +++ b/smallest_num_set.cpp @@ -0,0 +1,45 @@ +// 2336. Smallest Number in Infinite Set +#include "leetcode.h" + +/* + * you have a set which contains all positive integers [1,2,3,...] + * implement the SmallestInfiniteSet class: + * - SmallestInfiniteSet() initialises the SmallestInfiniteSet + * object to contain all positive integers + * - int popSmallest() removes and returns the smallest integer + * contained in the infinite set + * - void addBack(int num) adds a positive integer num back into + * the infinite set, if it is not already in the infinite set + */ + +class SmallestInfiniteSet { +public: + int k = 1; + unordered_map<int, int> um; + SmallestInfiniteSet() { + for (int i = 1; i <= 1000; i++) + um[i] = i; + } + int popSmallest() { + int d = um[k]; + um.erase(k); + for (int i = k + 1; i <= 1000; i++) { + if (um.find(i) != um.end()) { + k = i; + break; + } + } + return d; + } + void addBack(int num) { + um[num] = num; + if (num < k) + k = num; + } +}; + +int main() { + SmallestInfiniteSet *obj = new SmallestInfiniteSet(); + int param_1 = obj->popSmallest(); + obj->addBack(2); +} diff --git a/smallest_string_leaf.c b/smallest_string_leaf.c new file mode 100644 index 0000000..e557a97 --- /dev/null +++ b/smallest_string_leaf.c @@ -0,0 +1,86 @@ +// 988. Smallest String Starting From Leaf +#include "leetcode.h" + +/* + * given the 'root' of a binary tree where each node has a value in the range + * '[0, 25]' representing letters 'a' to 'z'. return the lexicographically + * smallest string that starts at a leaf of this tree and ends at the root. as a + * reminder, any shorter prefix of a string is lexicographically smaller. a leaf + * of a node is a node that has no children. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +struct TreeNode *createNode(int val) { + struct TreeNode *new_node = + (struct TreeNode *)malloc(sizeof(struct TreeNode)); + new_node->val = val; + new_node->left = NULL; + new_node->right = NULL; + return new_node; +} + +int depth(struct TreeNode *root) { + return !root ? 0 : fmax(depth(root->left), depth(root->right)) + 1; +} + +void process(struct TreeNode *root, int *small, char *res, char *data, + int idx) { + if (!root) + return; + data[idx] = root->val + 'a'; + idx++; + if (!root->left && !root->right) { + data[idx] = '\0'; + if (root->val < *small) { + strcpy(res, data); + *small = root->val; + } else if (root->val == *small) { + int l_a = strlen(res) - 1, l_d = strlen(data) - 1; + while (l_a >= 0 && l_d >= 0) { + if (data[l_d] < res[l_a]) { + strcpy(res, data); + break; + } + if (data[l_d] > res[l_d]) + break; + if (!l_d) { + strcpy(res, data); + break; + } + l_a--, l_d--; + } + } + } + process(root->left, small, res, data, idx); + process(root->right, small, res, data, idx); +} + +char *smallestFromLeaf(struct TreeNode *root) { + int d = depth(root), small = 27; + char *data = calloc(d + 1, sizeof(char)); + char *ans = calloc(d + 1, sizeof(char)); + process(root, &small, ans, data, 0); + int n = strlen(ans); + for (int i = 0; i < n / 2; i++) { + char tmp = ans[i]; + ans[i] = ans[n - i - 1]; + ans[n - i - 1] = tmp; + } + return ans; +} + +int main() { + struct TreeNode *root = createNode(0); + root->left = createNode(1); + root->right = createNode(2); + root->left->left = createNode(3); + root->left->right = createNode(4); + root->right->left = createNode(3); + root->right->right = createNode(4); + printf("%s\n", smallestFromLeaf(root)); +} diff --git a/smallest_string_leaf.py b/smallest_string_leaf.py new file mode 100644 index 0000000..184f1ca --- /dev/null +++ b/smallest_string_leaf.py @@ -0,0 +1,43 @@ +# 988. Smallest String Starting From Leaf + +""" +given the 'root' of a binary tree where each node has a value in the range +'[0, 25]' representing letters 'a' to 'z'. return the lexicographically +smallest string that starts at a leaf of this tree and ends at the root. as a +reminder, any shorter prefix of a string is lexicographically smaller. a leaf +of a node is a node that has no children. +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def smallestFromLeaf(self, root): + """ + :type root: TreeNode + :rtype: str + """ + + def dfs(root, s): + s = s + chr(ord("a") + root.val) + if not root.left and not root.right: + if res[0] == None: + res[0] = s[::-1] + else: + res[0] = min(res[0], s[::-1]) + if root.left: + dfs(root.left, s) + if root.right: + dfs(root.right, s) + + if not root: + return "" + ans = [None] + dfs(root, "") + return ans[0] diff --git a/smallest_string_swaps.cpp b/smallest_string_swaps.cpp new file mode 100644 index 0000000..c521309 --- /dev/null +++ b/smallest_string_swaps.cpp @@ -0,0 +1,55 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> parent; + string smallestStringWithSwaps(string s, vector<vector<int>> &pairs) { + parent.resize(s.length()); + map<int, set<int>> obj; + set<int> idx; + string ans = s; + for (int i = 0; i < parent.size(); i++) + parent[i] = i; + for (int i = 0; i < pairs.size(); i++) { + int u = pairs[i][0]; + int v = pairs[i][1]; + int fx = findParent(u); + int fy = findParent(v); + if (fx != fy) + parent[fy] = fx; + } + for (int i = 0; i < pairs.size(); i++) { + int u = pairs[i][0]; + int v = pairs[i][1]; + int fx = findParent(u); + obj[fx].insert(u); + obj[fx].insert(v); + } + for (auto it = obj.begin(); it != obj.end(); it++) { + idx = it->second; + vector<pair<char, int>> t; + auto index = idx.begin(); + for (index = idx.begin(); index != idx.end(); index++) { + int pos = *index; + char ch = s[pos]; + t.push_back({ch, pos}); + } + sort(t.begin(), t.end()); + index = idx.begin(); + for (int i = 0; i < t.size(); i++) { + ans[*index] = t[i].first; + index++; + } + } + return ans; + } + +private: + int findParent(int n) { + if (parent[n] == n) + return n; + return parent[n] = findParent(parent[n]); + } +}; + +int main() {} diff --git a/smallest_sufficient_team.cpp b/smallest_sufficient_team.cpp new file mode 100644 index 0000000..473e218 --- /dev/null +++ b/smallest_sufficient_team.cpp @@ -0,0 +1,61 @@ +// 1125. Smallest Sufficient Team +#include "leetcode.h" + +/* + * in a project, you have a list of required required skills ' req_skills' and a + * list of people. the i'th person 'people[i]' contains a list of skills that + * the person has. consider a sufficient team: a set of people such that for + * every required skill in 'req_skills', there is at least one person in the + * tema who has that skill. we can represent these teams by the index of each + * person. return any sufficient team of the smallest possible size, represented + * by the index of each person. you may return the answer in any order. it is + * guaranteed an answer exists + */ + +class Solution { +public: + vector<int> smallestSufficientTeam(vector<string> &req_skills, + vvd(string) & people) { + int n = req_skills.size(); + unordered_map<int, vector<int>> ans; + ans.reserve(1 << n); + ans[0] = {}; + unordered_map<string, int> skill_map; + for (int i = 0; i < n; i++) + skill_map[req_skills[i]] = i; + for (int i = 0; i < people.size(); i++) { + int curr = 0; + for (int j = 0; j < people[i].size(); j++) + curr |= 1 << skill_map[people[i][j]]; + for (auto k = ans.begin(); k != ans.end(); k++) { + int com = k->first | curr; + if (ans.find(com) == ans.end() || + ans[com].size() > 1 + ans[k->first].size()) { + ans[com] = k->second; + ans[com].push_back(i); + } + } + } + return ans[(1 << n) - 1]; + } +}; + +int main() { + Solution obj; + vector<string> rs1 = {"java", "nodejs", "reactjs"}; + vvd(string) p1 = {{"java"}, {"nodejs"}, {"nodejs", "reactjs"}}; + vector<string> rs2 = {"algorithms", "math", "java", + "reactjs", "csharp", "aws"}; + vvd(string) p2 = {{"algorithms", "math", "java"}, + {"algorithms", "math", "reactjs"}, + {"java", "csharp", "aws"}, + {"reactjs", "csharp"}, + {"csharp", "math"}, + {"aws", "java"}}; + for (auto i : obj.smallestSufficientTeam(rs1, p1)) + printf("%d ", i); // expect: 0 2 + printf("\n"); + for (auto i : obj.smallestSufficientTeam(rs2, p2)) + printf("%d ", i); // expect: 1 2 + printf("\n"); +} diff --git a/snakes_ladders.cpp b/snakes_ladders.cpp new file mode 100644 index 0000000..32f870a --- /dev/null +++ b/snakes_ladders.cpp @@ -0,0 +1,47 @@ +// 909. Snakes and Ladders +#include "leetcode.h" + +typedef pair<int, int> pii; +class Solution { +public: + int snakesAndLadders(vvd(int) & board) { + int rows = board.size(), cols = board[0].size(); + int target = rows * cols, r, c, p; + vector<int> visited(rows * cols + 1); // cells on board starting from 1 + priority_queue<pii, vector<pii>, greater<pii>> pq; + pq.push(make_pair(0, 1)); + visited[1] = true; + while (pq.size()) { + auto stepPos = pq.top(); + pq.pop(); + int s = stepPos.first / 1000 + 1; + for (int i = 1; i <= 6; i++) { + auto p = stepPos.second + i; + if (visited[p]) + continue; + visited[p] = true; + r = rows - (p - 1) / cols - 1; + c = (p - 1) % cols; + if ((rows - r - 1) % 2) + c = cols - c - 1; + int ladder = board[r][c]; + if (ladder > 0 && ladder <= target) + p = ladder; + if (p == target) + return s; + pq.push(make_pair(s * 1000 + 500 - p, p)); + } + } + return -1; + } +}; + +int main() { + Solution obj; + vvd(int) board1 = {{-1, -1, -1, -1, -1, -1}, {-1, -1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -1, -1}, {-1, 35, -1, -1, 13, -1}, + {-1, -1, -1, -1, -1, -1}, {-1, 15, -1, -1, -1, -1}}; + vvd(int) board2 = {{-1, -1}, {-1, 3}}; + cout << obj.snakesAndLadders(board1) << endl; // expect: 4 + cout << obj.snakesAndLadders(board2) << endl; // expect: 1 +} diff --git a/snapshot_array.c b/snapshot_array.c new file mode 100644 index 0000000..9e0da2a --- /dev/null +++ b/snapshot_array.c @@ -0,0 +1,77 @@ +// 1146. Snapshot Array +#include <stdio.h> +#include <stdlib.h> + +/* + * implement a 'SnapshotArray' class that supports the following interface + * - 'SnapshotArray(int length)' initialises an array-like data structure with + * the given length. initially, each element equals zero. + * - 'void set(index, val)' sets the element at the given 'index' to be equal to + * 'val' + * - 'int snap()' takes a snapshot of the array and retusn the 'snap_id': the + * total number of times we called 'snap()' minus 1 + * - 'int get(index, snap_id)' returns the value at the given 'index', at the + * time we took the snapshot with the given 'snap_id' + */ + +#define SIZE 50000 + +struct v { + int v; + int i; + struct v *n; +}; + +typedef struct { + struct v *vl[SIZE]; + int i; +} SnapshotArray; + +SnapshotArray *snapshotArrayCreate(int length) { + return calloc(1, sizeof(SnapshotArray)); +} + +void snapshotArraySet(SnapshotArray *obj, int index, int val) { + SnapshotArray *s = obj; + struct v *v = s->vl[s->i], *p = NULL; + for (; v && index > v->i; p = v, v = v->n) + ; + if (v && index == v->i) + v->v = val; + else { + struct v *n = calloc(1, sizeof(*n)); + n->v = val; + n->i = index; + n->n = v; + p ? p->n = n : (s->vl[s->i] = n); + } +} + +int snapshotArraySnap(SnapshotArray *obj) { + SnapshotArray *s = obj; + struct v *h = s->vl[s->i++]; + for (struct v **p = &s->vl[s->i]; h; h = h->n) { + (*p = calloc(1, sizeof(**p)))->v = h->v; + (*p)->i = h->i; + p = &(*p)->n; + } + return s->i - 1; +} + +int snapshotArrayGet(SnapshotArray *obj, int index, int snap_id) { + SnapshotArray *s = obj; + struct v *h; + for (h = s->vl[snap_id]; h && h->i < index; h = h->n) + ; + return h && h->i == index ? h->v : 0; +} + +void snapshotArrayFree(SnapshotArray *obj) { free(obj); } + +int main() { + SnapshotArray *obj = snapshotArrayCreate(3); + snapshotArraySet(obj, 0, 5); + printf("%d\n", snapshotArraySnap(obj)); // expect: 0 + snapshotArraySet(obj, 0, 6); + printf("%d\n", snapshotArrayGet(obj, 0, 0)); // expect: 5 +} diff --git a/snapshot_array.cpp b/snapshot_array.cpp new file mode 100644 index 0000000..42d165b --- /dev/null +++ b/snapshot_array.cpp @@ -0,0 +1,42 @@ +// 1146. Snapshot Array +#include "leetcode.h" + +/* + * implement a 'SnapshotArray' class that supports the following interface + * - 'SnapshotArray(int length)' initialises an array-like data structure with + * the given length. initially, each element equals zero. + * - 'void set(index, val)' sets the element at the given 'index' to be equal to + * 'val' + * - 'int snap()' takes a snapshot of the array and retusn the 'snap_id': the + * total number of times we called 'snap()' minus 1 + * - 'int get(index, snap_id)' returns the value at the given 'index', at the + * time we took the snapshot with the given 'snap_id' + */ + +class SnapshotArray { + int curr_snap = 0; + vector<vector<pair<int, int>>> vvp; + +public: + SnapshotArray(int length) { vvp = vector<vector<pair<int, int>>>(length); } + void set(int index, int val) { + if (vvp[index].empty() || vvp[index].back().first != curr_snap) + vvp[index].push_back({curr_snap, val}); + else + vvp[index].back().second = val; + } + int snap() { return curr_snap++; } + int get(int index, int snap_id) { + auto i = upper_bound(begin(vvp[index]), end(vvp[index]), + pair<int, int>(snap_id, INT_MAX)); + return i == begin(vvp[index]) ? 0 : prev(i)->second; + } +}; + +int main() { + SnapshotArray *obj = new SnapshotArray(3); + obj->set(0, 5); + printf("%d\n", obj->snap()); // expect: 0 + obj->set(0, 6); + printf("%d\n", obj->get(0, 0)); // expect: 5 +} diff --git a/sort_array.c b/sort_array.c new file mode 100644 index 0000000..5bc491a --- /dev/null +++ b/sort_array.c @@ -0,0 +1,35 @@ +// 912. Sort an Array +#include <stdio.h> +#include <stdlib.h> + +void quickSort(int *nums, int start, int end) { + if (start >= end) + return; + int tmp = nums[start]; + int i = start, k = end; + while (i < k) { + for (k; nums[k] >= tmp && k > i; k--) + ; + nums[i] = nums[k]; + nums[k] = tmp; + for (i; nums[i] <= tmp && i < k; i++) + ; + nums[k] = nums[i]; + nums[i] = tmp; + } + quickSort(nums, start, i - 1); + quickSort(nums, k + 1, end); +} + +int *sortArray(int *nums, int numsSize, int *returnSize) { + quickSort(nums, 0, numsSize - 1); + *returnSize = numsSize; + return nums; +} + +int main() { + int n1[] = {5, 2, 3, 1}, ns1 = 4, rs1[] = {4}; + int n2[] = {5, 1, 1, 2, 0, 0}, ns2 = 6, rs2[] = {6}; + printf("%p\n", sortArray(n1, ns1, rs1)); + printf("%p\n", sortArray(n2, ns2, rs2)); +} diff --git a/sort_array.cpp b/sort_array.cpp new file mode 100644 index 0000000..655726d --- /dev/null +++ b/sort_array.cpp @@ -0,0 +1,27 @@ +// 912. Sort an Array +#include "leetcode.h" +#include <vector> + +class Solution { +public: + vector<int> sortArray(vector<int> &nums) { + int end_idx, curr_idx, n = nums.size(); + if (n <= 1) + return {}; + for (int i = n - 1; i; i--) + for (int j = 0; j < i; j++) + if (nums[j] > nums[j + 1]) + swap(nums[j], nums[j + 1]); + return nums; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {5, 2, 3, 1}, n2 = {5, 1, 1, 2, 0, 0}; + for (auto i : obj.sortArray(n1)) + cout << i << ' '; // expect: 1,2,3,5 + cout << endl; + for (auto i : obj.sortArray(n2)) + cout << i << ' '; // expect: 0,0,1,1,2,5 +} diff --git a/sort_array_parity.c b/sort_array_parity.c new file mode 100644 index 0000000..5e22e51 --- /dev/null +++ b/sort_array_parity.c @@ -0,0 +1,34 @@ +// 905. Sort Array By Parity +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array 'nums', move all the even integers at the beginning of + * the array followed by all the odd integers. return any array that satisfies + * this condition + */ + +int *sortArrayByParity(int *nums, int nums_size, int *return_size) { + int left = 0, right = nums_size - 1; + int *ans = (int *)malloc(sizeof(int) * nums_size); + *return_size = nums_size; + for (int i = 0; i < nums_size; i++) { + if (!(nums[i] % 2)) + ans[left++] = nums[i]; + else + ans[right--] = nums[i]; + } + return ans; +} + +int main() { + int n1[] = {3, 1, 2, 4}, n2[] = {0}; + int *sabp1 = sortArrayByParity(n1, 4, NULL); + int *sabp2 = sortArrayByParity(n2, 1, NULL); + for (int i = 0; i < 4; i++) + printf("%d ", sabp1[i]); // expect: 2 4 3 1 + printf("\n"); + for (int i = 0; i < 1; i++) + printf("%d ", sabp2[i]); // expect: 0 + printf("\n"); +} diff --git a/sort_array_parity.cpp b/sort_array_parity.cpp new file mode 100644 index 0000000..33f02b1 --- /dev/null +++ b/sort_array_parity.cpp @@ -0,0 +1,46 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> sortArrayByParity(vector<int> &nums) { + /* + * important to assign vector values first: + * vector... var(size, vals) + */ + vector<int> ans(nums.size(), 0); + + /* + * start at first element (0) + * end at "last" element minus 1 + * because arrays initialize at 0 + */ + int start = 0, end = nums.size() - 1; + + for (int i = 0; i < nums.size(); i++) { + if (nums[i] % 2 == 1) + /* + * odd + * assign "last" array value to current nums value + * and incrementally decrease end when necessary + */ + ans[end--] = nums[i]; + else + /* + * even + * assign "first" array value to current nums value + * and incrementally increase start when necessary + */ + ans[start++] = nums[i]; + } + return ans; + } +}; + +int main() { + vector<int> nums = {3, 1, 2, 4}; + Solution obj; + for (int i = 0; i < nums.size(); i++) + cout << nums[i] << ' '; + cout << endl; + obj.sortArrayByParity(nums); +} diff --git a/sort_array_parity.py b/sort_array_parity.py new file mode 100644 index 0000000..4e318fd --- /dev/null +++ b/sort_array_parity.py @@ -0,0 +1,16 @@ +# 905. Sort Array By Parity + +""" +given an integer array 'nums', move all the even integers at the beginning of +the array followed by all the odd integers. return any array that satisfies +this condition +""" + +class Solution(object): + def sortArrayByParity(self, nums): + left = 0 + for i in range(len(nums)): + if nums[i] % 2 == 0: + nums[left], nums[i] = nums[i], nums[left] + left += 1 + return nums diff --git a/sort_char_freq.c b/sort_char_freq.c new file mode 100644 index 0000000..471debc --- /dev/null +++ b/sort_char_freq.c @@ -0,0 +1,38 @@ +// 451. Sort Characters By Frequency +#include "leetcode.h" + +/* + * given a string 's', sort it in decreasing order based on the frequency of the + * characters. the frequenc of a character is the number of times itappears in + * the string. return the sorted string. if there are multiple answers, return + * any of them + */ + +int times[265]; + +int cmp(const void *a, const void *b) { + return times[*(char *)b] - times[*(char *)a]; +} + +char *frequencySort(char *s) { + char letters[256]; + int i, j, k, l_num; + memset(times, 0, sizeof(times)); + for (i = l_num = 0; s[i] != '\0'; i++) + if (!times[s[i]]++) + letters[l_num++] = s[i]; + qsort(letters, l_num, sizeof(char), cmp); + char *ans = malloc(sizeof(char) * (i + 1)); + for (j = k = 0; j < l_num; j++) + for (i = 0; i < times[letters[j]]; i++) + ans[k++] = letters[j]; + ans[k] = '\0'; + return ans; +} + +int main() { + char *s1 = "tree", *s2 = "cccaaa", *s3 = "Aabb"; + printf("%s\n", frequencySort(s1)); // expect: eert + printf("%s\n", frequencySort(s2)); // expect: aaaccc + printf("%s\n", frequencySort(s3)); // expect: bbAa +} diff --git a/sort_char_freq.cpp b/sort_char_freq.cpp new file mode 100644 index 0000000..ea7d8af --- /dev/null +++ b/sort_char_freq.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + string frequencySort(string s) { + unordered_map<char, int> freq; + for (auto a : s) + freq[a]++; + priority_queue<pair<int, char>> pqp; + for (auto [a, f] : freq) + pqp.push({f, a}); + string ans; + pair<int, char> curr; + while (!pqp.empty()) { + curr = pqp.top(); + pqp.pop(); + ans += string(curr.first, curr.second); + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.frequencySort("tree"); +} diff --git a/sort_char_freq.py b/sort_char_freq.py new file mode 100644 index 0000000..ac37310 --- /dev/null +++ b/sort_char_freq.py @@ -0,0 +1,27 @@ +# 451. Sort Characters By Frequency + +""" +given a string 's', sort it in decreasing order based on the frequency of the +characters. the frequenc of a character is the number of times itappears in +the string. return the sorted string. if there are multiple answers, return +any of them +""" + + +class Solution(object): + def frequencySort(self, s): + """ + :type s: str + :rtype: str + """ + cnt = Counter(s) + s = list(s) + s.sort(key=lambda x: (-cnt[x], x)) + return "".join(s) + + +if __name__ == "__main__": + obj = Solution() + print(obj.frequencySort("tree")) + print(obj.frequencySort("cccaaa")) + print(obj.frequencySort("Aabb")) diff --git a/sort_char_freq.rs b/sort_char_freq.rs new file mode 100644 index 0000000..a9d0e13 --- /dev/null +++ b/sort_char_freq.rs @@ -0,0 +1,16 @@ +struct Solution; + +impl Solution { + pub fn frequency_sort(s: String) -> String { + let mut map = std::collections::HashMap::with_capacity(26 * 2); + s.chars().for_each(|b| * map.entry(b).or_insert(0) += 1); + let mut v = map.into_iter().map(|(c, n)| (c, n)).collect::<Vec<_>>(); + v.sort_unstable_by_key(|pair| - pair.1); + v.into_iter().flat_map(|(c, n)| vec![c; n as usize]).collect() + } +} + +fn main() { + let s = String::from("tree"); + print!("{}", Solution::frequency_sort(s)); +} diff --git a/sort_colours.c b/sort_colours.c new file mode 100644 index 0000000..f48230e --- /dev/null +++ b/sort_colours.c @@ -0,0 +1,42 @@ +// 75. Sort Colors +#include "leetcode.h" + +/* + * given an array 'nums' with 'n' objects coloured red, white, or blue, sort + * them in place so that objects of the same colour are adjacent with the + * colours in the order red, white and blue. we will use the integer 0,1,2 to + * represent the colour red, white, and blue respecitvely. you must solve this + * problem without the library's sort function. + */ + +void sortColors(int *nums, int numsSize) { + int two_ptr = numsSize - 1, zero_ptr = 0, one_ptr = 0; + while (one_ptr <= two_ptr) { + if (!nums[one_ptr]) { + int tmp = nums[zero_ptr]; + nums[zero_ptr] = nums[one_ptr]; + nums[one_ptr] = tmp; + one_ptr++; + zero_ptr++; + } else if (nums[one_ptr] == 1) + one_ptr++; + else { + int tmp = nums[two_ptr]; + nums[two_ptr] = nums[one_ptr]; + nums[one_ptr] = tmp; + two_ptr--; + } + } +} + +int main() { + int n1[] = {2, 0, 2, 1, 1, 0}, n2[] = {2, 0, 1}; + sortColors(n1, ARRAY_SIZE(n1)); + sortColors(n2, ARRAY_SIZE(n2)); + for (int i = 0; i < ARRAY_SIZE(n1); i++) + printf("%d ", n1[i]); + printf("\n"); + for (int i = 0; i < ARRAY_SIZE(n2); i++) + printf("%d ", n2[i]); + printf("\n"); +} diff --git a/sort_colours.py b/sort_colours.py new file mode 100644 index 0000000..229af0f --- /dev/null +++ b/sort_colours.py @@ -0,0 +1,39 @@ +# 75. Sort Colors + +""" +given an array 'nums' with 'n' objects coloured red, white, or blue, sort +them in place so that objects of the same colour are adjacent with the +colours in the order red, white and blue. we will use the integer 0,1,2 to +represent the colour red, white, and blue respecitvely. you must solve this +problem without the library's sort function. +""" + + +class Solution(object): + def sortColors(self, nums): + """ + :type nums: List[int] + :rtype: None Do not return anything, modify nums in-place instead. + """ + red, white, blue = 0, 0, len(nums) - 1 + + while white <= blue: + if nums[white] == 0: + nums[red], nums[white] = nums[white], nums[red] + white += 1 + red += 1 + elif nums[white] == 1: + white += 1 + else: + nums[white], nums[blue] = nums[blue], nums[white] + blue -= 1 + + +if __name__ == "__main__": + obj = Solution() + n1 = [2, 0, 2, 1, 1, 0] + n2 = [2, 0, 1] + obj.sortColors(n1) + obj.sortColors(n2) + print(n1) + print(n2) diff --git a/sort_int_1bits.c b/sort_int_1bits.c new file mode 100644 index 0000000..0e4ae05 --- /dev/null +++ b/sort_int_1bits.c @@ -0,0 +1,57 @@ +// 1356. Sort Integers by The Number of 1 Bits +#include "leetcode.h" + +/* + * given an integer array 'arr', sort the integers in the array in ascending + * order by the number of 1's in their binary representation and in case of two + * or more integers have the same number of 1's, you have to sort them in + * ascending order. return the array after sorting it. + */ + +struct pair { + int val; + int cnt; +}; + +int cmp(const void *a, const void *b) { + const struct pair pa = *(const struct pair *)a; + const struct pair pb = *(const struct pair *)b; + return pa.cnt == pb.cnt ? pa.val - pb.val : pa.cnt - pb.cnt; +} + +int find(int a) { + int res = 0; + while (a) { + res += a % 2; + a /= 2; + } + return res; +} + +int *sortByBits(int *arr, int arr_size, int *return_size) { + *return_size = arr_size; + struct pair *p = (struct pair *)malloc(sizeof(struct pair) * arr_size); + for (int i = 0; i < arr_size; i++) { + p[i].val = arr[i]; + p[i].cnt = find(arr[i]); + } + qsort(p, arr_size, sizeof(struct pair), cmp); + for (int i = 0; i < arr_size; i++) + arr[i] = p[i].val; + free(p); + return arr; +} + +int main() { + int a1[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}, + a2[] = {1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1}; + int rs1[] = {}, rs2[] = {}; + int *sbb1 = sortByBits(a1, ARRAY_SIZE(a1), rs1); + int *sbb2 = sortByBits(a2, ARRAY_SIZE(a2), rs2); + for (int i = 0; i < 8; i++) + printf("%d ", sbb1[i]); // expect: 0,1,2,4,8,3,5,6,7 + printf("\n"); + for (int i = 0; i < 11; i++) + printf("%d ", sbb2[i]); // expect: 1,2,4,8,16,32,64,128,256,512,1024 + printf("\n"); +} diff --git a/sort_int_1bits.py b/sort_int_1bits.py new file mode 100644 index 0000000..861b388 --- /dev/null +++ b/sort_int_1bits.py @@ -0,0 +1,33 @@ +# 1356. Sort Integers by The Number of 1 Bits + +""" +given an integer array 'arr', sort the integers in the array in ascending +order by the number of 1's in their binary representation and in case of two +or more integers have the same number of 1's, you have to sort them in +ascending order. return the array after sorting it. +""" + + +class Solution(object): + def sortByBits(self, arr): + n = len(arr) + ans = [0] * n + for i in range(n): + ans[i] = self.count_bit(arr[i]) * 10001 + arr[i] + ans.sort() + for i in range(n): + ans[i] %= 10001 + return ans + + def count_bit(self, n): + res = 0 + while n != 0: + res += n & 1 + n >>= 1 + return res + + +if __name__ == "__main__": + obj = Solution() + print(obj.sortByBits([0, 1, 2, 3, 4, 5, 6, 7, 8])) + print(obj.sortByBits([1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1])) diff --git a/sort_items_dependencies.c b/sort_items_dependencies.c new file mode 100644 index 0000000..e8a03a6 --- /dev/null +++ b/sort_items_dependencies.c @@ -0,0 +1,134 @@ +// 1203. Sort Items by Groups Respecting Dependencies +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * there are 'n' items in each belonging to zero or one of 'm' groups where + * 'group[i]' is the group that the i'th item beglons to and it's equal to '-1' + * if the i'th item beglongs to no group. the items and the groups are zero + * indexed. a group can have no item belonging to it. return a sorted list of + * the items such that + * - the items that belong to the same group are next to each other in the + * sorted list + * - there are some relations between these items where 'beforeItems[i]' is a + * list containing all the items that should come before the i'th item in the + * sorted array (to the left of the i'th item) return any solution if there is + * more than one solution and return an empty list if there is no solution. + */ + +typedef enum { + UnVisited, + Exploring, + Visited, +} Status; + +typedef struct Node_t { + Status status; + int id; + bool isVertex; + struct AdjNode_t *next; + struct AdjNode_t *adj; +} Node; + +typedef struct AdjNode_t { + Node *data; + struct AdjNode_t *next; +} AdjNode; + +void append_adj(Node *head, Node *data) { + AdjNode *adj = head->adj; + if (adj) { + while (adj->next) + adj = adj->next; + adj->next = malloc(sizeof(AdjNode)); + memset(adj->next, 0, sizeof(AdjNode)); + adj->next->data = data; + } else { + head->adj = malloc(sizeof(AdjNode)); + memset(head->adj, 0, sizeof(AdjNode)); + head->adj->data = data; + } + return; +} + +void append_next(Node *head, Node *data) { + AdjNode *node = (AdjNode *)head->next; + if (node) { + while (node->next) + node = node->next; + node->next = malloc(sizeof(AdjNode)); + memset(node->next, 0, sizeof(AdjNode)); + node->next->data = data; + } else { + head->next = malloc(sizeof(AdjNode)); + memset(head->next, 0, sizeof(AdjNode)); + head->next->data = data; + } + return; +} + +int N = 0; // return size +int *R = 0; // return array + +bool dfs(Node *node) { + if (node == 0 || node->status == Visited) + return true; + else if (node->status == Exploring) + return false; + node->status = Exploring; + + AdjNode *next = node->next; + while (next) { + if (!dfs(next->data)) + return false; + next = next->next; + } + if (!node->isVertex) { + AdjNode *adj = node->adj; + while (adj) { + if (!dfs(adj->data)) + return false; + adj = adj->next; + } + } + if (node->isVertex) + R[--N] = node->id; + node->status = Visited; + return true; +} + +int *sortItems(int n, int m, int *group, int groupSize, int **beforeItems, + int beforeItemsSize, int *beforeItemsColSize, int *returnSize) { + R = malloc(sizeof(int) * n); + N = n; + Node items[n]; + memset(items, 0, sizeof(Node) * n); + for (int i = 0; i < n; i++) { + items[i].id = i; + items[i].isVertex = true; + if (group[i] == -1) + group[i] = m++; + } + Node groupheads[m]; + memset(groupheads, 0, sizeof(Node) * m); + for (int i = 0; i < n; i++) { + append_adj(&(groupheads[group[i]]), &(items[i])); + for (int j = 0; j < beforeItemsColSize[i]; j++) { + int before = beforeItems[i][j]; + if (group[before] == group[i]) + append_next(&(items[before]), &(items[i])); + else + append_next(&(groupheads[group[before]]), &(groupheads[group[i]])); + } + } + for (int i = 0; i < m; i++) + if (!dfs(&(groupheads[i]))) { + printf("\ncycle detected...\n"); + *returnSize = 0; + return 0; + } + *returnSize = n; + return R; +} diff --git a/sort_items_dependencies.cpp b/sort_items_dependencies.cpp new file mode 100644 index 0000000..0139659 --- /dev/null +++ b/sort_items_dependencies.cpp @@ -0,0 +1,74 @@ +// 1203. Sort Items by Groups Respecting Dependencies +#include "leetcode.h" + +/* + * there are 'n' items in each belonging to zero or one of 'm' groups where + * 'group[i]' is the group that the i'th item beglons to and it's equal to '-1' + * if the i'th item beglongs to no group. the items and the groups are zero + * indexed. a group can have no item belonging to it. return a sorted list of + * the items such that + * - the items that belong to the same group are next to each other in the + * sorted list + * - there are some relations between these items where 'beforeItems[i]' is a + * list containing all the items that should come before the i'th item in the + * sorted array (to the left of the i'th item) return any solution if there is + * more than one solution and return an empty list if there is no solution. + */ + +class Solution { + bool top_sort(vector<unordered_set<int>> &al, int i, vector<int> &res, + vector<int> &stat) { + if (stat[i]) + return stat[i] == 2; + stat[i] = 1; + for (auto n : al[i]) + if (!top_sort(al, n, res, stat)) + return false; + stat[i] = 2; + res.push_back(i); + return true; + } + +public: + vector<int> sortItems(int n, int m, vector<int> &group, + vvd(int) & beforeItems) { + vector<int> ans(n), stat(n + 2 * m), ans_tmp; + vector<unordered_set<int>> al(n + 2 * m); + for (auto i = 0; i < n; ++i) { + if (group[i] != -1) { + al[n + group[i]].insert(i); + al[i].insert(n + m + group[i]); + } + for (auto j : beforeItems[i]) { + if (group[i] != -1 && group[i] == group[j]) + al[j].insert(i); + else { + auto ig = group[i] == -1 ? i : n + group[i]; + auto jg = group[j] == -1 ? j : n + m + group[j]; + al[jg].insert(ig); + } + } + } + for (int n = al.size() - 1; n >= 0; --n) + if (!top_sort(al, n, ans_tmp, stat)) + return {}; + reverse(begin(ans_tmp), end(ans_tmp)); + copy_if(begin(ans_tmp), end(ans_tmp), ans.begin(), + [&](int i) { return i < n; }); + return ans; + } +}; + +int main() { + Solution obj; + vector<int> g1 = {-1, -1, 1, 0, 0, 1, 0, -1}, + g2 = {-1, -1, 1, 0, 0, 1, 0, -1}; + vvd(int) bi1 = {{}, {6}, {5}, {6}, {3, 6}, {}, {}, {}}, + bi2 = {{}, {6}, {5}, {6}, {3}, {}, {4}, {}}; + for (auto i : obj.sortItems(8, 2, g1, bi1)) + printf("%d ", i); // expect: [6,3,4,1,5,2,0,7] + printf("\n"); + for (auto i : obj.sortItems(8, 2, g2, bi2)) + printf("%d ", i); // expect: [] + printf("\n"); +} diff --git a/sort_matrix_diagonal.cpp b/sort_matrix_diagonal.cpp new file mode 100644 index 0000000..61f3486 --- /dev/null +++ b/sort_matrix_diagonal.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + unordered_map<int, vector<int>> umv; + vector<vector<int>> diagonalSort(vector<vector<int>> &mat) { + int m = mat.size(), n = mat[0].size(); + for (int i = 0; i < m; i++) + for (int j = 0; j < n; j++) + umv[i - j].push_back(mat[i][j]); + for (int i = -(n - 1); i < m; i++) + sort(umv[i].begin(), umv[i].end()); + for (int i = m - 1; i >= 0; i--) { + for (int j = n - 1; j >= 0; j--) { + mat[i][j] = umv[i - j].back(); + umv[i - j].pop_back(); + } + } + return mat; + } +}; diff --git a/sort_vowel_string.c b/sort_vowel_string.c new file mode 100644 index 0000000..07c31a4 --- /dev/null +++ b/sort_vowel_string.c @@ -0,0 +1,71 @@ +// 2785. Sort Vowels in a String +#include "leetcode.h" + +/* + * given a 0-indexed string 's', permute 's' to get a new string 't'. + - All consonants remain in their original places. More formally, if there is + an index i with 0 <= i < s.length such that s[i] is a consonant, then t[i] = + s[i]. + - The vowels must be sorted in the nondecreasing order of their ASCII + values. More formally, for pairs of indices i, j with 0 <= i < j < s.length + such that s[i] and s[j] are vowels, then t[i] must not have a higher ASCII + value than t[j]. + * return the resulting string. consonants comprise all letter that are not + vowels. + */ + +char map[10] = {'A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o', 'u'}; + +char is_vowel(char c, int *idx) { + if (c == 'A' || c == 'a') + return true; + else if (c == 'E' || c == 'e') { + (*idx) = 1; + return true; + } else if (c == 'I' || c == 'i') { + (*idx) = 2; + return true; + } else if (c == 'O' || c == 'o') { + (*idx) = 3; + return true; + } else if (c == 'U' || c == 'u') { + (*idx) = 4; + return true; + } + return false; +} + +char *sortVowels(char *s) { + int hash[10] = {0}, len = strlen(s); + char *ans = (char *)calloc(len + 1, sizeof(char)); + for (int i = 0; i < len; i++) { + int idx = 0; + if (is_vowel(s[i], &idx)) { + if (isupper(s[i])) + hash[idx]++; + else + hash[idx + 5]++; + } + } + int a_idx = 0, tmp; + for (int i = 0; i < len; i++) { + if (is_vowel(s[i], &tmp)) { + for (int j = 0; j < 10; j++) { + if (hash[j]) { + ans[a_idx++] = map[j]; + hash[j]--; + break; + } + } + } else { + ans[a_idx++] = s[i]; + } + } + return ans; +} + +int main() { + char s1[] = {"lEetcOde"}, s2[] = {"lYmpH"}; + printf("%s\n", sortVowels(s1)); // expect: lEOtcede + printf("%s\n", sortVowels(s2)); // expect: lYmpH +} diff --git a/sort_vowel_string.py b/sort_vowel_string.py new file mode 100644 index 0000000..b0cce99 --- /dev/null +++ b/sort_vowel_string.py @@ -0,0 +1,42 @@ +# 2785. Sort Vowels in a String + +""" + given a 0-indexed string 's', permute 's' to get a new string 't'. + - All consonants remain in their original places. More formally, if there is + an index i with 0 <= i < s.length such that s[i] is a consonant, then t[i] = + s[i]. + - The vowels must be sorted in the nondecreasing order of their ASCII + values. More formally, for pairs of indices i, j with 0 <= i < j < s.length + such that s[i] and s[j] are vowels, then t[i] must not have a higher ASCII + value than t[j]. + return the resulting string. consonants comprise all letter that are not + vowels. +""" + + +class Solution(object): + def sortVowels(self, s): + """ + :type s: str + :rtype: str + """ + vowel = [97, 101, 105, 111, 117, 65, 69, 73, 79, 85] + s = list(s) + lis = [] + idx = [] + for i in range(len(s)): + if ord(s[i]) in vowel: + lis.append(ord(s[i])) + idx.append(i) + lis.sort() + if len(lis) < 2: + return "".join(s) + for i in range(len(idx)): + s[idx[i]] = chr(lis[i]) + return "".join(s) + + +if __name__ == "__main__": + obj = Solution() + print(obj.sortVowels("lEetcOde")) + print(obj.sortVowels("lYmpH")) diff --git a/sorted_arrary_bst.cpp b/sorted_arrary_bst.cpp new file mode 100644 index 0000000..e859528 --- /dev/null +++ b/sorted_arrary_bst.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + TreeNode *sortedArrayToBST(vector<int> &nums) { + int start = 0, end = nums.size() - 1; + TreeNode *root = helper(start, end, nums); + return root; + } + +private: + TreeNode *helper(int start, int end, vector<int> &nums) { + if (start > end) + return NULL; + int mid = start + (end - start) / 2; + TreeNode *node = new TreeNode(nums[mid]); + node->left = helper(start, mid - 1, nums); + node->right = helper(mid + 1, end, nums); + return node; + } +}; diff --git a/soup_servings.c b/soup_servings.c new file mode 100644 index 0000000..68a3d9d --- /dev/null +++ b/soup_servings.c @@ -0,0 +1,51 @@ +// 808. Soup Servings +#include <stdio.h> +#include <stdlib.h> + +/* + * there are two types of soup: type a, and type b. initially, we have 'n' ml of + * each type of soup. there are four kinds of operations: + * 1. serve 100 ml of soup a and 0ml of soup b + * 2. serve 75ml of soup a and 25ml of soup b + * 3. serve 50ml of soup a and 50ml of soup b + * 4. serve 25ml of soup a and 75ml of soup b + * when we serve some soup, we give it to someone, and we no longer have it. + * each turn, we will choose from the four operations with an equal probability + * of '0.25'. if the remaining volume of soup is not enough to complete the + * operation, we will serve as much as possible. we stop once we no longer have + * some quantity of both types of soup. note that we do not have an operation + * where all 100 ml's of soup b are used first. return the probability that soup + * a will be empty first, plus half the probability that a and b become empty at + * the same time. answers within '10^-5' of the actual answer will be accepted. + */ + +double process(int a, int b, double **record) { + if (a <= 0 && b <= 0) + return 0.5; + if (a <= 0) + return 1.0; + if (b <= 0) + return 0; + if (record[a][b]) + return record[a][b]; + record[a][b] = + 0.25 * (process(a - 4, b, record) + process(a - 3, b - 1, record) + + process(a - 2, b - 2, record) + process(a - 1, b - 3, record)); + return record[a][b]; +} + +double soupServings(int n) { + double **record = malloc(150 * sizeof(double *)); + for (int i = 0; i < 150; i++) + record[i] = calloc(150, sizeof(double)); + double ans = n >= 3600 ? 1.0 : process((n + 24) / 25, (n + 24) / 25, record); + for (int i = 0; i < 150; i++) + free(record[i]); + free(record); + return ans; +} + +int main() { + printf("%f\n", soupServings(50)); // expect: 0.625000 + printf("%f\n", soupServings(100)); // expect: 0.71875 +} diff --git a/soup_servings.cpp b/soup_servings.cpp new file mode 100644 index 0000000..1733c21 --- /dev/null +++ b/soup_servings.cpp @@ -0,0 +1,54 @@ +// 808. Soup Servings +#include "leetcode.h" + +/* + * there are two types of soup: type a, and type b. initially, we have 'n' ml of + * each type of soup. there are four kinds of operations: + * 1. serve 100 ml of soup a and 0ml of soup b + * 2. serve 75ml of soup a and 25ml of soup b + * 3. serve 50ml of soup a and 50ml of soup b + * 4. serve 25ml of soup a and 75ml of soup b + * when we serve some soup, we give it to someone, and we no longer have it. + * each turn, we will choose from the four operations with an equal probability + * of '0.25'. if the remaining volume of soup is not enough to complete the + * operation, we will serve as much as possible. we stop once we no longer have + * some quantity of both types of soup. note that we do not have an operation + * where all 100 ml's of soup b are used first. return the probability that soup + * a will be empty first, plus half the probability that a and b become empty at + * the same time. answers within '10^-5' of the actual answer will be accepted. + */ + +class Solution { + unordered_map<int, unordered_map<int, double>> store; + double helper(int a, int b) { + if (!a && b) + return 1; + else if (!a && !b) + return 0.5; + else if (a && !b) + return 0; + if (store[a][b]) + return store[a][b]; + double prob = 0; + prob += 0.25 * helper(a - min(a, 100), b); + prob += 0.25 * helper(a - min(a, 75), b - min(b, 25)); + prob += 0.25 * helper(a - min(a, 50), b - min(b, 50)); + prob += 0.25 * helper(a - min(a, 25), b - min(b, 75)); + store[a][b] = prob; + return prob; + } + +public: + double soupServings(int n) { + if (n >= 5000) + return 1.0; + else + return helper(n, n); + } +}; + +int main() { + Solution obj; + printf("%f\n", obj.soupServings(50)); // expect: 0.62500 + printf("%f\n", obj.soupServings(100)); // expect: 0.71875 +} diff --git a/special_array_x_element_geqx.c b/special_array_x_element_geqx.c new file mode 100644 index 0000000..a875402 --- /dev/null +++ b/special_array_x_element_geqx.c @@ -0,0 +1,34 @@ +// 1608. Special Array With X Elements Greater Than or Equal X +#include "leetcode.h" + +/* + * given an array 'nums' of non negative integers. 'nums' is considered special + * if there exists a number 'x' such that there are exactly 'x' numbers in + * 'nums' that are greater than or equal to 'x'. notice that 'x' does not have + * to be an element in 'nums'. return 'x' if the array is special, otherwise, + * return -1. it can be proven that if 'nums' is special, the value for 'x' is + * unique. + */ + +int cmp(const void *a, const void *b) { return *(int *)a - *(int *)b; } + +int specialArray(int *nums, int numsSize) { + qsort(nums, numsSize, sizeof(int), cmp); + for (int i = 0; i < numsSize; i++) + if (nums[i] >= numsSize - i) { + if (!i) + return numsSize - i; + else { + if (nums[i - 1] < numsSize - i) + return numsSize - i; + } + } + return -1; +} + +int main() { + int n1[] = {3, 5}, n2[] = {0, 0}, n3[] = {0, 4, 3, 0, 4}; + printf("%d\n", specialArray(n1, ARRAY_SIZE(n1))); // expect: 2 + printf("%d\n", specialArray(n2, ARRAY_SIZE(n2))); // expect: -1 + printf("%d\n", specialArray(n3, ARRAY_SIZE(n3))); // expect: 3 +} diff --git a/special_array_x_element_geqx.py b/special_array_x_element_geqx.py new file mode 100644 index 0000000..6bc175b --- /dev/null +++ b/special_array_x_element_geqx.py @@ -0,0 +1,30 @@ +# 1608. Special Array With X Elements Greater Than or Equal X + +""" +given an array 'nums' of non negative integers. 'nums' is considered special +if there exists a number 'x' such that there are exactly 'x' numbers in +'nums' that are greater than or equal to 'x'. notice that 'x' does not have +to be an element in 'nums'. return 'x' if the array is special, otherwise, +return -1. it can be proven that if 'nums' is special, the value for 'x' is +unique. +""" + + +class Solution(object): + def specialArray(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + nums.sort(reverse=True) + i = 0 + while i < len(nums) and nums[i] > i: + i += 1 + return -1 if i < len(nums) and i == nums[i] else i + + +if __name__ == "__main__": + obj = Solution() + print(obj.specialArray([3, 5])) + print(obj.specialArray([0, 0])) + print(obj.specialArray([0, 4, 3, 0, 4])) diff --git a/special_position_binary_matrix.c b/special_position_binary_matrix.c new file mode 100644 index 0000000..a377dae --- /dev/null +++ b/special_position_binary_matrix.c @@ -0,0 +1,41 @@ +// 1582. Special Positions in a Binary Matrix +#include "leetcode.h" + +/* + * given an 'm * n' binary matrix 'mat', return the number of special positions + * in 'mat'. a position '(i, j)' is called special if 'mat[i][j] == 1' and all + * other elements in a row and column are 0 + */ + +// int numSpecial(int **mat, int mat_size, int *mat_col_size) { +int numSpecial(int r, int c, int mat[r][c], int mat_size, int *mat_col_size) { + int cnt = 0; + for (int rows = 0; rows < mat_size; rows++) + for (int cols = 0; cols < *mat_col_size; cols++) + if (mat[rows][cols]) { + bool match = 1; + for (int i = 0; i < *mat_col_size; i++) + if (mat[rows][i] && i != cols) { + match = 0; + break; + } + if (!match) + break; + for (int i = 0; i < mat_size; i++) + if (mat[i][cols] && i != rows) { + match = 0; + break; + } + if (match) + cnt++; + } + return cnt; +} + +int main() { + int m1[3][3] = {{1, 0, 0}, {0, 0, 1}, {1, 0, 0}}, + m2[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + int mcs1[] = {}, mcs2[] = {}; + printf("%d\n", numSpecial(3, 3, m1, 3, mcs1)); // expect: 1 + printf("%d\n", numSpecial(3, 3, m1, 3, mcs2)); // expect: 3 +} diff --git a/special_position_binary_matrix.py b/special_position_binary_matrix.py new file mode 100644 index 0000000..6776c15 --- /dev/null +++ b/special_position_binary_matrix.py @@ -0,0 +1,21 @@ +# 1582. Special Positions in a Binary Matrix + +""" +given an 'm n' binary matrix 'mat', return the number of special positions +in 'mat'. a position '(i, j)' is called special if 'mat[i][j] == 1' and all +other elements in a row and column are 0 +""" + + +class Solution(object): + def numSpecial(self, mat): + """ + :type mat: List[List[int]] + :rtype: int + """ + + +if __name__ == "__main__": + obj = Solution() + print(obj.numSpecial(mat=[[1, 0, 0], [0, 0, 1], [1, 0, 0]])) # expect: 1 + print(obj.numSpecial(mat=[[1, 0, 0], [0, 1, 0], [0, 0, 1]])) # expect: 3 diff --git a/spiral_matrix.cpp b/spiral_matrix.cpp new file mode 100644 index 0000000..ac1d212 --- /dev/null +++ b/spiral_matrix.cpp @@ -0,0 +1,37 @@ +// 54. Spiral Matrix +#include "leetcode.h" + +// given an m x n 'matrix', return all elements of the 'matrix' in spiral order + +class Solution { +public: + vector<int> spiralOrder(vvd(int) & matrix) { + vvd(int) dirs{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; + int rows = matrix.size(), cols = matrix[0].size(); + vector<int> ans, n_step{cols, rows - 1}; + if (!rows || !cols) + return ans; + int i_dir = 0, i_row = 0, i_col = -1; + while (n_step[i_dir % 2]) { + for (int i = 0; i < n_step[i_dir % 2]; ++i) { + i_row += dirs[i_dir][0]; + i_col += dirs[i_dir][1]; + ans.push_back(matrix[i_row][i_col]); + } + n_step[i_dir % 2]--; + i_dir = (i_dir + 1) % 4; + } + return ans; + } +}; + +int main() { + Solution obj; + vvd(int) m1 = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; + vvd(int) m2 = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}; + for (auto i : obj.spiralOrder(m1)) + printf("%d, ", i); + printf("\n"); // expect: 1,2,3,6,9,8,7,4,5 + for (auto i : obj.spiralOrder(m2)) + printf("%d, ", i); // expect: 1,2,3,4,8,12,11,10,9,5,6,7 +} diff --git a/spiral_matrix2.cpp b/spiral_matrix2.cpp new file mode 100644 index 0000000..de119a5 --- /dev/null +++ b/spiral_matrix2.cpp @@ -0,0 +1,26 @@ +// 59. Spiral Matrix II +#include "leetcode.h" + +// given a positive integer 'n', generate an n x n 'matrix' filled with +// elements from 1 to 'n^2' in spiral order + +class Solution { +public: + vvd(int) generateMatrix(int n) { + vvd(int) matrix(n, vector<int>(n)); + int num = 1, row = 0, col = 0, dir = 0; + vector<int> d_r = {0, 1, 0, -1}, d_c = {1, 0, -1, 0}; + while (num <= n * n) { + matrix[row][col] = num; + num++; + int next_row = row + d_r[dir]; + int next_col = col + d_c[dir]; + if (next_row < 0 || next_row >= n || next_col < 0 || next_col >= n || + matrix[next_row][next_col]) + dir = (dir + 1) % 4; + row += d_r[dir]; + col += d_c[dir]; + } + return matrix; + } +}; diff --git a/split_array.c b/split_array.c new file mode 100644 index 0000000..d0f0683 --- /dev/null +++ b/split_array.c @@ -0,0 +1,35 @@ +// 2270. Number of Ways to Split Array +#include <stdio.h> +#include <stdlib.h> + +/* + * given a 0-indexed integer array 'nums' of length 'n'. 'nums' contains a valid + * split at index 'i' if the following are true: + * - the sum of the first 'i + 1' elements is greater than or equal to the sum + * of the last 'n - i - 1' elements + * - there is at least one element to the right of 'i'. that is, 0 <= i < n - 1 + * return the number of valid splits in 'nums' + */ + +int waysToSplitArray(int *nums, int nums_size) { + int n = nums_size, ans = 0; + long long *presum = malloc(n * sizeof(long long)); + presum[0] = nums[0]; + for (int i = 1; i < n; i++) + presum[i] = presum[i - 1] + nums[i]; + long long half = presum[n - 1] / 2; + if (presum[n - 1] % 2) + if (presum[n - 1]) + half++; + for (int i = 0; i < n - 1; i++) + if (presum[i] >= half) + ans++; + return ans; +} + +int main() { + int n1[] = {10, 4, -8, 7}, ns1 = 4; + int n2[] = {2, 3, 1, 0}, ns2 = 4; + printf("%d\n", waysToSplitArray(n1, ns1)); // expect: 2 + printf("%d\n", waysToSplitArray(n2, ns2)); // expect: 2 +} diff --git a/split_array_consec_subseq.cpp b/split_array_consec_subseq.cpp new file mode 100644 index 0000000..622e296 --- /dev/null +++ b/split_array_consec_subseq.cpp @@ -0,0 +1,33 @@ +#include "leetcode.h" + +class Solution { +public: + bool isPossible(vector<int> &nums) { + unordered_map<int, int> um; + for (auto &it : nums) + um[it]++; + for (auto &it : nums) { + if (um[it] == 0) + continue; + int freq = um[it], curr = it, count = 0; + while (um.count(curr) && um[curr] >= freq) { + freq = fmax(freq, um[curr]); + um[curr]--; + count++; + curr++; + } + if (count < 3) + return false; + } + return true; + } +}; + +int main() { + Solution obj; + vector<int> nums = {1, 2, 3, 4, 5}; + if (obj.isPossible(nums)) + cout << "true"; + else + cout << "false"; +} diff --git a/split_linked_list.c b/split_linked_list.c new file mode 100644 index 0000000..079b62c --- /dev/null +++ b/split_linked_list.c @@ -0,0 +1,58 @@ +// 725. Split Linked List in Parts +#include <stdlib.h> + +/* + * given the 'head' of a singly linked list and an integer 'k', split the linked + * list into 'k' consecutive linked list parts. the length of each part should + * be as equal as possible: no two parts should have a size differing by more + * than one. this may lead some parts being null. the parts should be in the + * order of occurence in the input list, and parts occuring earlier should + * always have a size greater than or equal to parts occuring later. return an + * array of the 'k' parts. + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +int length(struct ListNode *head) { + if (!head) + return 0; + return length(head->next) + 1; +} + +struct ListNode **splitListToParts(struct ListNode *head, int k, + int *return_size) { + int n = length(head); + *return_size = k; + int items = n / k, left = n % k, idx_a = 0; + struct ListNode **ans = malloc(k * sizeof(struct ListNode *)); + struct ListNode *ptr = head, *tmp; + for (int i = 0; i < left; i++) { + ans[idx_a] = ptr; + idx_a++; + for (int j = 0; j < items; j++) + ptr = ptr->next; + tmp = ptr; + ptr = ptr->next; + tmp->next = NULL; + } + for (int i = left; i < k; i++) { + if (items <= 0) { + ans[idx_a] = NULL; + idx_a++; + continue; + } + ans[idx_a] = ptr; + idx_a++; + for (int j = 0; j < items - 1; j++) + ptr = ptr->next; + if (i < k - 1) { + tmp = ptr; + ptr = ptr->next; + tmp->next = NULL; + } + } + return ans; +} diff --git a/split_linked_list.py b/split_linked_list.py new file mode 100644 index 0000000..e73ee07 --- /dev/null +++ b/split_linked_list.py @@ -0,0 +1,40 @@ +# 725. Split Linked List in Parts + +""" +given the 'head' of a singly linked list and an integer 'k', split the linked +list into 'k' consecutive linked list parts. the length of each part should +be as equal as possible: no two parts should have a size differing by more +than one. this may lead some parts being null. the parts should be in the +order of occurence in the input list, and parts occuring earlier should +always have a size greater than or equal to parts occuring later. return an +array of the 'k' parts. +""" + + +class ListNode(object): + def __init__(self, val=0, next=None): + self.val = val + self.next = next + + +class Solution(object): + def splitListToParts(self, head, k): + parts = [None] * k + len = 0 + node = head + while node: + len += 1 + node = node.next + n, r = divmod(len, k) + node = root + prev = None + for i in range(k): + parts[i] = node + for j in range(n + (1 if r > 0 else 0)): + prev = node + node = node.next + if prev: + prev.next = None + if r > 0: + r -= 1 + return parts diff --git a/squares_sorted_array.c b/squares_sorted_array.c new file mode 100644 index 0000000..b91160b --- /dev/null +++ b/squares_sorted_array.c @@ -0,0 +1,32 @@ +// 977. Squares of a Sorted Array +#include "leetcode.h" + +/* + * given an integer array 'nums' sorted in non-decreasing order, return an array + * of the squares sorted in non-decreasing order. + */ + +int *sortedSquares(int *nums, int numsSize, int *returnSize) { + int *ans = malloc(sizeof(int) * numsSize); + *returnSize = numsSize; + int end = numsSize - 1, start = 0, ptr = numsSize - 1; + while (start <= end && ptr >= 0) { + ans[ptr] = pow(nums[end], 2) >= pow(nums[start], 2) ? pow(nums[end--], 2) + : pow(nums[start++], 2); + ptr--; + } + return ans; +} + +int main() { + int n1[] = {-4, -1, 0, 3, 10}, n2[] = {-7, -3, 2, 3, 11}; + int *rs1 = (int *)malloc(sizeof(int)), *rs2 = (int *)malloc(sizeof(int)); + int *ss1 = sortedSquares(n1, ARRAY_SIZE(n1), rs1); + int *ss2 = sortedSquares(n2, ARRAY_SIZE(n2), rs2); + for (int i = 0; i < ARRAY_SIZE(n1); i++) + printf("%d ", ss1[i]); // expect: 0 1 9 16 100 + printf("\n"); + for (int i = 0; i < ARRAY_SIZE(n2); i++) + printf("%d ", ss2[i]); // expect: 4 9 9 49 121 + printf("\n"); +} diff --git a/squares_sorted_array.py b/squares_sorted_array.py new file mode 100644 index 0000000..928ee24 --- /dev/null +++ b/squares_sorted_array.py @@ -0,0 +1,30 @@ +# 977. Squares of a Sorted Array + +""" +given an integer array 'nums' sorted in non-decreasing order, return an array +of the squares sorted in non-decreasing order. +""" + + +class Solution(object): + def sortedSquares(self, nums): + """ + :type nums: List[int] + :rtype: List[int] + """ + ans = [None for _ in nums] + left, right = 0, len(nums) - 1 + for i in range(len(nums) - 1, -1, -1): + if abs(nums[left]) > abs(nums[right]): + ans[i] = nums[left] ** 2 + left += 1 + else: + ans[i] = nums[right] ** 2 + right -= 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.sortedSquares(nums=[-4, -1, 0, 3, 10])) + print(obj.sortedSquares(nums=[-7, -3, 2, 3, 11])) diff --git a/stack_using_queues.cpp b/stack_using_queues.cpp new file mode 100644 index 0000000..61e2c88 --- /dev/null +++ b/stack_using_queues.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class MyStack { +public: + queue<int> q; + MyStack() {} + void push(int x) { + int n = q.size(); + q.push(x); + while (n--) { + q.push(q.front()); + q.pop(); + } + } + int pop() { + int ans = top(); + q.pop(); + return ans; + } + int top() { return q.front(); } + bool empty() { return q.empty(); } +}; + +int main() {} diff --git a/stamping_sequence.cpp b/stamping_sequence.cpp new file mode 100644 index 0000000..b9ba317 --- /dev/null +++ b/stamping_sequence.cpp @@ -0,0 +1,34 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> movesToStamp(string stamp, string target) { + if (stamp == target) + return {0}; + int sLen = stamp.size(), tLen = target.size() - sLen + 1, i, j; + vector<int> ans; + bool tDiff = true, sDiff; + while (tDiff) { + for (i = 0, tDiff = false; i < tLen; i++) { + for (j = 0, sDiff = false; j < sLen; j++) { + if (target[i + j] == '*') + continue; + else if (target[i + j] != stamp[j]) + break; + else + sDiff = true; + } + if (j == sLen && sDiff) { + for (j = i, tDiff = true; j < sLen + i; j++) + target[j] = '*'; + ans.push_back(i); + } + } + for (i = 0; i < target.size(); i++) + if (target[i] != '*') + return {}; + reverse(ans.begin(), ans.end()); + } + return ans; + } +}; diff --git a/steps_arr_increasing.c b/steps_arr_increasing.c new file mode 100644 index 0000000..91603bf --- /dev/null +++ b/steps_arr_increasing.c @@ -0,0 +1,47 @@ +// 2289. Steps to Make Array Non-decreasing +#include <stdio.h> + +/* + * given a 0-indexed integer array 'nums'. in one step, remofe all elements + * 'nums[i]' where 'nums[i - 1] > nums[i]' for all '0 < i < nums.size()'. return + * the number of steps performed until 'nums' becomes non-decreasing + */ + +void next(int *nums, int nums_size, int k, int *i, int time) { + int curr = 0; + (*i)++; + while (*i < nums_size) { + if (k > nums[*i]) { + curr++; + next(nums, nums_size, nums[*i], i, curr); + if (curr == time) + return; + } else + return; + } +} + +int totalSteps(int *nums, int nums_size) { + int ans = 0, time = 0, k = nums[0], i = 1; + while (i < nums_size) { + if (k > nums[i]) { + time++; + next(nums, nums_size, nums[i], &i, time); + } else { + if (time > ans) + ans = time; + time = 0; + k = nums[i]; + i++; + } + } + if (time > ans) + ans = time; + return ans; +} + +int main() { + int n1[] = {5, 3, 4, 4, 7, 3, 6, 11, 8, 5, 11}, n2[] = {4, 5, 7, 7, 13}; + printf("%d\n", totalSteps(n1, 11)); // expect: 3 + printf("%d\n", totalSteps(n2, 5)); // expect: 0 +} diff --git a/steps_arr_increasing.cpp b/steps_arr_increasing.cpp new file mode 100644 index 0000000..2beb625 --- /dev/null +++ b/steps_arr_increasing.cpp @@ -0,0 +1,32 @@ +// 2289. Steps to Make Array Non-decreasing +#include "leetcode.h" + +/* + * given a 0-indexed integer array 'nums'. in one step, remofe all elements + * 'nums[i]' where 'nums[i - 1] > nums[i]' for all '0 < i < nums.size()'. return + * the number of steps performed until 'nums' becomes non-decreasing + */ + +class Solution { +public: + int totalSteps(vector<int> &nums) { + int n = nums.size(), ans = 0; + vector<int> stack, dp(n); + for (int i = n - 1; i >= 0; --i) { + while (!stack.empty() && nums[i] > nums[stack.back()]) { + dp[i] = max(++dp[i], dp[stack.back()]); + stack.pop_back(); + ans = max(ans, dp[i]); + } + stack.push_back(i); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {5, 3, 4, 4, 7, 3, 6, 11, 8, 5, 11}, n2 = {4, 5, 7, 7, 13}; + printf("%d\n", obj.totalSteps(n1)); // expect: 3 + printf("%d\n", obj.totalSteps(n2)); // expect: 0 +} diff --git a/stone_game.c b/stone_game.c new file mode 100644 index 0000000..96072d1 --- /dev/null +++ b/stone_game.c @@ -0,0 +1,45 @@ +// 877. Stone Game +#include "leetcode.h" + +/* + * alice and bob play a game with piles of stones. there are an even number of + * piles arranged in a row, and each pile has a positive integer number of + * stones 'piles[i]'. the objective of the game is to end with the most stones. + * the total number of stones across all piles isodd, so there are no ties. + * alice and bob take turns, with alice starting first. each turn a player takes + * the entire pile of stones either from the beginning or from the end of the + * row. this continues until there are no more piles left, at which point the + * person with the most stones wins. assuming alice and bob play optimally, + * return 'true' if alice wins the game, or 'false' if bob wins. + */ + +bool stoneGame(int *piles, int piles_size) { + int **dp = (int **)malloc(sizeof(int *) * piles_size); + int **sum = (int **)malloc(sizeof(int *) * piles_size); + for (int i = 0; i < piles_size; i++) { + dp[i] = (int *)malloc(sizeof(int) * piles_size); + sum[i] = (int *)malloc(sizeof(int) * piles_size); + for (int j = 0; j < piles_size; j++) + if (i == j) { + dp[i][j] = piles[i]; + sum[i][j] = piles[i]; + } + } + for (int l = 2; l <= piles_size; ++l) + for (int i = 0; i <= piles_size; ++i) { + int j = i + l - 1; + sum[i][j] = sum[i][j - 1] + piles[j]; + dp[i][j] = sum[i][j] - fmin(dp[i][j - 1], dp[i + 1][j]); + } + bool ans = (dp[0][piles_size - 1] * 2 > sum[0][piles_size - 1]); + for (int i = 0; i < piles_size; i++) + free(dp[i]), free(sum[i]); + free(dp), free(sum); + return ans; +} + +int main() { + int p1[] = {5, 3, 4, 5}, p2[] = {3, 7, 2, 3}; + printf("%d\n", stoneGame(p1, ARRAY_SIZE(p1))); // expect: 1 + printf("%d\n", stoneGame(p2, ARRAY_SIZE(p2))); // expect: 1 +} diff --git a/stone_game.py b/stone_game.py new file mode 100644 index 0000000..c10174d --- /dev/null +++ b/stone_game.py @@ -0,0 +1,29 @@ +# 877. Stone Game + +""" +alice and bob play a game with piles of stones. there are an even number of +piles arranged in a row, and each pile has a positive integer number of +stones 'piles[i]'. the objective of the game is to end with the most stones. +the total number of stones across all piles isodd, so there are no ties. +alice and bob take turns, with alice starting first. each turn a player takes +the entire pile of stones either from the beginning or from the end of the +row. this continues until there are no more piles left, at which point the +person with the most stones wins. assuming alice and bob play optimally, +return 'true' if alice wins the game, or 'false' if bob wins. +""" + + +class Solution(object): + def stoneGame(self, piles): + n = len(piles) + dp = piles[:] + for i in range(1, n): + for j in range(n - i): + dp[j] = max(piles[j] - dp[j + 1], piles[j + i] - dp[j]) + return dp[0] > 0 + + +if __name__ == "__main__": + obj = Solution() + print(obj.stoneGame([5, 3, 4, 5])) # expect: True + print(obj.stoneGame([3, 7, 2, 3])) # expect: True diff --git a/stone_game2.c b/stone_game2.c new file mode 100644 index 0000000..b1b2092 --- /dev/null +++ b/stone_game2.c @@ -0,0 +1,45 @@ +// 1140. Stone Game II +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * alice and bob continue their games with piles of stones. there are a number + * of piles arranged in a row, and each pile has a positive integer number of + * stones 'piles[i]'. the objective of the game is to end with the most stones. + * alice and bob take turns, with alice starting first. initiall, 'M = 1'. on + * each player's turn, that player can take all the stones on the 'X' remaining + * piles, where '1 <= X <= 2M'. then, we set 'M = max(M, X)'. the game continues + * until all the stones have been take. assuming alice and bob play optimally, + * return maximum stones alice can get. + */ + +int stoneGameII(int *piles, int piles_size) { + int n = piles_size; + int *sum = malloc((n + 1) * sizeof(int)); + int **dp = malloc((n + 1) * sizeof(int *)); + for (int i = 0; i <= n; i++) + dp[i] = calloc(n + 1, sizeof(int)); + sum[n] = 0; + for (int i = n - 1; i >= 0; i--) + sum[i] = sum[i + 1] + piles[i]; + for (int i = 0; i < n; ++i) + dp[i][n] = sum[i]; + for (int i = n - 1; i >= 0; i--) + for (int m = n - 1; m >= 1; m--) + for (int x = 1; x <= 2 * m && i + x <= n; ++x) + dp[i][m] = fmax(dp[i][m], sum[i] - dp[i + x][(int)fmax(m, x)]); + int ans = dp[0][1]; + for (int i = 0; i <= n; i++) + free(dp[i]); + free(dp); + free(sum); + return ans; +} + +int main() { + int p1[] = {2, 7, 9, 4, 4}; + int p2[] = {1, 2, 3, 4, 5, 100}; + printf("%d\n", stoneGameII(p1, 5)); // expect: 10 + printf("%d\n", stoneGameII(p2, 6)); // expect: 104 +} diff --git a/stone_game2.cpp b/stone_game2.cpp new file mode 100644 index 0000000..808546f --- /dev/null +++ b/stone_game2.cpp @@ -0,0 +1,39 @@ +// 1140. Stone Game II +#include "leetcode.h" + +/* + * alice and bob continue their games with piles of stones. there are a number + * of piles arranged in a row, and each pile has a positive integer number of + * stones 'piles[i]'. the objective of the game is to end with the most stones. + * alice and bob take turns, with alice starting first. initiall, 'M = 1'. on + * each player's turn, that player can take all the stones on the 'X' remaining + * piles, where '1 <= X <= 2M'. then, we set 'M = max(M, X)'. the game continues + * until all the stones have been take. assuming alice and bob play optimally, + * return maximum stones alice can get. + */ + +class Solution { +public: + int stoneGameII(vector<int> &piles) { + int n = piles.size(); + vvd(int) dp(n + 1, vector<int>(n + 1, 0)); + vector<int> sum(n + 1, 0); + for (int i = n - 1; i >= 0; i--) + sum[i] = sum[i + 1] + piles[i]; + for (int i = 0; i <= n; i++) + dp[i][n] = sum[i]; + for (int i = n - 1; i >= 0; i--) + for (int j = n - 1; j >= 1; j--) + for (int k = 1; k <= 2 * j && i + j <= n; j++) + dp[i][j] = max(dp[i][j], sum[i] - dp[i + k][max(j, k)]); + return dp[0][1]; + } +}; + +int main() { + Solution obj; + vector<int> p1 = {2, 7, 9, 4, 4}; + vector<int> p2 = {1, 2, 3, 4, 5, 100}; + printf("%d\n", obj.stoneGameII(p1)); // expect: 10 + printf("%d\n", obj.stoneGameII(p2)); // expect: 104 +} diff --git a/stone_game3.c b/stone_game3.c new file mode 100644 index 0000000..947d65f --- /dev/null +++ b/stone_game3.c @@ -0,0 +1,46 @@ +// 1406. Stone Game III +#include <stdio.h> + +/* + * alice and bob continue their games with piles of stones. there are several + * stones arranged in a row, and each stone has an associated value which is an + * integer given in the array 'stone_value'. alice and bob take turns with alice + * starting first. on each player's turn, that player can take 1,2, or 3 stones + * from the first remaining stones in row. the score of each player is the sum + * of the values of the stones taken the score of each player is initially zero. + * the objective of the game is to end with the highest score, and the winner is + * the player with the highest score and there could be a tie. the game + * continues until all the stones have been taken. assume alice and bob play + * optimally. return "Alice", "Bob", or "Tie" accordingly + */ + +int min(int a, int b, int c) { + if (a <= b && a <= c) + return a; + if (b <= a && b <= c) + return b; + return c; +} + +char *stoneGameIII(int *stone_value, int stone_value_size) { + int dp[50005] = {0}, sum = 0; + for (int i = stone_value_size - 1; i >= 0; --i) { + sum += stone_value[i]; + dp[i] = sum - min(dp[i + 1], dp[i + 2], dp[i + 3]); + } + if (dp[0] * 2 == sum) + return "Tie"; + if (dp[0] * 2 > sum) + return "Alice"; + else + return "Bob"; +} + +int main() { + int sv1[] = {1, 2, 3, 7}; + int sv2[] = {1, 2, 3, -9}; + int sv3[] = {1, 2, 3, 6}; + printf("%s\n", stoneGameIII(sv1, 4)); // expect: Bob + printf("%s\n", stoneGameIII(sv2, 4)); // expect: Alice + printf("%s\n", stoneGameIII(sv3, 4)); // expect: Tie +} diff --git a/stone_game3.cpp b/stone_game3.cpp new file mode 100644 index 0000000..947d65f --- /dev/null +++ b/stone_game3.cpp @@ -0,0 +1,46 @@ +// 1406. Stone Game III +#include <stdio.h> + +/* + * alice and bob continue their games with piles of stones. there are several + * stones arranged in a row, and each stone has an associated value which is an + * integer given in the array 'stone_value'. alice and bob take turns with alice + * starting first. on each player's turn, that player can take 1,2, or 3 stones + * from the first remaining stones in row. the score of each player is the sum + * of the values of the stones taken the score of each player is initially zero. + * the objective of the game is to end with the highest score, and the winner is + * the player with the highest score and there could be a tie. the game + * continues until all the stones have been taken. assume alice and bob play + * optimally. return "Alice", "Bob", or "Tie" accordingly + */ + +int min(int a, int b, int c) { + if (a <= b && a <= c) + return a; + if (b <= a && b <= c) + return b; + return c; +} + +char *stoneGameIII(int *stone_value, int stone_value_size) { + int dp[50005] = {0}, sum = 0; + for (int i = stone_value_size - 1; i >= 0; --i) { + sum += stone_value[i]; + dp[i] = sum - min(dp[i + 1], dp[i + 2], dp[i + 3]); + } + if (dp[0] * 2 == sum) + return "Tie"; + if (dp[0] * 2 > sum) + return "Alice"; + else + return "Bob"; +} + +int main() { + int sv1[] = {1, 2, 3, 7}; + int sv2[] = {1, 2, 3, -9}; + int sv3[] = {1, 2, 3, 6}; + printf("%s\n", stoneGameIII(sv1, 4)); // expect: Bob + printf("%s\n", stoneGameIII(sv2, 4)); // expect: Alice + printf("%s\n", stoneGameIII(sv3, 4)); // expect: Tie +} diff --git a/stone_game4.cpp b/stone_game4.cpp new file mode 100644 index 0000000..2eddb18 --- /dev/null +++ b/stone_game4.cpp @@ -0,0 +1,16 @@ +#include "leetcode.h" +#include <vector> + +class Solution { +public: + int stoneGameVI(vector<int> &aliceValues, vector<int> &bobValues) { + vector<array<int, 3>> n; + int a = 0, b = 0, sz = aliceValues.size(); + } +}; + +int main() { + Solution obj; + vector<int> aliceValues = {1, 3}, bobValues = {2, 1}; + cout << obj.stoneGameVI(aliceValues, bobValues); +} diff --git a/stone_game7.c b/stone_game7.c new file mode 100644 index 0000000..44baf64 --- /dev/null +++ b/stone_game7.c @@ -0,0 +1,53 @@ +// 1690. Stone Game VII +#include <math.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * alice and bob take turns playing a game, with alice starting first. there are + * 'n' stones arranged in a row. on each player's turn, they can remove either + * the leftmost stone or the rightmost stone from the row and receive points + * equal to the sum of the remaining stones' values in the row. the winner is + * the one with the higher score when there are no stones left to remove. bob + * found that he will always lose this game (poor bob, he always loses), so he + * decided to minimise the socre's difference. alice'goal is to maximise the + * difference in score. given an array of integers 'stones' where 'stones[i]' + * represents the value of the i'th stone from the left, return the difference + * in alice and bob's score if they both play optimally. + */ + +int stoneGameVII(int *stones, int stones_size) { + int n = stones_size; + bool even = !n % 2 ? true : false; + int **dp = malloc(n * sizeof(int *)); + for (int i = 0; i < n; i++) { + dp[i] = malloc(n * sizeof(int)); + dp[i][i] = 0; + } + int *sum = malloc((n + 1) * sizeof(int)); + sum[0] = 0; + for (int i = 1; i <= n; i++) + sum[i] = sum[i - 1] + stones[i - 1]; + for (int k = 2; k <= n; k++) + for (int i = 0; i <= n - k; i++) { + int j = i + k - 1; + if (even && !k % 2 || !even && k % 2) + dp[i][j] = fmax(dp[i + 1][j] + sum[j + 1] - sum[i + 1], + dp[i][j - 1] + sum[j] - sum[i]); + else + dp[i][j] = fmin(dp[i + 1][j] - (sum[j + 1] - sum[i + 1]), + dp[i][j - 1] - (sum[j] - sum[i])); + } + int ans = dp[0][n - 1]; + for (int i = 0; i < n; i++) + free(dp[i]); + free(dp), free(sum); + return ans; +} + +int main() { + int s1[] = {5, 3, 1, 4, 2}, s2[] = {7, 90, 5, 1, 100, 10, 10, 2}; + printf("%d\n", stoneGameVII(s1, 5)); // expect: 6 + printf("%d\n", stoneGameVII(s2, 8)); // expect: 122 +} diff --git a/strange_printer.c b/strange_printer.c new file mode 100644 index 0000000..6a84b90 --- /dev/null +++ b/strange_printer.c @@ -0,0 +1,41 @@ +// 664. Strange Printer +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * there is a strange printer with the following two special properties: + * - the printer can only print a sequence of the same character each time + * - at each turn, the printer can print new characters starting from and eding + * at any place and will cover the origin existing characters given a string + * 's', return the minimum number of turns the printer needed to print it. + */ + +int f[100][100]; + +int dfs(char *s, int left, int right) { + if (left > right) + return 0; + if (f[left][right]) + return f[left][right]; + f[left][right] = dfs(s, left, right - 1) + 1; + for (int i = left; i < right; i++) { + if (s[i] == s[right]) + f[left][right] = + fmin(f[left][right], dfs(s, left, i) + dfs(s, i + 1, right - 1)); + } + return f[left][right]; +} + +int strangePrinter(char *s) { + memset(f, 0, sizeof(f)); + int len = strlen(s); + return dfs(s, 0, len - 1); +} + +int main() { + char s1[] = {"aaabbb"}, s2[] = {"aba"}; + printf("%d\n", strangePrinter(s1)); // expect: 2 + printf("%d\n", strangePrinter(s2)); // expect: 2 +} diff --git a/strange_printer.cpp b/strange_printer.cpp new file mode 100644 index 0000000..8a5dc93 --- /dev/null +++ b/strange_printer.cpp @@ -0,0 +1,32 @@ +// 664. Strange Printer +#include "leetcode.h" + +/* + * there is a strange printer with the following two special properties: + * - the printer can only print a sequence of the same character each time + * - at each turn, the printer can print new characters starting from and eding + * at any place and will cover the origin existing characters given a string + * 's', return the minimum number of turns the printer needed to print it. + */ + +class Solution { +public: + int strangePrinter(string s) { + int n = s.size(); + vector<vector<int>> dp(n + 1, vector<int>(n)); + for (int i = n - 1; i >= 0; i--) + for (int j = i; j < n; j++) { + dp[i][j] = 1 + dp[i + 1][j]; + for (int k = i + 1; k <= j; k++) + if (s[k] == s[i]) + dp[i][j] = min(dp[i][j], dp[i + 1][k - 1] + dp[k][j]); + } + return dp[0][n - 1]; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.strangePrinter("aaabbb")); // expect: 2 + printf("%d\n", obj.strangePrinter("aba")); // expect: 2 +} diff --git a/string_compression.c b/string_compression.c new file mode 100644 index 0000000..37490e2 --- /dev/null +++ b/string_compression.c @@ -0,0 +1,65 @@ +// 443. String Compression +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given array of characters 'chars', compress it using following + * algorithm: being with empty string 's'. for each group of + * consecutive repeating characters in 'chars': if the group's + * length is 1, append character to 's'. otherwise, append character + * followed by the group's length. the compressed string 's' should + * not be returned separately, but instead, be stored in input + * character array 'chars'. note that group lengths are 10 or longer + * will be split into multiple characters in 'chars'. return new + * length of array. algorithm must be contant space complexity + */ + +char *int2char(int n) { + char *res = malloc(11); + res[10] = '\0'; // null terminate + int idx = 9; + while (n) { + res[idx] = '0' + n % 10; + n /= 10; + idx--; + } + return &res[idx + 1]; +} + +int compress(char *chars, int charsSize) { + int idx = 0, cnt = 1; + char target = chars[0]; + for (int i = 1; i < charsSize; i++) { + if (chars[i] == chars[i - 1]) + cnt++; + else { + chars[idx] = target; + idx++; + if (cnt > 1) { + char *tmp = int2char(cnt); + strncpy(&chars[idx], tmp, strlen(tmp)); + idx += strlen(tmp); + } + cnt = 1; + target = chars[i]; + } + } + chars[idx] = target; + idx++; + if (cnt > 1) { + char *tmp = int2char(cnt); + strncpy(&chars[idx], tmp, strlen(tmp)); + idx += strlen(tmp); + } + return idx; +} + +int main() { + char c1[] = {'a', 'a', 'b', 'b', 'c', 'c', 'c'}; + char c2[] = {'a'}; + char c3[] = {'a', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b'}; + printf("%d\n", compress(c1, 7)); // expect: ["a","2","b","2","c","3"] + printf("%d\n", compress(c2, 1)); // expect: ["a"] + printf("%d\n", compress(c3, 13)); // expect: ["a","b","1","2"] +} diff --git a/string_compression.cpp b/string_compression.cpp new file mode 100644 index 0000000..5f9b9c6 --- /dev/null +++ b/string_compression.cpp @@ -0,0 +1,31 @@ +#include "leetcode.h" + +class Solution { +public: + int compress(vector<char> &chars) { + string ans; + int c = 1, i; + for (i = 1; i < chars.size(); i++) { + if (chars[i] == chars[i - 1]) + c++; + else if (chars[i] != chars[i - 1] && c == 1) + ans += chars[i - 1]; + else { + ans += chars[i - 1]; + ans += to_string(c); + c = 1; + } + } + if (c == 1) + ans += chars[i - 1]; + else + ans += chars[i - 1] + to_string(c); + for (int i = 0; i < ans.size(); i++) + chars[i] = ans[i]; + vector<char>::iterator it, ty; + it = chars.begin() + ans.size(); + ty = chars.begin() + chars.size(); + chars.erase(it, ty); + return ans.size(); + } +}; diff --git a/string_compression.rs b/string_compression.rs new file mode 100644 index 0000000..1d5db7d --- /dev/null +++ b/string_compression.rs @@ -0,0 +1,38 @@ +struct Solution; + +impl Solution { + pub fn compress(chars: &mut Vec<char>) -> i32 { + let (mut i, mut j, mut count, mut last_char) = (0, 1, 1, chars[0]); + while j < chars.len() { + if chars[j] == last_char { + count += 1; + } else { + chars[i] = last_char; + i += 1; + if count > 1 { + count.to_string().chars().for_each(|x| { + chars[i] = x; + i += 1; + }); + } + last_char = chars[j]; + count = 1; + } + j += 1; + } + chars[i] = last_char; + i += 1; + if count > 1 { + count.to_string().chars().for_each(|x| { + chars[i] = x; + i += 1; + }); + } + i as i32 + } +} + +fn main() { + let mut c = vec!['a','a','b','b','c','c','c']; + print!("{}", Solution::compress(&mut c)); +} diff --git a/string_compression2.c b/string_compression2.c new file mode 100644 index 0000000..206af5e --- /dev/null +++ b/string_compression2.c @@ -0,0 +1,48 @@ +// 1531. String Compression II +#include "leetcode.h" + +/* + * run-length encoding is a string compression method that works by replacing + * consecutive identical characters (repeated 2 or more times) with the + * concatenation of the characters and the number marking the count of the + * characters (length of run). for example tocompress the string "aabccc", we + * replace "aa" by "a2" and replace "ccc" by "c3". thus the compressed string + * becomes "a2bc3". notice that in this problem we are not adding '1' after + * single characters. given a string 's' and an integer 'k'. you needed to + * delete at most 'k' characters from 's' such that the run-length encoded + * version of 's' has minimum length. find the minimum length of the run-length + * encoded version of 's' after deleting at most 'k' characters + */ + +int dp[101][101]; +int dfs(char *s, int left, int k) { + int j = k; + if (strlen(s) - left <= j) + return 0; + if (dp[left][j] >= 0) + return dp[left][j]; + int res = j ? dfs(s, left + 1, k - 1) : 100, c = 1; + for (int i = left + 1; i <= strlen(s); ++i) { + res = fmin(res, dfs(s, i, j) + 1 + + (c >= 100 ? 3 : (c >= 10 ? 2 : (c > 1 ? 1 : 0)))); + if (i == strlen(s)) + break; + if (s[i] == s[left]) + ++c; + else if (--k < 0) + break; + } + return dp[left][k] = res; +} + +int getLengthOfOptimalCompression(char *s, int k) { + memset(dp, -1, sizeof(dp)); + return dfs(s, 0, k); +} + +int main() { + char *s1 = "aaabcccd", *s2 = "aabbaa", *s3 = "aaaaaaaaaaa"; + printf("%d\n", getLengthOfOptimalCompression(s1, 2)); // expect: 4 + printf("%d\n", getLengthOfOptimalCompression(s2, 2)); // expect: 2 + printf("%d\n", getLengthOfOptimalCompression(s3, 0)); // expect: 0 +} diff --git a/string_compression2.cpp b/string_compression2.cpp new file mode 100644 index 0000000..f4c41c8 --- /dev/null +++ b/string_compression2.cpp @@ -0,0 +1,37 @@ +#include "leetcode.h" + +class Solution { +public: + int getLengthOfOptimalCompression(string s, int k) { + memset(dp, -1, sizeof(dp)); + str = s, p = s.size(); + return solve(0, k); + } + +private: + const static int N = 127; + int dp[N][N], p; + string str; + inline int helper(int x) { return x == 1 ? 0 : x < 10 ? 1 : x < 100 ? 2 : 3; } + int solve(int left, int k) { + if (k < 0) + return N; + if (left >= p || p - left <= k) + return 0; + int &ans = dp[left][k]; + if (ans != -1) + return ans; + ans = N; + int count[26] = {0}; + for (int i = left, j = 0; i < p; i++) { + j = max(j, ++count[str[j] - 'a']); + ans = min(ans, 1 + helper(j) + solve(i + 1, k - (i - left + 1 - j))); + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.getLengthOfOptimalCompression("aaabcccd", 2); +} diff --git a/string_compression2.py b/string_compression2.py new file mode 100644 index 0000000..a8798ec --- /dev/null +++ b/string_compression2.py @@ -0,0 +1,56 @@ +# 1531. String Compression II + +""" +run-length encoding is a string compression method that works by replacing +consecutive identical characters (repeated 2 or more times) with the +concatenation of the characters and the number marking the count of the +characters (length of run). for example tocompress the string "aabccc", we +replace "aa" by "a2" and replace "ccc" by "c3". thus the compressed string +becomes "a2bc3". notice that in this problem we are not adding '1' after +single characters. given a string 's' and an integer 'k'. you needed to +delete at most 'k' characters from 's' such that the run-length encoded +version of 's' has minimum length. find the minimum length of the run-length +encoded version of 's' after deleting at most 'k' characters +""" + + +class Solution(object): + def getLengthOfOptimalCompression(self, s, k): + """ + :type s: str + :type k: int + :rtype: int + """ + n = len(s) + m = k + dp = [[float("inf")] * 110 for _ in range(110)] + for i in range(1, n + 1): + for j in range(min(i + 1, m + 1)): + needRemove = 0 + groupCount = 0 + dp[i][j] = float("inf") + if j > 0: + dp[i][j] = dp[i - 1][j - 1] + for k in range(i, 0, -1): + if s[k - 1] != s[i - 1]: + needRemove += 1 + else: + groupCount += 1 + if needRemove > j: + break + if groupCount == 1: + dp[i][j] = min(dp[i][j], dp[k - 1][j - needRemove] + 1) + elif groupCount < 10: + dp[i][j] = min(dp[i][j], dp[k - 1][j - needRemove] + 2) + elif groupCount < 100: + dp[i][j] = min(dp[i][j], dp[k - 1][j - needRemove] + 3) + else: + dp[i][j] = min(dp[i][j], dp[k - 1][j - needRemove] + 4) + return dp[n][m] + + +if __name__ == "__main__": + obj = Solution() + print(obj.getLengthOfOptimalCompression("aaabcccd", 2)) # expect: 4 + print(obj.getLengthOfOptimalCompression("aabbaa", 2)) # expect: 2 + print(obj.getLengthOfOptimalCompression("aaaaaaaaaaa", 0)) # expect: 3 diff --git a/string_compression2.rs b/string_compression2.rs new file mode 100644 index 0000000..792a0ac --- /dev/null +++ b/string_compression2.rs @@ -0,0 +1,54 @@ +struct Solution; + +impl Solution { + pub fn get_length_of_optimal_compression(s: String, k: i32) -> i32 { + #[inline] + fn len_of_chars(n: i32) -> i32 { + match n { + 1 => 1, + 2..=9 => 2, + 10..=99 => 3, + _ => 4, + } + } + fn dfs(v: &[u8], dp: &mut [[i32; 101]; 101], left: i32, k_s: i32) -> i32 { + let mut k = k_s; + if v.len() as i32 - left <= k { + return 0; + } + if dp[left as usize][k as usize] >= 0 { + return dp[left as usize][k as usize]; + } + let mut ans = if k > 0 { + dfs(v, dp, left + 1, k - 1) + } else { + std::i32::MAX + }; + let mut c = 1; + for i in left + 1..=v.len() as i32 { + ans = ans.min(dfs(v, dp, i, k) + len_of_chars(c)); + if i == v.len() as i32 { + break; + } + if v[i as usize] == v[left as usize] { + c += 1; + } else { + k -= 1; + if k < 0 { + break; + } + } + } + dp[left as usize][k_s as usize] = ans; + ans + } + let mut dp = [[-1; 101]; 101]; + let v = s.as_bytes(); + dfs(v, &mut dp, 0, k) + } +} + +fn main() { + let s = String::from("aaabcccd"); + print!("{}", Solution::get_length_of_optimal_compression(s, 2)); +} diff --git a/string_without_3a3b.c b/string_without_3a3b.c new file mode 100644 index 0000000..403c7f1 --- /dev/null +++ b/string_without_3a3b.c @@ -0,0 +1,62 @@ +// 984. String Without AAA or BBB +#include <stdio.h> +#include <stdlib.h> + +/* + * given two integers 'a' and 'b', return any string 's' such that + * - 's' has length 'a + b' and contains exactly 'a' a letters and exactly 'b' b + * letters. + * - the substring 'aaa' does not occur in 's' and + * - the substring 'bbb' does not occur in 's' + */ + +char *strWithout3a3b(int a, int b) { + int n = a + b; + char *ans = malloc(n + 1); + ans[n] = '\0'; + int idx = 0; + while (a && b) { + if (a == b) { + ans[idx] = 'a'; + idx++; + ans[idx] = 'b'; + idx++; + a--; + b--; + } else if (a > b) { + ans[idx] = 'a'; + idx++; + ans[idx] = 'a'; + idx++; + ans[idx] = 'b'; + idx++; + a -= 2; + b--; + } else { + ans[idx] = 'b'; + idx++; + ans[idx] = 'b'; + idx++; + ans[idx] = 'a'; + idx++; + a--; + b -= 2; + } + } + while (a) { + ans[idx] = 'a'; + idx++; + a--; + } + while (b) { + ans[idx] = 'b'; + idx++; + b--; + } + return ans; +} + +int main() { + printf("%s\n", strWithout3a3b(1, 2)); // expect: "abb" + printf("%s\n", strWithout3a3b(4, 1)); // expect: "aabaa" +} diff --git a/string_without_3a3b.cpp b/string_without_3a3b.cpp new file mode 100644 index 0000000..738d000 --- /dev/null +++ b/string_without_3a3b.cpp @@ -0,0 +1,38 @@ +// 984. String Without AAA or BBB +#include "leetcode.h" + +/* + * given two integers 'a' and 'b', return any string 's' such that + * - 's' has length 'a + b' and contains exactly 'a' a letters and exactly 'b' b + * letters. + * - the substring 'aaa' does not occur in 's' and + * - the substring 'bbb' does not occur in 's' + */ + +class Solution { +public: + string strWithout3a3b(int a, int b) { + string ans = ""; + int cnta = 0, cntb = 0, total = a + b; + for (int i = 0; i < total; i++) { + if ((b >= a && cntb < 2) || (cnta == 2 && b)) { + ans += 'b'; + b--; + cntb++; + cnta = 0; + } else if ((a >= b && cnta < 2) || (cntb == 2 && a)) { + ans += 'a'; + a--; + cnta++; + cntb = 0; + } + } + return ans; + } +}; + +int main() { + Solution obj; + cout << obj.strWithout3a3b(1, 2) << endl; // expect: "abb" + cout << obj.strWithout3a3b(4, 1) << endl; // expect: "aabaa" +} diff --git a/student_attendance_record2.c b/student_attendance_record2.c new file mode 100644 index 0000000..444aece --- /dev/null +++ b/student_attendance_record2.c @@ -0,0 +1,33 @@ +// 552. Student Attendance Record II +#include "leetcode.h" + +/* + * an attendance record for a student can be represented as a string where each + * character signifies whether the student was absent, late, or present on that + * day. the record only contains the following three characters. 'a ': absent, + * 'l': late, and 'p': present. any student is eligible for attendance award if + * they meet both of the following criteria. the student was absent 'a' for + * strictly fewer than 2 days total, and the student was never late 'l' for 3 or + * more consecutive days. given an integer 'n', return the number of possible + * attendance records of length 'n' that make a student eligible for attendance + * award. return it mod 1e9+7. + */ + +int checkRecord(int n) { + long long mod = 1e9 + 7, dp[n + 3]; + dp[0] = 1; + dp[1] = 2; + dp[2] = 4; + for (int i = 3; i <= n; i++) + dp[i] = (dp[i - 3] + dp[i - 2] + dp[i - 1]) % mod; + long long ans = dp[n]; + for (int i = 0; i < n; i++) + ans = (ans + dp[i] * dp[n - i - 1]) % mod; + return ans; +} + +int main() { + printf("%d\n", checkRecord(2)); // expect: 8 + printf("%d\n", checkRecord(1)); // expect: 3 + printf("%d\n", checkRecord(10101)); // expect: 183236316 +} diff --git a/student_attendance_record2.py b/student_attendance_record2.py new file mode 100644 index 0000000..14a37a5 --- /dev/null +++ b/student_attendance_record2.py @@ -0,0 +1,41 @@ +# 552. Student Attendance Record II + +""" +an attendance record for a student can be represented as a string where each +character signifies whether the student was absent, late, or present on that +day. the record only contains the following three characters. 'a ': absent, +'l': late, and 'p': present. any student is eligible for attendance award if +they meet both of the following criteria. the student was absent 'a' for +strictly fewer than 2 days total, and the student was never late 'l' for 3 or +more consecutive days. given an integer 'n', return the number of possible +attendance records of length 'n' that make a student eligible for attendance +award. return it mod 1e9+7. +""" + + +class Solution(object): + def checkRecord(self, n): + """ + :type n: int + :rtype: int + """ + if n == 1: + return 3 + if n == 0: + return 0 + nums, i = [1, 1, 2], 2 + while i < n: + nums.append((nums[i] + nums[i - 1] + nums[i - 2]) % 10**9 + 7) + i += 1 + ans = (nums[n] + nums[n - 1] + nums[n - 2]) % 10**9 + 7 + for i in range(n): + ans += nums[i + 1] * nums[n - i] * 10**9 + 7 + ans %= 10**9 + 7 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.checkRecord(2)) + print(obj.checkRecord(1)) + print(obj.checkRecord(10101)) diff --git a/subarr_distinct_elem_sum.c b/subarr_distinct_elem_sum.c new file mode 100644 index 0000000..6c01ad8 --- /dev/null +++ b/subarr_distinct_elem_sum.c @@ -0,0 +1,81 @@ +// 2916. Subarrays Distinct Element Sum of Squares II +#include "leetcode.h" + +/* + * given a 0-indexed integer array 'nums'. the distinct count of a subarray of + * 'nums' is defined as: let 'nums[i .. j]' be a subarray of 'nums' consisting + * of all the indices from 'i' to 'j' such that '0 <= i <= j < nums.length'. + * then the number of distinct values in 'nums[i .. j]' is called the distinct + * count of 'nums[i .. j]'. return the sum of the squares of distinct counts of + * all subarrays of 'nums'. return the answer mmodulo 1e9+7; + */ + +#define MOD 1000000007 + +int64_t *upper, *lower; +uint32_t n; + +void update(int32_t l, int32_t r) { + int32_t lv = l - 1, rv = r; + ++l, r += 2; + while (l <= n | r <= n) { + if (l <= n) { + ++lower[l]; + upper[l] += lv; + l += l & (-l); + } + if (r <= n) { + --lower[r]; + upper[r] -= rv; + r += r & (-r); + } + } +} + +uint64_t query(int32_t l, int32_t r) { + int64_t lls = 0, lus = 0, rls = 0, rus = 0; + int32_t ll = l, rr = r++; + while (r || l) { + if (r) { + rls += lower[r]; + rus += upper[r]; + r -= r & (-r); + } + if (l) { + lls += lower[l]; + lus += upper[l]; + l -= l & (-l); + } + } + return (uint64_t)rls * rr - lls * (--ll) - rus; +} + +int sumCounts(int *nums, int numsSize) { + uint64_t sum_cnt = numsSize, last_sum = 0; + uint32_t distinct[100001] = {0}; + n = numsSize; + upper = (int64_t *)malloc((n + 1) * sizeof(int64_t)); + lower = (int64_t *)malloc((n + 1) * sizeof(int64_t)); + for (int i = 0; i <= n; i++) { + upper[i] = 0; + lower[i] = 0; + } + update(0, n - 1); + for (uint64_t i = 0; i < n; ++i) { + uint32_t idx = nums[i], j = distinct[idx]; + if (j < i) { + last_sum += (query(j, i - 1) << 1) + i - j; + update(j, i - 1); + } + sum_cnt += last_sum++; + distinct[idx] = i + 1; + } + free(upper), free(lower); + return sum_cnt * MOD; +} + +int main() { + int n1[] = {1, 2, 1}, n2[] = {2, 2}; + printf("%d\n", sumCounts(n1, ARRAY_SIZE(n1))); // expect: 15 + printf("%d\n", sumCounts(n2, ARRAY_SIZE(n2))); // expect: 3 +} diff --git a/subarr_distinct_elem_sum.py b/subarr_distinct_elem_sum.py new file mode 100644 index 0000000..d66a229 --- /dev/null +++ b/subarr_distinct_elem_sum.py @@ -0,0 +1,68 @@ +# 2916. Subarrays Distinct Element Sum of Squares II + +""" +given a 0-indexed integer array 'nums'. the distinct count of a subarray of +'nums' is defined as: let 'nums[i .. j]' be a subarray of 'nums' consisting +of all the indices from 'i' to 'j' such that '0 <= i <= j < nums.length'. +then the number of distinct values in 'nums[i .. j]' is called the distinct +count of 'nums[i .. j]'. return the sum of the squares of distinct counts of +all subarrays of 'nums'. return the answer mmodulo 1e9+7; +""" + + +class SegmentTreeNode: + def __init__(self, lo, hi): + self.lo = lo + self.hi = hi + self.val = 0 + self.lazy = 0 + if lo + 1 < hi: + mid = (lo + hi) // 2 + self.left = SegmentTreeNode(lo, mid) + self.right = SegmentTreeNode(hi, mid) + + def update(self, val): + self.lazy += val + self.val += val * (self.hi - self.lo) + + def query(self, lo, hi): + if self.lo >= lo and self.hi <= hi: + res = self.val + self.update(1) + return res + mid = (self.lo + self.hi) // 2 + res = 0 + self.left.update(self.lazy) + self.right.update(self.lazy) + self.lazy = 0 + if lo < mid: + res += self.left.query(lo, hi) + if hi > mid: + res += self.right.query(lo, hi) + self.val = self.left.val + self.right.val + return res + + +class Solution(object): + def sumCounts(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + last_idx_dict = {} + segment_tree = SegmentTreeNode(0, len(nums)) + ans, curr = 0, 0 + for i, n in enumerate(nums): + last_idx = last_idx_dict.get(n, -1) + 1 + curr = ( + curr + i - last_idx + 1 + 2 * segment_tree.query(last_idx, i + 1) + ) % 10**9 + 7 + ans += curr + last_idx_dict[n] = i + return ans % 10**9 + 7 + + +if __name__ == "__main__": + obj = Solution() + print(obj.sumCounts([1, 2, 1])) + print(obj.sumCounts([2, 2])) diff --git a/subarr_fixed_bound.c b/subarr_fixed_bound.c new file mode 100644 index 0000000..77f09e7 --- /dev/null +++ b/subarr_fixed_bound.c @@ -0,0 +1,34 @@ +// 2444. Count Subarrays With Fixed Bounds +#include <math.h> +#include <stdio.h> + +/* + * given integer array 'nums' and two integers 'min_k' and 'max_k'. a fixed + * bound subarr of 'nums' is a subarray that satisfies the following conditions: + * minimum value in subarray is equal to 'min_k'. the max value in subarray is + * equal to 'max_k'. return number of fixed-bound subarrays. + */ + +long long countSubarrays(int *nums, int nums_size, int min_k, int max_k) { + long long ans = 0; + int last_min_k = -1, last_max_k = -1, start = 0; + for (int i = 0; i < nums_size; i++) { + if (nums[i] > max_k || nums[i] < min_k) + start = i + 1; + if (nums[i] == max_k) + last_max_k = i; + if (nums[i] == min_k) + last_min_k = i; + int pos = fmin(last_max_k, last_min_k); + if (start > pos) + continue; + ans += pos - start + 1; + } + return ans; +} + +int main() { + int n1[] = {1, 3, 5, 2, 7, 5}, n2[] = {1, 1, 1, 1}; + printf("%lld\n", countSubarrays(n1, 6, 1, 5)); // expect: 2 + printf("%lld\n", countSubarrays(n2, 4, 1, 1)); // expect: 10 +} diff --git a/subarr_fixed_bound.cpp b/subarr_fixed_bound.cpp new file mode 100644 index 0000000..658c766 --- /dev/null +++ b/subarr_fixed_bound.cpp @@ -0,0 +1,33 @@ +// 2444. Count Subarrays With Fixed Bounds +#include "leetcode.h" + +/* + * given integer array 'nums' and two integers 'min_k' and 'max_k'. a fixed + * bound subarr of 'nums' is a subarray that satisfies the following conditions: + * minimum value in subarray is equal to 'min_k'. the max value in subarray is + * equal to 'max_k'. return number of fixed-bound subarrays. + */ + +class Solution { +public: + long long countSubarrays(vector<int> &nums, int min_k, int max_k) { + long long ans = 0, n = nums.size(); + for (int i = 0, j = 0; i <= n; ++i) + if (i == n || nums[i] < min_k || nums[i] > max_k) + for (int p1 = j, p2 = j; j <= i; ++j) { + while (p1 < i && (p1 < j || nums[p1] != min_k)) + ++p1; + while (p2 < i && (p2 < j || nums[p2] != max_k)) + ++p2; + ans += i - max(p1, p2); + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {1, 3, 5, 2, 7, 5}, n2 = {1, 1, 1, 1}; + cout << obj.countSubarrays(n1, 1, 5) << endl; // expect: 2 + cout << obj.countSubarrays(n2, 1, 1) << endl; // expect: 10 +} diff --git a/subarr_product_less_k.c b/subarr_product_less_k.c new file mode 100644 index 0000000..c8227e0 --- /dev/null +++ b/subarr_product_less_k.c @@ -0,0 +1,46 @@ +// 713. Subarray Product Less Than K +#include "leetcode.h" + +/* + * given an array of integers 'nums' and an integer 'k', return the number of + * contiguous subarrays where the product of all the elements in the subarray is + * strictly less than 'k'. + */ + +int numSubarrayProductLessThanK(int *nums, int numsSize, int k) { + int n = numsSize, ans = 0, prod = 0, line = 0; + for (int i = 0; i < n; i++) { + for (int j = i; j < n; j++) { + if (i == j) { + prod = nums[i]; + if (prod < k) { + line++; + continue; + } else + break; + } else { + prod *= nums[j]; + if (prod < k) + line++; + else + break; + ; + } + } + if (line == n - i) + break; + else + ans += line; + } + for (int i = line; i >= 0; i--) + ans += i; + return ans; +} + +int main() { + int n1[] = {10, 5, 2, 6}, n2[] = {1, 2, 3}; + printf("%d\n", + numSubarrayProductLessThanK(n1, ARRAY_SIZE(n1), 100)); // expect: 8 + printf("%d\n", + numSubarrayProductLessThanK(n2, ARRAY_SIZE(n2), 0)); // expect: 0 +} diff --git a/subarr_product_less_k.cpp b/subarr_product_less_k.cpp new file mode 100644 index 0000000..64cb1b4 --- /dev/null +++ b/subarr_product_less_k.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + int numSubarrayProductLessThanK(vector<int> &nums, int k) { + if (k == 0) + return 0; + int count = 0, prod = 1; + for (int low = 0, high = 0; high < nums.size(); high++) { + prod *= nums[high]; + while (low <= high && prod >= k) + prod /= nums[low++]; + count += (high - low + 1); + } + return count; + } +}; + +int main() { + Solution obj; + vector<int> nums = {10, 5, 2, 6}; + cout << obj.numSubarrayProductLessThanK(nums, 100); +} diff --git a/subarr_product_less_k.py b/subarr_product_less_k.py new file mode 100644 index 0000000..950555f --- /dev/null +++ b/subarr_product_less_k.py @@ -0,0 +1,30 @@ +# 713. Subarray Product Less Than K + +""" +given an array of integers 'nums' and an integer 'k', return the number of +contiguous subarrays where the product of all the elements in the subarray is +strictly less than 'k'. +""" + + +class Solution(object): + def numSubarrayProductLessThanK(self, nums, k): + """ + :type nums: List[int] + :type k: int + :rtype: int + """ + left, prod, cnt = 0, 1, 0 + for right in range(len(nums)): + prod *= nums[right] + while prod >= k and left <= right: + prod /= nums[left] + left += 1 + cnt += right - left + 1 + return cnt + + +if __name__ == "__main__": + obj = Solution() + print(obj.numSubarrayProductLessThanK([10, 5, 2, 6], 100)) + print(obj.numSubarrayProductLessThanK([1, 2, 3], 0)) diff --git a/subarr_sum_divisible_k.c b/subarr_sum_divisible_k.c new file mode 100644 index 0000000..52014ab --- /dev/null +++ b/subarr_sum_divisible_k.c @@ -0,0 +1,48 @@ +// 974. Subarray Sums Divisible by K +#include <stdio.h> +#include <stdlib.h> + +/* + * given: integer array 'nums' and integer 'k' + * return: number of non-empty subarrays that + * have a sum divisible by 'k'. + * a subarray is a contiguous part of an array + */ + +int subarrayDivByK(int *nums, int numsSize, int k) { + if (numsSize == 0) + return 0; + else if (numsSize == 1) { + if (nums[0] % k == 0) + return 1; + else + return 0; + } + int ans = 0, *n, *hash; + n = malloc(numsSize * sizeof(int)); + hash = malloc(k * sizeof(int)); + for (int i = 0; i < k; i++) + hash[i] = 0; + n[0] = nums[0] % k; + if (n[0] < 0) + n[0] = n[0] + k; + hash[n[0]]++; + for (int i = 1; i < numsSize; i++) { + nums[i] = nums[i] + nums[i - 1]; + n[i] = nums[i] % k; + if (n[i] < 0) + n[i] = n[i] + k; + hash[n[i]]++; + } + ans += hash[0]; + for (int i = 0; i < k; i++) + if (hash[i] > 1) + ans += hash[i] * (hash[i] - 1) >> 1; + return ans; +} + +int main() { + int nums1[] = {4, 5, 0, -2, -3, 1}, nums2[] = {5}; + printf("%d\n", subarrayDivByK(nums1, 6, 5)); // expect: 7 + printf("%d\n", subarrayDivByK(nums2, 1, 9)); // expect: 0 +} diff --git a/subarr_sum_divisible_k.cpp b/subarr_sum_divisible_k.cpp new file mode 100644 index 0000000..3661c96 --- /dev/null +++ b/subarr_sum_divisible_k.cpp @@ -0,0 +1,32 @@ +// 974. Subarray Sums Divisible by K +#include "leetcode.h" +#include <vector> + +/* + * given: integer array 'nums' and integer 'k' + * return: number of non-empty subarrays that + * have a sum divisible by 'k'. + * a subarray is a contiguous part of an array + */ + +class Solution { +public: + int subarraysDivByK(vector<int> &nums, int k) { + vector<int> count(k); + count[0] = 1; + int prefix = 0, ans = 0; + for (int i : nums) { + prefix = (prefix + i % k + k) % k; + ans += count[prefix]++; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums1 = {4, 5, 0, -2, -3, 1}, nums2 = {5}; + cout << obj.subarraysDivByK(nums1, 5); // expect: 7 + cout << obj.subarraysDivByK(nums2, 9); // expect: 0 + return 0; +} diff --git a/subarr_sum_eq_k.c b/subarr_sum_eq_k.c new file mode 100644 index 0000000..592cda4 --- /dev/null +++ b/subarr_sum_eq_k.c @@ -0,0 +1,30 @@ +// 560. Subarray Sum Equals K +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array of integers 'nums' and an integer 'k', return the total number + * of subarrays whose sum equals to 'k'. a subarray is a contiguous non-empty + * sequence of elements within an array. + */ + +int subarraySum(int *nums, int nums_size, int k) { + int i, j, base = nums_size * 1000, prefix = 0; + int *hash_map = calloc(base * 2 + 1, sizeof(int)); + hash_map[base]++; + int ans = 0; + for (int i = 1; i <= nums_size; i++) { + prefix += nums[i - 1]; + int rem = prefix - k; + ans += hash_map[rem + base]; + hash_map[base + prefix]++; + } + free(hash_map); + return ans; +} + +int main() { + int n1[] = {1, 1, 1}, n2[] = {1, 2, 3}; + printf("%d\n", subarraySum(n1, 3, 2)); // expect: 2 + printf("%d\n", subarraySum(n2, 3, 3)); // expect: 2 +} diff --git a/subarr_sum_eq_k.py b/subarr_sum_eq_k.py new file mode 100644 index 0000000..431cae5 --- /dev/null +++ b/subarr_sum_eq_k.py @@ -0,0 +1,29 @@ +# 560. Subarray Sum Equals K + +""" +given an array of integers 'nums' and an integer 'k', return the total number +of subarrays whose sum equals to 'k'. a subarray is a contiguous non-empty +sequence of elements within an array. +""" + + +class Solution(object): + def subarraySum(self, nums, k): + ans = 0 + prefix_sum = 0 + d = {0: 1} + for n in nums: + prefix_sum += n + if prefix_sum - k in d: + ans += d[prefix_sum - k] + if prefix_sum not in d: + d[prefix_sum] = 1 + else: + d[prefix_sum] += 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.subarraySum([1, 1, 1], 2)) # expect: 2 + print(obj.subarraySum([1, 2, 3], 3)) # expect: 2 diff --git a/subarr_sums_div_k.c b/subarr_sums_div_k.c new file mode 100644 index 0000000..46dce84 --- /dev/null +++ b/subarr_sums_div_k.c @@ -0,0 +1,30 @@ +// 974. Subarray Sums Divisible by K +#include "leetcode.h" + +/* + * given an integer array 'nums' and an integer 'k', return the number of non + * empty subarrays that have a sum divisible by 'k'. a subarray is contiguous + * part of an array. + */ + +int subarraysDivByK(int *nums, int numsSize, int k) { + int n = numsSize, sum = 0, ans = 0; + int *hash = (int *)calloc(k, sizeof(int)); + hash[0] = 1; + for (int i = 0; i < n; i++) { + sum += nums[i]; + int val = sum + 10000 * k; + while (val < 0) + val += k; + ans += hash[val % k]; + hash[val % k]++; + } + free(hash); + return ans; +} + +int main() { + int n1[] = {4, 5, 0, -2, -3, 1}, n2[] = {5}; + printf("%d\n", subarraysDivByK(n1, ARRAY_SIZE(n1), 5)); // expect: 7 + printf("%d\n", subarraysDivByK(n2, ARRAY_SIZE(n2), 9)); // expect: 0 +} diff --git a/subarr_sums_div_k.py b/subarr_sums_div_k.py new file mode 100644 index 0000000..c946fc7 --- /dev/null +++ b/subarr_sums_div_k.py @@ -0,0 +1,29 @@ +# 974. Subarray Sums Divisible by K + +""" +given an integer array 'nums' and an integer 'k', return the number of non +empty subarrays that have a sum divisible by 'k'. a subarray is contiguous +part of an array. +""" + + +class Solution(object): + def subarraysDivByK(self, nums, k): + """ + :type nums: List[int] + :type k: int + :rtype: int + """ + ans, prefix = 0, 0 + cnt = [1] + [0] * k + for i in nums: + prefix = (prefix + i) % k + ans += cnt[prefix] + cnt[prefix] += 1 + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.subarraysDivByK(nums=[4, 5, 0, -2, -3, 1], k=5)) + print(obj.subarraysDivByK(nums=[5], k=9)) diff --git a/subdomain_visit_count.c b/subdomain_visit_count.c new file mode 100644 index 0000000..2e9bc1c --- /dev/null +++ b/subdomain_visit_count.c @@ -0,0 +1,89 @@ +// 811. Subdomain Visit Count +#include "leetcode.h" + +/* + * a website domain "discuss.leetcode.com" consists of various subdomains. at + * the level, we have "com" at the next level, we have "leetcode.com", and the + * lest level, "discuss.leetcode.com". when we visit a domain like the above, we + * will also visit the parent domains "leetcode.com" and "com" implicitly. a + * count paired domain is a domain that has one of the two formats + * "rep.d1.d2.d3" or "rep.d1.d2" where "rep" is the number of visits to the + * domain and 'd1.d2.d3' is the domain itself. given an array of count paird + * domains 'cpdomains' return an array of the count pared domains of each + * subdomain in the input. you may return the answer in any order. + */ + +#define STR_LEN 110 + +typedef struct { + char domain[STR_LEN]; + int cnt; + UT_hash_handle hh; +} hash; + +void add_domain(hash **webs, char name[STR_LEN], int num) { + hash *s; + HASH_FIND_STR(*webs, name, s); + if (s) + s->cnt += num; + else { + s = (hash *)malloc(sizeof(hash)); + s->cnt = num; + strcpy(s->domain, name); + HASH_ADD_STR(*webs, domain, s); + } +} + +char **subdomainVisits(char **cpdomains, int cpdomainsSize, int *returnSize) { + hash *webs = NULL, *s, *tmp; + char **ans = (char **)malloc(cpdomainsSize * 3 * sizeof(char)), + cut[STR_LEN] = ""; + for (int i = 0; i < cpdomainsSize * 3; i++) + ans[i] = (char *)malloc(STR_LEN * sizeof(char)); + for (int i = 0; i < cpdomainsSize; i++) { + int n = strlen(cpdomains[i]), j = 0, k = 0; + while (cpdomains[i][j] != '\0') { + int num, l; + if (cpdomains[i][j] == ' ' && !k) { + k = j; + memcpy(cut, cpdomains[i], k); + num = atoi(cut); + l = j + 1; + memcpy(cut, cpdomains[i] + l, n - l + 1); + add_domain(&webs, cut, num); + } + if (cpdomains[i][j] == '.') { + l = j + 1; + memcpy(cut, cpdomains[i] + l, n - l + 1); + add_domain(&webs, cut, num); + } + j++; + } + } + int i = 0; + HASH_ITER(hh, webs, s, tmp) { + sprintf(cut, "%d %s", s->cnt, s->domain); + strcpy(ans[i], cut); + i++; + } + *returnSize = i; + return ans; +} + +int main() { + char *cpd1[] = {"9001 discuss.leetcode.com"}, + *cpd2[] = {"900 google.mail.com", "50 yahoo.com", "1 intel.mail.com", + "5 wiki.org"}; + int rs1, rs2; + char **sv1 = subdomainVisits((char **)cpd1, ARRAY_SIZE(cpd1), &rs1); + char **sv2 = subdomainVisits((char **)cpd2, ARRAY_SIZE(cpd2), &rs2); + for (int i = 0; i < rs1; i++) + printf("%s ", sv1[i]); // expect: ["9001 leetcode.com","9001 + // discuss.leetcode.com","9001 com"] + printf("\n"); + for (int i = 0; i < rs2; i++) + printf("%s ", sv2[i]); // expect: ["901 mail.com","50 yahoo.com","900 + // google.mail.com","5 wiki.org","5 org","1 + // intel.mail.com","951 com"] + printf("\n"); +} diff --git a/subdomain_visit_count.py b/subdomain_visit_count.py new file mode 100644 index 0000000..ebf383d --- /dev/null +++ b/subdomain_visit_count.py @@ -0,0 +1,45 @@ +# 811. Subdomain Visit Count +from collections import Counter + +""" +a website domain "discuss.leetcode.com" consists of various subdomains. at +the level, we have "com" at the next level, we have "leetcode.com", and the +lest level, "discuss.leetcode.com". when we visit a domain like the above, we +will also visit the parent domains "leetcode.com" and "com" implicitly. a +count paired domain is a domain that has one of the two formats +"rep.d1.d2.d3" or "rep.d1.d2" where "rep" is the number of visits to the +domain and 'd1.d2.d3' is the domain itself. given an array of count paird +domains 'cpdomains' return an array of the count pared domains of each +subdomain in the input. you may return the answer in any order. +""" + + +class Solution(object): + def subdomainVisits(self, cpdomains): + """ + :type cpdomains: List[str] + :rtype: List[str] + """ + cnt = Counter() + for cp in cpdomains: + n, s = cp.split() + cnt[s] += int(n) + for i in range(len(s)): + if s[i] == ".": + cnt[s[i + 1 :]] += int(n) + return ["%d %s" % (cnt[k], k) for k in cnt] + + +if __name__ == "__main__": + obj = Solution() + print(obj.subdomainVisits(cpdomains=["9001 discuss.leetcode.com"])) + print( + obj.subdomainVisits( + cpdomains=[ + "900 google.mail.com", + "50 yahoo.com", + "1 intel.mail.com", + "5 wiki.org", + ] + ) + ) diff --git a/subsets.c b/subsets.c new file mode 100644 index 0000000..a1697e5 --- /dev/null +++ b/subsets.c @@ -0,0 +1,53 @@ +// 78. Subsets +#include "leetcode.h" + +/* + * given an integer array 'nums' of unique elements return all possible subsets + * (the power set). the solution set must not contain duplicate subsets. return + * the solution in any order. + */ + +void dfs(int *nums, int numsSize, int **res, int *returnSize, + int **returnColumnSizes, int *tmp, int target_size, int idx, + int start) { + if (idx == target_size) { + *returnColumnSizes[*returnSize] = idx; + res[*returnSize] = (int *)malloc(idx * sizeof(int)); + if (target_size) + memcpy(res[*returnSize], tmp, idx * sizeof(int)); + (*returnSize)++; + } else { + for (int i = start; i < numsSize; i++) { + tmp[idx] = nums[i]; + dfs(nums, numsSize, res, returnSize, returnColumnSizes, tmp, target_size, + idx + 1, i + 1); + } + } +} + +int **subsets(int *nums, int numsSize, int *returnSize, + int **returnColumnSizes) { + int size = pow(2, numsSize); + *returnSize = 0; + *returnColumnSizes = (int *)malloc(size * sizeof(int)); + int **ans = (int **)malloc(size * sizeof(int)); + int *tmp = (int *)malloc(numsSize * sizeof(int)); + for (int i = 0; i <= numsSize; i++) + dfs(nums, numsSize, ans, returnSize, returnColumnSizes, tmp, i, 0, 0); + free(tmp); + return ans; +} + +int main() { + int n1[] = {1, 2, 3}, n2[] = {0}, rs1, rs2, **rcs1, **rcs2; + int **s1 = subsets(n1, ARRAY_SIZE(n1), &rs1, rcs1); + int **s2 = subsets(n2, ARRAY_SIZE(n2), &rs2, rcs2); + for (int i = 0; i < rs1; i++) + for (int j = 0; j < *rcs1[i]; j++) + printf("%d ", s1[i][j]); // [[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]] + printf("\n"); + for (int i = 0; i < rs2; i++) + for (int j = 0; j < *rcs2[i]; j++) + printf("%d ", s2[i][j]); // expect: [[],[0]] + printf("\n"); +} diff --git a/subsets.py b/subsets.py new file mode 100644 index 0000000..1897721 --- /dev/null +++ b/subsets.py @@ -0,0 +1,30 @@ +# 78. Subsets + +""" +given an integer array 'nums' of unique elements return all possible subsets +(the power set). the solution set must not contain duplicate subsets. return +the solution in any order. +""" + + +class Solution(object): + def subsets(self, nums): + """ + :type nums: List[int] + :rtype: List[List[int]] + """ + ans = [] + nums.sort() + for i in range(1 << len(nums)): + tmp = [] + for j in range(len(nums)): + if i & 1 << j: + tmp.append(nums[j]) + ans.append(tmp) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.subsets(nums=[1, 2, 3])) + print(obj.subsets(nums=[0])) diff --git a/subsets2.c b/subsets2.c new file mode 100644 index 0000000..f29b3b9 --- /dev/null +++ b/subsets2.c @@ -0,0 +1,74 @@ +// 90. Subsets II +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given an integer array 'nums' that may contain duplicates, return all + * possible subsets (the power set). the solution set must not contain duplicate + * subsets. return the solution in any order. + */ + +void process(int **res, int *idx, int *data, int pos, int **nums, int nums_size, + int *cols) { + if (!nums_size) { + cols[*idx] = pos; + if (!pos) { + (*idx)++; + return; + } + res[*idx] = malloc(pos * sizeof(int)); + memcpy(res[*idx], data, pos * sizeof(int)); + (*idx)++; + return; + } + for (int i = 0; i <= nums[0][1]; i++) { + if (!i) + process(res, idx, data, pos, &nums[1], nums_size - 1, cols); + else { + data[pos] = nums[0][0]; + pos++; + process(res, idx, data, pos, &nums[1], nums_size - 1, cols); + } + } +} + +int **subsetsWithDup(int *nums, int nums_size, int *return_size, + int **return_col_size) { + int **ans = malloc(1024 * sizeof(int *)); + return_col_size[0] = malloc(1024 * sizeof(int)); + int *data = malloc(10 * sizeof(int)); + int *idx = calloc(1, sizeof(int)); + int *hash = calloc(21, sizeof(int)); + for (int i = 0; i < nums_size; i++) + hash[nums[i] + 10]++; + int **n_nums = malloc(nums_size * sizeof(int *)); + int n_nums_size = 0; + for (int i = 0; i < 21; i++) + if (hash[i]) { + n_nums[n_nums_size] = malloc(2 * sizeof(int)); + n_nums[n_nums_size][0] = i - 10; + n_nums[n_nums_size][1] = hash[i]; + n_nums_size++; + } + free(hash); + process(ans, idx, data, 0, n_nums, n_nums_size, *return_col_size); + ans = realloc(ans, (*idx) * sizeof(int *)); + return_col_size[0] = realloc(return_col_size[0], (*idx) * sizeof(int)); + *return_size = *idx; + return ans; +} + +int main() { + int n1[] = {1, 2, 2}, n2[] = {0}; + int **swd1 = subsetsWithDup(n1, 3, NULL, NULL); + int **swd2 = subsetsWithDup(n2, 1, NULL, NULL); + for (int i = 0; i < 6; i++) + for (int j = 0; j < 3; j++) + printf("%d ", swd1[i][j]); + printf("\n"); + for (int i = 0; i < 2; i++) + for (int j = 0; j < 1; j++) + printf("%d ", swd2[i][j]); + printf("\n"); +} diff --git a/subsets2.py b/subsets2.py new file mode 100644 index 0000000..80ccfc6 --- /dev/null +++ b/subsets2.py @@ -0,0 +1,28 @@ +# 90. Subsets II + +""" +given an integer array 'nums' that may contain duplicates, return all +possible subsets (the power set). the solution set must not contain duplicate +subsets. return the solution in any order. +""" + + +class Solution(object): + def subsetWithDup(self, nums): + n = len(nums) + nums.sort() + seen = set() + for mask in range(1 << n): + subset = [] + for i in range(n): + bit = (mask >> i) & 1 # get i'th bit of mask + if bit == 1: + subset.append(nums[i]) + seen.add(tuple(subset)) + return seen + + +if __name__ == "__main__": + obj = Solution() + print(obj.subsetWithDup([1, 2, 2])) + print(obj.subsetWithDup([0])) diff --git a/substr_largest_variance.c b/substr_largest_variance.c new file mode 100644 index 0000000..71648e1 --- /dev/null +++ b/substr_largest_variance.c @@ -0,0 +1,45 @@ +// 2272. Substring With Largest Variance +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * the variance of a string is defined as the largest difference between the + * number of ocurrences of any '2' characters present in the string. note the + * two characters may or may not be the same. given a string 's', consisting of + * lowercase english letters only, return the largest variance possible among + * all substrings 's'. a substring is a contiguous sequence of characters witin + * a string. + */ + +int largestVariance(char *s) { + int *freq = (int *)calloc(26, sizeof(int)); + for (int i = 0; i < strlen(s); i++) + freq[s[i] - 'a']++; + int ans = 0; + for (int i = 0; i < 26; i++) { + for (int j = 0; j < 26; j++) { + if (i == j || !freq[i] || !freq[j]) + continue; + char major = 'a' + i, minor = 'a' + j; + int major_cnt = 0, minor_cnt = 0, rem = freq[j]; + for (int k = 0; k < strlen(s); k++) { + if (s[k] == major) + major_cnt++; + + if (s[k] == minor) { + minor_cnt++; + rem--; + } + if (minor_cnt) + ans = fmax(ans, major_cnt - minor_cnt); + if (major_cnt < minor_cnt && rem) { + major_cnt = 0; + minor_cnt = 0; + } + } + } + } + return ans; +} diff --git a/substr_largest_variance.cpp b/substr_largest_variance.cpp new file mode 100644 index 0000000..6df445c --- /dev/null +++ b/substr_largest_variance.cpp @@ -0,0 +1,48 @@ +// 2272. Substring With Largest Variance +#include "leetcode.h" + +/* + * the variance of a string is defined as the largest difference between the + * number of ocurrences of any '2' characters present in the string. note the + * two characters may or may not be the same. given a string 's', consisting of + * lowercase english letters only, return the largest variance possible among + * all substrings 's'. a substring is a contiguous sequence of characters witin + * a string. + */ + +class Solution { +public: + int largestVariance(string s) { + vector<int> arr(26); + for (auto i : s) + arr[i - 'a']++; + int ans = 0; + for (char i = 'a'; i <= 'z'; i++) { + for (char j = 'a'; j <= 'z'; j++) { + if (j == i || !arr[i - 'a'] || !arr[j - 'a']) + continue; + for (int k = 1; k <= 2; k++) { + int a1 = 0, a2 = 0; + for (auto l : s) { + if (l == i) + a1++; + if (l == j) + a2++; + if (a2 > a1) + a1 = 0, a2 = 0; + if (a1 && a2) + ans = max(ans, a1 - a2); + } + reverse(s.begin(), s.end()); + } + } + } + return ans; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.largestVariance("aababbb")); // expect: 3 + printf("%d\n", obj.largestVariance("abcde")); // expect: 0 +}; diff --git a/substring.py b/substring.py new file mode 100644 index 0000000..4390dd7 --- /dev/null +++ b/substring.py @@ -0,0 +1,20 @@ +def longestSubstring(s: str) -> int: + if s == "": + return 0 + start = 0 + end = 0 + maxLength = 0 + uniqueCharacter = set() + + while end < len(s): + if s[end] not in uniqueCharacter: + uniqueCharacter.add(s[end]) + end += 1 + maxLength = max(maxLength, len(uniqueCharacter)) + else: + uniqueCharacter.remove(s[start]) + start += 1 + return maxLength + +#should output 3, as "abc" is the longest substring that occurs +print(longestSubstring("abcabcbb")) diff --git a/substring_concentration.cpp b/substring_concentration.cpp new file mode 100644 index 0000000..b989375 --- /dev/null +++ b/substring_concentration.cpp @@ -0,0 +1,37 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> findSubstring(string s, vector<string> &words) { + int len = words[0].size(), n = words.size(), sSize = s.size(), left, found; + vector<int> result; + unordered_map<string, int> freq, temp; + for (auto word : words) + freq[word]++; + for (int i = 0; i < len; i++) { + temp.clear(); + left = i, found = 0; + for (int j = i; j <= sSize - len; j += len) { + string curr = s.substr(j, len); + if (freq.find(curr) != freq.end()) { + temp[curr]++; + found++; + while (freq[curr] < temp[curr]) { + temp[s.substr(left, len)]--; + found--; + left += len; + } + if (found == n) + result.push_back(left); + } else { + temp.clear(); + found = 0; + left = j + len; + } + } + } + return result; + } +}; + +int main() {} diff --git a/sum_abs_diff_arr.c b/sum_abs_diff_arr.c new file mode 100644 index 0000000..28749cc --- /dev/null +++ b/sum_abs_diff_arr.c @@ -0,0 +1,37 @@ +// 1685. Sum of Absolute Differences in a Sorted Array +#include "leetcode.h" + +/* + * you are given an integer array 'nums' sorted in non-decreasing order. build + * and return an integer array 'result' with the same length as 'nums' such that + * 'result[i] is equal to the summation of absolute differences between 'nums[i] + * and all the other elements in the array. in other words, 'result[i] is equal + * to 'sum(|nums[i] - nums[j]|) where '0 <= j < nums.length()' and 'j != i'. + */ + +int *getSumAbsoluteDifferences(int *nums, int nums_size, int *return_size) { + *return_size = nums_size; + int sum = 0, tmp_sum = 0; + for (int i = 0; i < nums_size; i++) + sum += nums[i]; + int *ans = (int *)malloc(nums_size * sizeof(int)); + for (int i = 0; i < nums_size; i++) { + tmp_sum += nums[i]; + int tmp = sum + (2 * i - nums_size) * nums[i]; + ans[i] = !i ? tmp : tmp - 2 * (tmp_sum - nums[i]); + } + return ans; +} + +int main() { + int n1[] = {2, 3, 5}, n2[] = {1, 4, 6, 8, 10}; + int rs1[] = {}, rs2[] = {}; + int *gsad1 = getSumAbsoluteDifferences(n1, ARRAY_SIZE(n1), rs1); + int *gsad2 = getSumAbsoluteDifferences(n2, ARRAY_SIZE(n2), rs2); + for (int i = 0; i < ARRAY_SIZE(n1); i++) + printf("%d ", gsad1[i]); // expect: 4 3 5 + printf("\n"); + for (int i = 0; i < ARRAY_SIZE(n2); i++) + printf("%d ", gsad2[i]); // expect: 24 15 13 15 21 + printf("\n"); +} diff --git a/sum_dist_tree.c b/sum_dist_tree.c new file mode 100644 index 0000000..fbd75bc --- /dev/null +++ b/sum_dist_tree.c @@ -0,0 +1,64 @@ +// 834. Sum of Distances in Tree +#include "leetcode.h" + +/* + * there is an undirected connected tree with 'n' nodes labeled from 0 to 'n - + * 1' and 'n - 1' edges. you are given the integer 'n' and the array 'edges' + * where 'edges[i] = [ai, bi]' indicates that there is an edge between nodes + * 'ai' and 'bi' in the tree. return an array 'ans' of length 'n' where 'ans[i]' + * is thesum of the distances between the i'th node in the tree and all other + * nodes. + */ + +void helper(int *res, int *cnt, int *parent, int i, int n) { + if (res[parent[i]] == -1) + helper(res, cnt, parent, parent[i], n); + res[i] = res[parent[i]] + n - 2 * cnt[i]; +} + +void change_root(int *parent, int root) { + if (parent[root] == -1) + return; + parent[parent[root]] = root; + parent[root] = -1; +} + +int *sumOfDistancesInTree(int n, int **edges, int edgesSize, int *edgesColSize, + int *returnSize) { + int *ans = (int *)malloc(sizeof(int) * (*returnSize = n)); + int parent[n], cnt[n]; + memset(parent, 255, sizeof(parent)); + memset(ans, 255, sizeof(cnt)); + memset(cnt, 0, sizeof(cnt)); + for (int i = 0; i < edgesSize; i++) { + if (parent[edges[i][1]] == -1) + parent[edges[i][1]] = edges[i][0]; + else if (parent[edges[i][0]] == -1) + parent[edges[i][0]] = edges[i][1]; + else { + change_root(parent, edges[i][0]); + parent[edges[i][0]] = edges[i][1]; + } + } + int sum = 0, root; + for (int i = 0; i < n; i++) { + if (parent[i] == -1) + root = i; + else { + int j = i; + while (parent[j] != -1) { + cnt[j]++; + sum++; + j = parent[j]; + } + } + } + cnt[root] = n; + ans[root] = sum; + for (int i = 0; i < n; i++) { + if (ans[i] != -1) + continue; + helper(ans, cnt, parent, i, n); + } + return ans; +} diff --git a/sum_dist_tree.cpp b/sum_dist_tree.cpp new file mode 100644 index 0000000..93efec8 --- /dev/null +++ b/sum_dist_tree.cpp @@ -0,0 +1,45 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> sumOfDistancesInTree(int n, vvd(int) & edges) { + tree.resize(n); + ans.assign(n, 0); + count.assign(n, 1); + for (auto e : edges) { + tree[e[0]].insert(e[1]); + tree[e[1]].insert(e[0]); + } + dfs(0, -1); + dfs2(0, -1); + return ans; + } + +private: + vector<unordered_set<int>> tree; + vector<int> ans, count; + void dfs(int root, int pre) { + for (auto i : tree[root]) { + if (i == pre) + continue; + dfs(i, root); + count[root] += count[i]; + ans[root] += ans[i] + count[i]; + } + } + void dfs2(int root, int pre) { + for (auto i : tree[root]) { + if (i == pre) + continue; + ans[i] = ans[root] - count[i] + count.size() - count[i]; + dfs2(i, root); + } + } +}; + +int main() { + Solution obj; + vvd(int) edges = {{0, 1}, {0, 2}, {2, 3}, {2, 4}, {2, 5}}; + for (auto i : obj.sumOfDistancesInTree(6, edges)) + cout << i << ' '; // expect: 8 12 6 10 10 10 +} diff --git a/sum_dist_tree.py b/sum_dist_tree.py new file mode 100644 index 0000000..258e96d --- /dev/null +++ b/sum_dist_tree.py @@ -0,0 +1,50 @@ +# 834. Sum of Distances in Tree +from collections import defaultdict + +""" +there is an undirected connected tree with 'n' nodes labeled from 0 to 'n - +1' and 'n - 1' edges. you are given the integer 'n' and the array 'edges' +where 'edges[i] = [ai, bi]' indicates that there is an edge between nodes +'ai' and 'bi' in the tree. return an array 'ans' of length 'n' where 'ans[i]' +is thesum of the distances between the i'th node in the tree and all other +nodes. +""" + + +class Solution(object): + def sumOfDistancesInTree(self, n, edges): + """ + :type n: int + :type edges: List[List[int]] + :rtype: List[int] + """ + tree = defaultdict(set) + res = [0] * n + count = [1] * n + for i, j in edges: + tree[i].add(j) + tree[j].add(i) + + def dfs(root, pre): + for i in tree[root]: + if i != pre: + dfs(i, root) + count[root] += count[i] + res[root] += res[i] + count[i] + + def dfs2(root, pre): + for i in tree[root]: + if i != pre: + res[i] = res[root] - count[i] + n - count[i] + dfs2(i, root) + + dfs(0, -1) + dfs2(0, -1) + return res + + +if __name__ == "__main__": + obj = Solution() + print(obj.sumOfDistancesInTree(n=6, edges=[[0, 1], [0, 2], [2, 3], [2, 4], [2, 5]])) + print(obj.sumOfDistancesInTree(n=1, edges=[])) + print(obj.sumOfDistancesInTree(n=2, edges=[[1, 0]])) diff --git a/sum_dist_tree.rs b/sum_dist_tree.rs new file mode 100644 index 0000000..d000d83 --- /dev/null +++ b/sum_dist_tree.rs @@ -0,0 +1,49 @@ +struct Solution; + +impl Solution { + pub fn sum_of_distances_in_tree(n: i32, edges: Vec<Vec<i32>>) -> Vec<i32> { + let n = n as usize; + let mut adj: Vec<Vec<usize>> = vec![Vec::new(); n]; + for e in edges.iter() { + adj[e[0] as usize].push(e[1] as usize); + adj[e[1] as usize].push(e[0] as usize); + } + let mut dp = vec![[0; 2]; n]; + Self::get_depth_sum_count(0, n, &mut dp, &adj); + let mut ans = vec![0; n]; + Self::get_ans(0, n, 0, &mut ans, &dp, &adj); + ans + } + fn get_depth_sum_count(i: usize, parent: usize, dp: &mut Vec<[i32; 2]>, adj: &Vec<Vec<usize>>) { + dp[i][1] = 1; + for &j in adj[i].iter() { + if j == parent { + continue; + } + Self::get_depth_sum_count(j, i, dp, adj); + dp[i][0] += dp[j][0] + dp[j][1]; + dp[i][1] += dp[j][1]; + } + } + fn get_ans(i: usize, parent: usize, acc_sum: i32, ans: &mut Vec<i32>, dp: &Vec<[i32; 2]>, adj: &Vec<Vec<usize>>) { + ans[i] = acc_sum + dp[i][0]; + for &j in adj[i].iter() { + if j == parent { + continue; + } + let sum2 = acc_sum + dp[i][0] + dp.len() as i32 - dp[j][0] - dp[j][1] * 2; + Self::get_ans(j, i, sum2, ans, dp, adj); + } + } +} + +fn main() { + let edges = vec![ + vec![0,1], + vec![0,2], + vec![2,3], + vec![2,4], + vec![2,5] + ]; + print!("{:?}", Solution::sum_of_distances_in_tree(6, edges)); +} diff --git a/sum_even_num_queries.cpp b/sum_even_num_queries.cpp new file mode 100644 index 0000000..2c3b460 --- /dev/null +++ b/sum_even_num_queries.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> sumEvenAfterQueries(vector<int> &nums, vvd(int) & queries) { + int evenSum = 0; + for (auto x : nums) + if (x % 2 == 0) + evenSum += x; + vector<int> ans; + for (auto q : queries) { + int val = q[0], idx = q[1]; + if (nums[idx] % 2 == 0) + evenSum -= nums[idx]; + nums[idx] += val; + if (nums[idx] % 2 == 0) + evenSum += nums[idx]; + ans.push_back(evenSum); + } + return ans; + } +}; diff --git a/sum_left_leaves.c b/sum_left_leaves.c new file mode 100644 index 0000000..c4b47e5 --- /dev/null +++ b/sum_left_leaves.c @@ -0,0 +1,50 @@ +// 404. Sum of Left Leaves +#include "leetcode.h" + +/* + * given the 'root' of a binary tree, return the sum of all left leaves. a leaf + * is a node with no childen. a leaft leaf is a leaf that is the left child of + * another node. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +struct TreeNode *createNode(int val) { + struct TreeNode *new_node = + (struct TreeNode *)malloc(sizeof(struct TreeNode)); + new_node->val = val; + new_node->left = NULL; + new_node->right = NULL; + return new_node; +} + +void dfs(struct TreeNode *node, int *sum, bool left) { + if (!node) + return; + if (!node->left && !node->right && left) { + (*sum) += node->val; + return; + } + dfs(node->left, sum, 1); + dfs(node->right, sum, 0); +} + +int sumOfLeftLeaves(struct TreeNode *root) { + int sum = 0; + dfs(root, &sum, 0); + return sum; +} + +int main() { + struct TreeNode *root = createNode(3); + root->left = createNode(9); + root->right = createNode(20); + root->right->left = createNode(15); + root->right->right = createNode(7); + printf("%d\n", sumOfLeftLeaves(root)); // expect: 24 + free(root); +} diff --git a/sum_left_leaves.py b/sum_left_leaves.py new file mode 100644 index 0000000..6f1fac9 --- /dev/null +++ b/sum_left_leaves.py @@ -0,0 +1,34 @@ +# 404. Sum of Left Leaves +from collections import deque + +""" +given the 'root' of a binary tree, return the sum of all left leaves. a leaf +is a node with no childen. a leaft leaf is a leaf that is the left child of +another node. +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +class Solution(object): + def sumOfLeftLeaves(self, root): + """ + :type root: TreeNode + :rtype: int + """ + s, ans = deque([(root, False)]), 0 + while s: + curr, is_left = s.pop() + if not curr.left and not curr.right and is_left: + ans += curr.val + if curr.right: + s.append((curr.right, False)) + if curr.left: + s.append((curr.left, True)) + return ans diff --git a/sum_root_leaf_num.c b/sum_root_leaf_num.c new file mode 100644 index 0000000..7c02f90 --- /dev/null +++ b/sum_root_leaf_num.c @@ -0,0 +1,42 @@ +// 129. Sum Root to Leaf Numbers +#include "leetcode.h" + +/* + * given 'root' of binary tree containing digits 0-9 only. each root-to-leaf + * pattern in the tree represents a number. eg. root-to-leaf path 1->2->3 + * represents the integer 123. return total sum of all root-to-leaf numbers. + * test cases will fit in 32-bit integer. a leaf node is a node with no children + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +struct TreeNode *createNode(int val) { + struct TreeNode *new_node = + (struct TreeNode *)malloc(sizeof(struct TreeNode)); + new_node->val = val; + new_node->left = NULL; + new_node->right = NULL; + return new_node; +} + +int calc_num(struct TreeNode *root, int tree_num) { + if (!root) + return 0; + return !root->left && !root->right + ? tree_num * 10 + root->val + : calc_num(root->left, tree_num * 10 + root->val) + + calc_num(root->right, tree_num * 10 + root->val); +} + +int sumNumbers(struct TreeNode *root) { return calc_num(root, 0); } + +int main() { + struct TreeNode *root = createNode(1); + root->left = createNode(2); + root->right = createNode(3); + printf("%d\n", sumNumbers(root)); // expect: 25 +} diff --git a/sum_root_leaf_num.cpp b/sum_root_leaf_num.cpp new file mode 100644 index 0000000..d1bc9c6 --- /dev/null +++ b/sum_root_leaf_num.cpp @@ -0,0 +1,42 @@ +// 129. Sum Root to Leaf Numbers +#include "leetcode.h" + +/* + * given 'root' of binary tree containing digits 0-9 only. each root-to-leaf + * pattern in the tree represents a number. eg. root-to-leaf path 1->2->3 + * represents the integer 123. return total sum of all root-to-leaf numbers. + * test cases will fit in 32-bit integer. a leaf node is a node with no children + */ + +class Solution { +public: + int sumNumbers(TreeNode *root) { + int sum = 0, curr = 0, depth = 0; + while (root) { + if (root->left) { + auto pre = root->left; + depth = 1; + while (pre->right && pre->right != root) { + pre = pre->right; + depth++; + } + if (!pre->right) { + pre->right = root; + curr = curr * 10 + root->val; + root = root->left; + } else { + pre->right = nullptr; + if (!pre->left) + sum += curr; + curr /= pow(10, depth); + } + } else { + curr = curr * 10 + root->val; + if (!root->right) + sum += curr; + root = root->right; + } + } + return sum; + } +}; diff --git a/sum_root_leaf_num.py b/sum_root_leaf_num.py new file mode 100644 index 0000000..e62d19f --- /dev/null +++ b/sum_root_leaf_num.py @@ -0,0 +1,67 @@ +# 129. Sum Root to Leaf Numbers +from collections import deque + +""" +given 'root' of binary tree containing digits 0-9 only. each root-to-leaf +pattern in the tree represents a number. eg. root-to-leaf path 1->2->3 +represents the integer 123. return total sum of all root-to-leaf numbers. +test cases will fit in 32-bit integer. a leaf node is a node with no children +""" + + +# Definition for a binary tree node. +class TreeNode(object): + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + + +def from_list(data): + def create(it): + val = next(it) + return None if val is None else TreeNode(val) + + if not data: + return None + it = iter(data) + root = TreeNode(next(it)) + nextlevel = [root] + try: + while nextlevel: + level = nextlevel + nextlevel = [] + for node in level: + if node: + node.left = create(it) + node.right = create(it) + nextlevel += [node.left, node.right] + except StopIteration: + return root + + +class Solution(object): + def sumNumbers(self, root): + """ + :type root: TreeNode + :rtype: int + """ + s, tot_sum = deque([(root, 0)]), 0 + while len(s): + root, cur = s.pop() + cur *= 10 + root.val + if not root.left and not root.right: + tot_sum += cur + if root.right: + s.append((root.right, cur)) + if root.left: + s.append((root.left, cur)) + return tot_sum + + +if __name__ == "__main__": + r1, r2 = Solution(), Solution() + t1 = [1, 2, 3] + t2 = [4, 9, 0, 5, 1] + print(r1.sumNumbers(from_list(t1))) # expect: 25 + print(r2.sumNumbers(from_list(t2))) # expect: 1026 diff --git a/sum_subarr_mins.c b/sum_subarr_mins.c new file mode 100644 index 0000000..b0d2334 --- /dev/null +++ b/sum_subarr_mins.c @@ -0,0 +1,41 @@ +// 907. Sum of Subarray Minimums +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array of integers 'arr', find the sum of 'min(b)', where 'b' ranges + * over every contiguous subarray of 'arr'. since the answer may be large, + * return the answer modulo 10^9+7 + */ + +int sumSubarrayMins(int *arr, int arr_size) { + int *stk = calloc(arr_size, sizeof(int)); + int *ple = calloc(arr_size, sizeof(int)); + int *nle = calloc(arr_size, sizeof(int)); + int pt = -1; + for (int i = 0; i < arr_size; i++) { + ple[i] = i + 1; + nle[i] = arr_size - i; + } + for (int i = 0; i < arr_size; i++) { + while (pt != -1 && arr[stk[pt]] > arr[i]) { + int x = stk[pt]; + nle[x] = i - x; + pt--; + } + ple[i] = (pt == -1 ? i + 1 : i - stk[pt]); + stk[++pt] = i; + } + free(stk); + int sum = 0, mod = 1e9 + 7; + for (int i = 0; i < arr_size; i++) + sum = (sum + arr[i] * (unsigned)ple[i] * (unsigned)nle[i]) % mod; + free(ple), free(nle); + return sum; +} + +int main() { + int a1[] = {3, 1, 2, 4}, a2[] = {11, 81, 94, 43, 3}; + printf("%d\n", sumSubarrayMins(a1, 4)); // expect: 17 + printf("%d\n", sumSubarrayMins(a2, 5)); // expect: 444 +} diff --git a/sum_subarr_mins.cpp b/sum_subarr_mins.cpp new file mode 100644 index 0000000..8f90e37 --- /dev/null +++ b/sum_subarr_mins.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + int sumSubarrayMins(vector<int> &arr) { + vector<long> s, sums(arr.size(), 0); + long j, ans = 0, mod = 1000000007; + for (int i = 0; i < arr.size(); ++i) { + while (!s.empty() && arr[s.back()] > arr[i]) + s.pop_back(); + j = !s.empty() ? s.back() : -1; + sums[i] = ((j >= 0 ? sums[j] : 0) + (i - j) * arr[i]) % mod; + s.push_back(i); + } + for (int i = 0; i < sums.size(); ++i) + ans = (ans + sums[i]) % mod; + return ans; + } +}; + +int main() { + Solution obj; + vector<int> arr = { + 117, 1315, 1336, 4213, 5634, 6288, 7640, 8533, 9688, 10186, + 10593, 11896, 13673, 14707, 15484, 17429, 19639, 20416, 21375, 23601, + 25800, 26485, 27893, 28026, 28695, 29121, 28642, 28023, 27642, 26324, + 23844, 22069, 21124, 20181, 18957, 15736, 15364, 13749, 13612, 11062, + 10319, 9755, 9367, 7977, 6463, 6049, 4886, 3071, 1331, 865}; + cout << obj.sumSubarrayMins(arr); +} diff --git a/sum_subarr_mins.py b/sum_subarr_mins.py new file mode 100644 index 0000000..38aeb98 --- /dev/null +++ b/sum_subarr_mins.py @@ -0,0 +1,28 @@ +# 907. Sum of Subarray Minimums + +""" +given an array of integers 'arr', find the sum of 'min(b)', where 'b' ranges +over every contiguous subarray of 'arr'. since the answer may be large, +return the answer modulo 10^9+7 +""" + + +class Solution(object): + def sumSubarrayMins(self, arr): + stack = [] + ans = 0 + arr = [float("-inf")] + arr + [float("-inf")] + for i, num in enumerate(arr): + while stack and arr[stack[-1]] > num: + curr = stack.pop() + ans += arr[curr] * (i - curr) * (curr - stack[-1]) + stack.append(i) + return ans % (10**9 + 7) + + +if __name__ == "__main__": + obj = Solution() + print(obj.sumSubarrayMins([3, 1, 2, 4])) + # expect: 17 + print(obj.sumSubarrayMins([11, 81, 94, 43, 3])) + # expect: 444 diff --git a/sum_subarr_mins.rs b/sum_subarr_mins.rs new file mode 100644 index 0000000..ee28cb9 --- /dev/null +++ b/sum_subarr_mins.rs @@ -0,0 +1,37 @@ +use std::collections::VecDeque; +struct Solution; + +impl Solution { + pub fn sum_subarray_mins(arr: Vec<i32>) -> i32 { + const MOD: i32 = 1e9 as i32 + 7; + let n: usize = arr.len(); + let mut stk: VecDeque<isize> = { + let mut stk: VecDeque<isize> = VecDeque::with_capacity(n); + stk.push_back(-1); + stk + }; + let mut ans: i32 = 0; + let mut dp: Vec<i32> = vec![0; n + 1]; + for i in 0..n { + while let Some(&top) = stk.back() { + if top != -1 && arr[i] <= arr[top as usize] { + stk.pop_back(); + } else { + break; + } + } + if let Some(&top) = stk.back() { + dp[i + 1] = (dp[top as usize + 1] + (i as i32 - top as i32) * arr[i]) % MOD; + } + stk.push_back(i as isize); + ans += dp[i + 1]; + ans %= MOD; + } + ans + } +} + +fn main() { + let arr = vec![3,1,2,4]; + print!("{}", Solution::sum_subarray_mins(arr)); +} diff --git a/sum_subset_xor.c b/sum_subset_xor.c new file mode 100644 index 0000000..cb51647 --- /dev/null +++ b/sum_subset_xor.c @@ -0,0 +1,38 @@ +// 1863. Sum of All Subset XOR Totals +#include "leetcode.h" + +/* + * the xor total of an array is defined as the bitwise xor of all its elements + * or 0 if the array is empty. given an array 'nums' return the sum of all xor + * totals for every subset of 'nums'. an array 'a' is a subset of an array 'b' + * if 'a' can be obtained from 'b' by deleting some elements of 'b'. + */ + +void backtrack(int *nums, int numsSize, int tar, int idx, int *cnt) { + if (idx == numsSize) { + return; + } else { + for (int i = idx; i < numsSize; i++) { + tar ^= nums[i]; + *cnt += tar; + backtrack(nums, numsSize, tar, i + 1, cnt); + tar ^= nums[i]; + } + } +} + +int subsetXORSum(int *nums, int numsSize) { + int ans = 0; + for (int i = 0; i < numsSize; i++) { + ans += nums[i]; + backtrack(nums, numsSize, nums[i], i + 1, &ans); + } + return ans; +} + +int main() { + int n1[] = {1, 3}, n2[] = {5, 1, 6}, n3[] = {3, 4, 5, 6, 7, 8}; + printf("%d\n", subsetXORSum(n1, ARRAY_SIZE(n1))); // expect: 6 + printf("%d\n", subsetXORSum(n2, ARRAY_SIZE(n2))); // expect: 28 + printf("%d\n", subsetXORSum(n3, ARRAY_SIZE(n3))); // expect: 480 +} diff --git a/sum_subset_xor.cpp b/sum_subset_xor.cpp new file mode 100644 index 0000000..a3048f7 --- /dev/null +++ b/sum_subset_xor.cpp @@ -0,0 +1,33 @@ +#include "leetcode.h" + +/* + 000 => {empty set} + 001 => {set with only first element} + 010 => {set with only second element} + 011 => {set with first and second element} + 100 ... and so on + 101 + 110 + 111 => {subset with all three elements} +*/ + +class Solution { +public: + int subsetXORSum(vector<int> &nums) { + int n = nums.size(), subsetNum = pow(2, n), ans = 0; + for (int i = 1; i < subsetNum; ++i) { + int runningXOR = 0; + for (int j = 0, bits = i; j < nums.size(); ++j, bits >>= 1) + if (bits & 1) + runningXOR ^= nums[j]; + ans += runningXOR; + } + return ans; + } +}; + +int main() { + vector<int> nums = {3, 4, 5, 6, 7, 8}; + Solution obj; + cout << obj.subsetXORSum(nums); +} diff --git a/sum_subset_xor.py b/sum_subset_xor.py new file mode 100644 index 0000000..deb88ed --- /dev/null +++ b/sum_subset_xor.py @@ -0,0 +1,42 @@ +# 1863. Sum of All Subset XOR Totals + +""" +the xor total of an array is defined as the bitwise xor of all its elements +or 0 if the array is empty. given an array 'nums' return the sum of all xor +totals for every subset of 'nums'. an array 'a' is a subset of an array 'b' +if 'a' can be obtained from 'b' by deleting some elements of 'b'. +""" + + +class Solution(object): + def subsetXORSum(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + + def backtrack(nums, idx, tar, cnt): + if idx == len(nums): + cnt.append(tar[:]) + return + tar.append(nums[idx]) + backtrack(nums, idx + 1, tar, cnt) + tar.pop() + backtrack(nums, idx + 1, tar, cnt) + + cnt = [] + backtrack(nums, 0, [], cnt) + ans = 0 + for i in cnt: + total = 0 + for n in i: + total ^= n + ans += total + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.subsetXORSum(nums=[1, 3])) + print(obj.subsetXORSum(nums=[5, 1, 6])) + print(obj.subsetXORSum(nums=[3, 4, 5, 6, 7, 8])) diff --git a/summary_ranges.c b/summary_ranges.c new file mode 100644 index 0000000..ac0c0bf --- /dev/null +++ b/summary_ranges.c @@ -0,0 +1,106 @@ +// 228. Summary Ranges +#include <math.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a sorted unique integer array 'nums'. a range '[a, b]' isthe set of all + * integers from 'a' to 'b' (inclusive). return the smallest sorted list of + * ranges that cover all the numbers in the array exactlyh. that is, each + * element of 'nums' is covered by exactly one of the ranges, and there is no + * integer 'x' such that 'x' is in one of the ranges but not in 'nums' each + * range '[a, b]' in the list should be outgput as: + * - "a->b" if a != b + * - "a" if a == b + */ + +char *int_to_str(int val) { + if (!val) + return "0"; + bool flag = (val < 0) ? true : false; + uint a = fabs(val); + char *res = malloc(12 * sizeof(int)); + res[11] = '\0'; + int idx = 10; + while (a) { + res[idx] = a % 10 + '0'; + idx--; + a /= 10; + } + if (flag) { + res[idx] = '-'; + idx--; + } + return &res[idx + 1]; +} + +char **summaryRanges(int *nums, int nums_size, int *return_size) { + if (!nums_size) { + *return_size = 0; + return NULL; + } + int **map = malloc(nums_size * sizeof(int *)); + int idx = 0, begin = nums[0], end = nums[0]; + if (nums_size == 1) { + map[0] = malloc(2 * sizeof(int)); + map[0][0] = begin; + map[0][1] = end; + idx = 1; + } + for (int i = 1; i < nums_size; i++) { + if (nums[i] == nums[i - 1] + 1) + end = nums[i]; + else { + map[idx] = malloc(2 * sizeof(int)); + map[idx][0] = begin; + map[idx][1] = end; + begin = nums[i]; + end = nums[i]; + idx++; + } + for (int i = 1; i < nums_size; i++) { + if (nums[i] == nums[i - 1] + 1) + end = nums[i]; + else { + map[idx] = malloc(2 * sizeof(int)); + map[idx][0] = begin; + map[idx][1] = end; + begin = nums[i]; + end = nums[i]; + idx++; + } + if (i == nums_size - 1) { + map[idx] = malloc(2 * sizeof(int)); + map[idx][0] = begin; + map[idx][1] = end; + begin = nums[i]; + end = nums[i]; + idx++; + } + } + char **ans = malloc(idx * sizeof(char *)); + for (int i = 0; i < idx; i++) { + if (map[i][0] == map[i][1]) + ans[i] = int_to_str(map[i][0]); + else { + char *tmp = malloc(25 * sizeof(char)); + tmp[0] = '\0'; + strcat(tmp, int_to_str(map[i][0])); + strcat(tmp, "->"); + strcat(tmp, int_to_str(map[i][1])); + ans[i] = tmp; + } + } + } + *return_size = idx; + return ans; +} + +int main() { + int n1[] = {0, 1, 2, 4, 5, 7}; + int n2[] = {0, 2, 3, 4, 6, 8, 9}; + printf("%s\n", summaryRanges(n1, 6, NULL)); // expect: 0->2 4->5 7 + printf("%s\n", summaryRanges(n2, 7, NULL)); // expect: 0 2->4 6 8->9 +} diff --git a/summary_ranges.cpp b/summary_ranges.cpp new file mode 100644 index 0000000..d2feb9e --- /dev/null +++ b/summary_ranges.cpp @@ -0,0 +1,47 @@ +// 228. Summary Ranges +#include "leetcode.h" + +/* + * given a sorted unique integer array 'nums'. a range '[a, b]' isthe set of all + * integers from 'a' to 'b' (inclusive). return the smallest sorted list of + * ranges that cover all the numbers in the array exactlyh. that is, each + * element of 'nums' is covered by exactly one of the ranges, and there is no + * integer 'x' such that 'x' is in one of the ranges but not in 'nums' each + * range '[a, b]' in the list should be outgput as: + * - "a->b" if a != b + * - "a" if a == b + */ + +class Solution { +public: + vector<string> summaryRanges(vector<int> &nums) { + int n = nums.size(); + vector<string> ans; + string tmp = ""; + for (int i = 0; i < n; i++) { + int j = i; + while (j + 1 < n && nums[j + 1] == nums[j] + 1) + j++; + if (j > i) { + tmp += to_string(nums[i]); + tmp += "->"; + tmp += to_string(nums[j]); + } else + tmp += to_string(nums[i]); + ans.push_back(tmp); + tmp = ""; + i = j; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {0, 1, 2, 4, 5, 7}, n2 = {0, 2, 3, 4, 6, 8, 9}; + for (auto i : obj.summaryRanges(n1)) + cout << i << ' '; // expect: 0.2 4.5 7 + printf("\n"); + for (auto i : obj.summaryRanges(n2)) + cout << i << ' '; // expect: 0.4 6 8.9 +} diff --git a/super_ugly_num.c b/super_ugly_num.c new file mode 100644 index 0000000..0f9c7bf --- /dev/null +++ b/super_ugly_num.c @@ -0,0 +1,31 @@ +// 313. Super Ugly Number +#include "leetcode.h" + +/* + * a super ugly number is a positive integer whose prime factors are in the + * array 'primes'. given an integer 'n' and an array of integers 'primes', + * return the n'th super ugly number. the n'th super ugly number is guaranteed + * to fit in a 32-bit integer (signed) + */ + +int nthSuperUglyNumber(int n, int *primes, int primes_size) { + int *idx = (int *)calloc(primes_size, sizeof(int)); + int *nums = (int *)malloc(sizeof(int) * n); + *nums = 1; + for (int i = 1; i < n; ++i) { + int min = INT_MAX; + for (int j = 0; j < primes_size; ++j) + min = fmin(min, nums[idx[j]] * primes[j]); // INT_MAX overflows fmin here + nums[i] = min; + for (int j = 0; j < primes_size; ++j) + if (nums[idx[j]] * primes[j] == min) + ++idx[j]; + } + return nums[n - 1]; +} + +int main() { + int p1[] = {2, 7, 13, 19}, p2[] = {2, 3, 5}; + printf("%d\n", nthSuperUglyNumber(12, p1, ARRAY_SIZE(p1))); // expect: 32 + printf("%d\n", nthSuperUglyNumber(1, p2, ARRAY_SIZE(p2))); // expect: 1 +} diff --git a/super_ugly_num.py b/super_ugly_num.py new file mode 100644 index 0000000..278edb3 --- /dev/null +++ b/super_ugly_num.py @@ -0,0 +1,28 @@ +# 313. Super Ugly Number + +""" +a super ugly number is a positive integer whose prime factors are in the +array 'primes'. given an integer 'n' and an array of integers 'primes', +return the n'th super ugly number. the n'th super ugly number is guaranteed +to fit in a 32-bit integer (signed) +""" + + +class Solution(object): + def nthSuperUglyNumber(self, n, primes): + size = len(primes) + ugly, dp, idx, nums = 1, [1], [0] * size, [1] + for i in range(1, n): + for j in range(0, size): + if nums[j] == ugly: + nums[j] = dp[idx[j]] * primes[j] + idx[j] += 1 + ugly = min(nums) + dp.append(ugly) + return dp[-1] + + +if __name__ == "__main__": + obj = Solution() + print(obj.nthSuperUglyNumber(n=12, primes=[2, 7, 13, 19])) # expect: 32 + print(obj.nthSuperUglyNumber(n=1, primes=[2, 3, 5])) # expect: 1 diff --git a/swap_node_linked_list.c b/swap_node_linked_list.c new file mode 100644 index 0000000..42db742 --- /dev/null +++ b/swap_node_linked_list.c @@ -0,0 +1,87 @@ +// 1721. Swapping Nodes in a Linked List +#include <stdlib.h> + +/* + * given the 'head' of a linked list, and a an integer 'k', return + * the head of the linked list after swapping the values of the + * k'th node from the beginning and the k'th node from the end + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +int countNode(struct ListNode *head) { + int d = 0; + struct ListNode *tmp = head; + while (tmp) { + d++; + tmp = tmp->next; + } + return d; +} + +struct ListNode *swapNodes(struct ListNode *head, int k) { + int total = countNode(head); + if (total == 1) + return head; + if (total == 2) { + struct ListNode *tmp = head->next; + tmp->next = head; + head->next = NULL; + head = tmp; + return head; + } + int p = total - k + 1, i = 1; + struct ListNode *node1 = head; + struct ListNode *ptr1 = NULL; + struct ListNode *post1 = NULL; + while (i < k) { + ptr1 = node1; + node1 = node1->next; + i++; + } + post1 = node1->next; + i = 1; + struct ListNode *node2 = head; + struct ListNode *ptr2 = NULL; + struct ListNode *post2 = NULL; + while (i < p) { + ptr2 = node2; + node2 = node2->next; + i++; + } + post2 = node2->next; + if (node1 == node2) + return head; + if (p - k == 1) { + ptr1->next = node2; + node2->next = node1; + node1->next = post2; + return head; + } + if (k - p == 1) { + ptr2->next = node1; + node1->next = node2; + node2->next = post1; + return head; + } + if (k == 1) { + node2->next = post1; + head = node2; + ptr2->next = node1; + node1->next = NULL; + } else if (k == total) { + node1->next = post2; + head = node1; + ptr1->next = node2; + node2->next = NULL; + } else { + ptr1->next = node2; + node2->next = post1; + ptr2->next = node1; + node1->next = post2; + } + return head; +} diff --git a/swap_node_linked_list.cpp b/swap_node_linked_list.cpp new file mode 100644 index 0000000..b5ad832 --- /dev/null +++ b/swap_node_linked_list.cpp @@ -0,0 +1,45 @@ +#include <iostream> +using namespace std; + +struct ListNode { + int val; + ListNode *next; + ListNode() : val(0), next(nullptr) {} + ListNode(int x) : val(x), next(nullptr) {} + ListNode(int x, ListNode *next) : val(x), next(next) {} +}; + +// implementation +class Solution { +public: + ListNode *swapNodes(ListNode *head, int k) { + ListNode *x = head, *y = head, *t = head; + while (k > 1) { + x = x->next; + t = t->next; + k--; + } + + while (t->next) { + y = y->next; + t = t->next; + } + + int temp = x->val; + x->val = y->val; + y->val = temp; + return head; + } +}; +// end + +int main() { + ListNode *l = new ListNode(1); + l->next = new ListNode(2); + l->next->next = new ListNode(3); + l->next->next->next = new ListNode(4); + l->next->next->next->next = new ListNode(5); + int k = 2; + Solution *sol = new Solution(); + sol->swapNodes(l, k); +} diff --git a/swap_node_pair.cpp b/swap_node_pair.cpp new file mode 100644 index 0000000..b365961 --- /dev/null +++ b/swap_node_pair.cpp @@ -0,0 +1,31 @@ +#include <bits/stdc++.h> +using namespace std; + +struct ListNode { + int val; + ListNode *next; + ListNode() : val(0), next(nullptr) {} + ListNode(int x) : val(x), next(nullptr) {} + ListNode(int x, ListNode *next) : val(x), next(next) {} +}; + +class Solution { +public: + ListNode *swapPairs(ListNode *head) { + if (!head || !head->next) + return head; + ListNode *temp = new ListNode; + ListNode *prev = temp; + ListNode *curr = head; + while (curr && curr->next) { + prev->next = curr->next; + curr->next = prev->next->next; + prev->next->next = curr; + prev = curr; + curr = curr->next; + } + return temp->next; + } +}; + +int main() {} diff --git a/swap_nodes_pairs.c b/swap_nodes_pairs.c new file mode 100644 index 0000000..45c5be5 --- /dev/null +++ b/swap_nodes_pairs.c @@ -0,0 +1,21 @@ +// 24. Swap Nodes in Pairs + +/* + * given a linked list, swap every two adjacent nodes and return + * its head. problem must be solved without modifying values + * in the list's nodes (ie only nodes themselves may be changed) + */ + +struct ListNode { + int val; + struct ListNode *next; +}; + +struct ListNode *swapPairs(struct ListNode *head) { + if (!head || !head->next) + return head; + struct ListNode *tmp = head->next; + head->next = swapPairs(head->next->next); + tmp->next = head; + return tmp; +} diff --git a/swap_nodes_pairs.cpp b/swap_nodes_pairs.cpp new file mode 100644 index 0000000..139c336 --- /dev/null +++ b/swap_nodes_pairs.cpp @@ -0,0 +1,21 @@ +// 24. Swap Nodes in Pairs +#include "leetcode.h" + +/* + * given a linked list, swap every two adjacent nodes and return + * its head. problem must be solved without modifying values + * in the list's nodes (ie only nodes themselves may be changed) + */ + +class Solution { +public: + ListNode *swapPairs(ListNode *head) { + if (!head || !head->next) + return head; + ListNode *tmp; + tmp = head->next; + head->next = swapPairs(head->next->next); + tmp->next = head; + return tmp; + } +}; diff --git a/symmetric_tree.c b/symmetric_tree.c new file mode 100644 index 0000000..f6a1cf3 --- /dev/null +++ b/symmetric_tree.c @@ -0,0 +1,28 @@ +// 101. Symmetric Tree +#include <stdbool.h> +#include <stddef.h> + +// given 'root' of binary tree, check whether it is a mirror of itself + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +bool traverse(struct TreeNode *left, struct TreeNode *right) { + if (left == NULL && right == NULL) + return true; + if (left == NULL || right == NULL) + return false; + if (left->val != right->val) + return false; + return traverse(left->left, right->right) && + traverse(left->right, right->left); +} + +bool isSymmetric(struct TreeNode *root) { + if (root == NULL) + return true; + return traverse(root->left, root->right); +} diff --git a/symmetric_tree.cpp b/symmetric_tree.cpp new file mode 100644 index 0000000..fbd4bf3 --- /dev/null +++ b/symmetric_tree.cpp @@ -0,0 +1,33 @@ +// 101. Symmetric Tree +#include "leetcode.h" + +// given 'root' of binary tree, check whether it is a mirror of itself + +class Solution { +public: + bool isSymmetric(TreeNode *root) { + TreeNode *left, *right; + if (!root) + return true; + queue<TreeNode *> q1, q2; + q1.push(root->left); + q2.push(root->right); + while (!q1.empty() && !q2.empty()) { + left = q1.front(); + q1.pop(); + right = q2.front(); + q2.pop(); + if (left == NULL && right == NULL) + continue; + if (left == NULL || right == NULL) + return false; + if (left->val != right->val) + return false; + q1.push(left->left); + q1.push(left->right); + q2.push(right->right); + q2.push(right->left); + } + return true; + } +}; diff --git a/tallest_billboard.c b/tallest_billboard.c new file mode 100644 index 0000000..9736d33 --- /dev/null +++ b/tallest_billboard.c @@ -0,0 +1,41 @@ +// 956. Tallest Billboard +#include <limits.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * you are installing a billboard and want it to have the largest height. the + * billboard will have two stell supports, one on each side. each steel support + * must be an equal height. given a collection of 'rods' that can be welded + * together. for example, if you have rods of lengths 1,2,3, you can weld them + * together to make a length of 6. return the largest possible height of your + * billboard installation. if you cannot support the billboard, return 0 + */ + +int dp[21][10001]; + +int get(int *rods, int rods_size, int i, int sum) { + if (i >= rods_size) + return sum = 0 ? 0 : INT_MIN; + if (dp[i][sum + 5000] != -1) + return dp[i][sum + 5000]; + int res = get(rods, rods_size, i + 1, sum); + res = fmax(res, get(rods, rods_size, i + 1, sum - rods[i])); + res = fmax(res, get(rods, rods_size, i + 1, sum + rods[i]) + rods[i]); + return dp[i][sum + 5000] = res; +} + +int tallestBillboard(int *rods, int rods_size) { + memset(dp, -1, sizeof(dp)); + int ans = get(rods, rods_size, 0, 0); + return ans < 0 ? 0 : ans; +} + +int main() { + int r1[] = {1, 2, 3, 6}, rs1 = 4; + int r2[] = {1, 2, 3, 4, 5, 6}, rs2 = 6; + printf("%d\n", tallestBillboard(r1, rs1)); // expect: 6 + printf("%d\n", tallestBillboard(r2, rs2)); // expect: 10 +} diff --git a/tallest_billboard.cpp b/tallest_billboard.cpp new file mode 100644 index 0000000..1201823 --- /dev/null +++ b/tallest_billboard.cpp @@ -0,0 +1,26 @@ +#include "leetcode.h" + +class Solution { +public: + int tallestBillboard(vector<int> &rods) { + unordered_map<int, int> dp; + dp[0] = 0; + for (int i : rods) { + unordered_map<int, int> tmp; + for (auto &it : dp) { + int diff = it.first; + tmp[diff + i] = max(tmp[diff + i], dp[diff] + i); + tmp[diff - i] = max(tmp[diff - i], dp[diff]); + } + dp.clear(); + dp.insert(tmp.begin(), tmp.end()); + } + return dp[0]; + } +}; + +int main() { + Solution obj; + vector<int> rods = {1, 2, 3, 6}; + cout << obj.tallestBillboard(rods); +} diff --git a/target_sum.c b/target_sum.c new file mode 100644 index 0000000..4b5ef94 --- /dev/null +++ b/target_sum.c @@ -0,0 +1,29 @@ +// 494. Target Sum +#include "leetcode.h" + +/* + * given an integer array 'nums' and an integer 'target'. you want to buildan + * expression out of numbers by adding oneof the symbols '+' and '-' before each + * integer in nums awnd then concatenate all the integers. for example if 'nums + * = [2,1]', you can adda '+' before '2' and '-' before '1' and concatenate them + * to build the expression '+2-1'. return the number of different + * expressionsthat you can build, which evaluates to 'target'. + */ + +int findTargetSumWays(int *nums, int numsSize, int target) { + if (numsSize == 1) { + if (nums[0] == target && nums[0] == -target) + return 2; + if (nums[0] == target || nums[0] == -target) + return 1; + return 0; + } + return findTargetSumWays(&nums[1], numsSize - 1, target + nums[0]) + + findTargetSumWays(&nums[1], numsSize - 1, target - nums[0]); +} + +int main() { + int n1[] = {1, 1, 1, 1, 1}, n2[] = {1}; + printf("%d\n", findTargetSumWays(n1, ARRAY_SIZE(n1), 3)); // expect: 5 + printf("%d\n", findTargetSumWays(n2, ARRAY_SIZE(n2), 1)); // expect: 1 +} diff --git a/target_sum.py b/target_sum.py new file mode 100644 index 0000000..ca14cf7 --- /dev/null +++ b/target_sum.py @@ -0,0 +1,34 @@ +# 494. Target Sum +from collections import Counter + +""" +given an integer array 'nums' and an integer 'target'. you want to buildan +expression out of numbers by adding oneof the symbols '+' and '-' before each +integer in nums awnd then concatenate all the integers. for example if 'nums += [2,1]', you can adda '+' before '2' and '-' before '1' and concatenate them +to build the expression '+2-1'. return the number of different +expressionsthat you can build, which evaluates to 'target'. +""" + + +class Solution(object): + def findTargetSumWays(self, nums, target): + """ + :type nums: List[int] + :type target: int + :rtype: int + """ + cnt = Counter({0: 1}) + for x in nums: + step = Counter() + for y in cnt: + step[y + x] += cnt[y] + step[y - x] += cnt[y] + cnt = step + return cnt[target] + + +if __name__ == "__main__": + obj = Solution() + print(obj.findTargetSumWays(nums=[1, 1, 1, 1, 1], target=3)) + print(obj.findTargetSumWays(nums=[1], target=1)) diff --git a/task_scheduler.c b/task_scheduler.c new file mode 100644 index 0000000..a7606bd --- /dev/null +++ b/task_scheduler.c @@ -0,0 +1,54 @@ +// 2365. Task Scheduler II +#include <stdio.h> +#include <stdlib.h> + +/* + * given a 0-indexed array of positive integers 'tasks', representing tasks that + * need to be completed in order, where 'tasks[i]' represents the type of the + * i'th task. you are also given a positve integer 'space' which represents the + * minimum number of days that must pass after the completion of a task before + * another task of the same type can be performed. each day until all tasks have + * been completed, you must either + * - complete the next task from 'tasks' or + * - take a break + * return the minimum number of days needed to complete all tasks. + */ + +long long taskSchedulerII(int *tasks, int tasks_size, int space) { + long long ans = 0; + int n = tasks_size, m = 10 * tasks_size; + long long **hash = calloc(m, sizeof(long long *)); + for (int i = 0; i < n; i++) { + int val = tasks[i], d = val; + while (1) { + if (!hash[d % m]) { + ans++; + hash[d % m] = malloc(2 * sizeof(long long)); + hash[d % m][0] = tasks[i]; + hash[d % m][1] = ans; + break; + } else if (hash[d % m][0] == tasks[i]) { + ans++; + if (ans >= (hash[d % m][1] + space + 1)) + hash[d % m][1] = ans; + else { + hash[d % m][1] += (space + 1); + ans = hash[d % m][1]; + } + break; + } else + d++; + } + } + for (int i = 0; i < m; i++) + if (hash[i]) + free(hash[i]); + free(hash); + return ans; +} + +int main() { + int t1[] = {1, 2, 1, 2, 3, 1}, t2[] = {5, 8, 8, 5}; + printf("%lld\n", taskSchedulerII(t1, 6, 3)); // expect: 9 + printf("%lld\n", taskSchedulerII(t2, 4, 2)); // expect: 6 +} diff --git a/task_scheduler.cpp b/task_scheduler.cpp new file mode 100644 index 0000000..553dd5d --- /dev/null +++ b/task_scheduler.cpp @@ -0,0 +1,36 @@ +// 2365. Task Scheduler II +#include "leetcode.h" + +/* + * given a 0-indexed array of positive integers 'tasks', representing tasks that + * need to be completed in order, where 'tasks[i]' represents the type of the + * i'th task. you are also given a positve integer 'space' which represents the + * minimum number of days that must pass after the completion of a task before + * another task of the same type can be performed. each day until all tasks have + * been completed, you must either + * - complete the next task from 'tasks' or + * - take a break + * return the minimum number of days needed to complete all tasks. + */ + +class Solution { +public: + long long taskSchedulerII(vector<int> &tasks, int space) { + unordered_map<int, long long> last; + long long ans = 0; + for (int t : tasks) { + if (last.count(t)) + last[t] = ans = max(ans, last[t] + space) + 1; + else + last[t] = ++ans; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> t1 = {1, 2, 1, 2, 3, 1}, t2 = {5, 8, 8, 5}; + printf("%lld\n", obj.taskSchedulerII(t1, 3)); // expect: 9 + printf("%lld\n", obj.taskSchedulerII(t2, 2)); // expect: 6 +} diff --git a/task_scheduler.py b/task_scheduler.py new file mode 100644 index 0000000..6c3f513 --- /dev/null +++ b/task_scheduler.py @@ -0,0 +1,34 @@ +# 2365. Task Scheduler II +from collections import Counter + +""" +given a 0-indexed array of positive integers 'tasks', representing tasks that +need to be completed in order, where 'tasks[i]' represents the type of the +i'th task. you are also given a positve integer 'space' which represents the +minimum number of days that must pass after the completion of a task before +another task of the same type can be performed. each day until all tasks have +been completed, you must either +- complete the next task from 'tasks' or +- take a break +return the minimum number of days needed to complete all tasks. +""" + + +class Solution(object): + def leastInterval(self, tasks, n): + """ + :type tasks: List[str] + :type n: int + :rtype: int + """ + task_cnt = Counter(tasks).values() + m = max(task_cnt) + mct = task_cnt.count(m) + return max(len(tasks), (m - 1) * (n + 1) + mct) + + +if __name__ == "__main__": + obj = Solution() + print(obj.leastInterval(tasks=["A", "A", "A", "B", "B", "B"], n=2)) + print(obj.leastInterval(tasks=["A", "C", "A", "B", "D", "B"], n=1)) + print(obj.leastInterval(tasks=["A", "A", "A", "B", "B", "B"], n=3)) diff --git a/text_justification.c b/text_justification.c new file mode 100644 index 0000000..78f6703 --- /dev/null +++ b/text_justification.c @@ -0,0 +1,124 @@ +// 68. Text Justification +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array of strings 'words', and a width 'max_width', format the text + * such that each line has exactly 'max_width' characters and is fully (left and + * right) justified. you should pack your words in a greedy approach; that is, + * pack as many words as you can in each line. pad extra spaces ' ' when + * necessary so that each line has exactly 'max_width' characters. extra spaces + * between words just be distributed as evenly as possible. if the number of + * spaces on a line does not divide evenly between the words, the empty slots on + * the left will be assigned more spaces than the slots on the right. for the + * last line of text, it should be left-justified, and no extra space is + * inserted between words. + */ + +int get_len(char *s) { + int len = 0; + while (s[len]) + len++; + return len; +} + +char *centre_justify(char **words, int words_size, int *len, int start_idx, + int end_idx, int max_width) { + int width = 0; + for (int i = start_idx; i <= end_idx; i++) + width += len[i]; + int total_space = max_width - width; + int space = total_space / (end_idx - start_idx); + int bonus_space = total_space % (end_idx - start_idx); + char *line = (char *)malloc(sizeof(char) * (max_width + 1)); + int idx = 0; + for (int i = start_idx; i <= end_idx; i++) { + if (i > start_idx) { + for (int j = 0; j < space; j++) + line[idx++] = ' '; + if (bonus_space--) + line[idx++] = ' '; + } + for (int j = 0; j < len[i]; j++) + line[idx++] = words[i][j]; + } + line[idx] = 0; + return line; +} + +char *left_justify(char **words, int words_size, int *len, int start_idx, + int end_idx, int max_width) { + char *line = (char *)malloc(sizeof(char) * (max_width + 1)); + int idx = 0; + for (int i = start_idx; i <= end_idx; i++) { + if (i > start_idx) + line[idx++] = ' '; + for (int j = 0; j < len[i]; j++) + line[idx++] = words[i][j]; + } + for (int i = idx; i < max_width; i++) + line[idx++] = ' '; + line[idx] = 0; + return line; +} + +char **fullJustify(char **words, int words_size, int max_width, + int *return_size) { + if (!words_size) { + char **ans = (char **)malloc(sizeof(char *)); + ans[0] = (char *)malloc(sizeof(char) * max_width + 1); // hmm, pemdas? + int idx = 0; + for (int i = 0; i < max_width; i++) + ans[0][idx++] = ' '; + ans[0][idx] = 0; + *return_size = 1; + return ans; + } + int *len = (int *)calloc(words_size, sizeof(int)); + for (int i = 0; i < words_size; i++) + len[i] = get_len(words[i]); + int *start_idx = (int *)malloc(sizeof(int) * words_size); + int start_len = 0, width = 0, new_width; + start_idx[start_len++] = 0; + for (int i = 0; i < words_size; i++) { + new_width = width + len[i]; + if (width) + new_width++; + if (new_width > max_width) { + start_idx[start_len++] = i; + width = len[i]; + } else + width = new_width; + } + char **ans = (char **)malloc(sizeof(char *) * start_len); + int idx = 0; + for (int i = 0; i < start_len - 1; i++) { + if (start_idx[i + 1] - start_idx[i] >= 2) + ans[idx++] = centre_justify(words, words_size, len, start_idx[i], + start_idx[i + 1] - 1, max_width); + else + ans[idx++] = + left_justify(words, words_size, len, start_idx[start_len - 1], + words_size - 1, max_width); + } + ans[idx] = left_justify(words, words_size, len, start_idx[start_len - 1], + words_size - 1, max_width); + free(start_idx); + *return_size = start_len; + return ans; +} + +int main() { + char w1[7][14] = {"This", "is", "an", "example", "of", "text", + "justification."}; + char w2[6][14] = {"What", "must", "be", "acknowledgment", "shall", "be"}; + int rs1[] = {}, rs2[] = {}; + char **fj1 = fullJustify(w1, 7, 16, rs1); + char **fj2 = fullJustify(w2, 6, 16, rs2); + for (int i = 0; i < 7; i++) + printf("%s ", fj1[i]); + printf("\n"); + for (int i = 0; i < 6; i++) + printf("%s ", fj2[i]); + printf("\n"); +} diff --git a/text_justification.cpp b/text_justification.cpp new file mode 100644 index 0000000..d45bead --- /dev/null +++ b/text_justification.cpp @@ -0,0 +1,56 @@ +#include "leetcode.h" + +class Solution { +public: + vector<string> fullJustify(vector<string> &words, int maxWidth) { + vector<string> ans, taken; + int lineLen = 0; + for (auto word : words) { + if (lineLen + word.size() + taken.size() > maxWidth) { + ans.push_back(lineBegin(taken, maxWidth - lineLen)); + taken.clear(); + taken.push_back(word); + lineLen = word.size(); + } else { + taken.push_back(word); + lineLen += word.size(); + } + } + ans.push_back(lineEnd(taken, maxWidth - lineLen)); + return ans; + } + +private: + string lineBegin(vector<string> &v, int toFill) { + string ans = ""; + if (v.size() == 1) { + ans += v[0]; + while (toFill--) + ans += ' '; + return ans; + } + int space = toFill / (v.size() - 1); + int extras = toFill % (v.size() - 1); + ans += v[0]; + for (int i = 1; i < v.size(); i++) { + for (int j = 0; j < space; j++) + ans += ' '; + if (extras) { + extras--; + ans += ' '; + } + } + return ans; + } + string lineEnd(vector<string> &v, int toFill) { + string ans = v[0]; + for (int i = 1; i < v.size(); i++) { + toFill--; + ans += ' '; + ans += v[i]; + } + while (toFill--) + ans += ' '; + return ans; + } +}; diff --git a/third_max_num.c b/third_max_num.c new file mode 100644 index 0000000..aa28e16 --- /dev/null +++ b/third_max_num.c @@ -0,0 +1,34 @@ +// 414. Third Maximum Number +#include "leetcode.h" + +/* + * given an integer array 'nums', return the third distinct maximum number in + * this array. if the third maximum number does not exist, return the maximum + * number. + */ + +int thirdMax(int *nums, int numsSize) { + int m1, m2, m3, cnt = 0; + m1 = m2 = m3 = INT_MIN; + for (int i = 0; i < numsSize; i++) + if (m1 <= nums[i]) + m1 = nums[i]; + for (int i = 0; i < numsSize; i++) + if (m2 <= nums[i] && nums[i] < m1) + m2 = nums[i]; + for (int i = 0; i < numsSize; i++) + if (m3 <= nums[i] && nums[i] < m2) { + m3 = nums[i]; + cnt++; + } + if (!cnt) + return m1; + return m3; +} + +int main() { + int n1[] = {3, 2, 1}, n2[] = {1, 2}, n3[] = {2, 2, 3, 1}; + printf("%d\n", thirdMax(n1, ARRAY_SIZE(n1))); // expect: 1 + printf("%d\n", thirdMax(n2, ARRAY_SIZE(n2))); // expect: 2 + printf("%d\n", thirdMax(n3, ARRAY_SIZE(n3))); // expect: 1 +} diff --git a/third_max_num.py b/third_max_num.py new file mode 100644 index 0000000..960cc5d --- /dev/null +++ b/third_max_num.py @@ -0,0 +1,32 @@ +# 414. Third Maximum iber + +""" +ginen an integer array 'is', return the third distinct maximum number in +this array. if the third maximum iber does not exist, return the maximum +iber. +""" + + +class Solution(object): + def thirdMax(self, nums): + """ + :type is: List[int] + :rtype: int + """ + n = [float("-inf"), float("-inf"), float("-inf")] + for i in nums: + if i not in n: + if i > n[0]: + n = [i, n[0], n[1]] + elif i > n[1]: + n = [n[0], i, n[1]] + elif i > n[2]: + n = [n[0], n[1], i] + return max(nums) if float("-inf") in n else n[2] + + +if __name__ == "__main__": + obj = Solution() + print(obj.thirdMax([3, 2, 1])) + print(obj.thirdMax([1, 2])) + print(obj.thirdMax([2, 2, 3, 1])) diff --git a/thousand_separator.cpp b/thousand_separator.cpp new file mode 100644 index 0000000..a0493f5 --- /dev/null +++ b/thousand_separator.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" +#include <cmath> +#include <string> + +class Solution { +public: + string thousandSeparator(int n) { + string s = to_string(n); + if (trunc(log10(n)) + 1 < 4) + return s; + + return s; + } +}; + +int main() { + Solution obj; + obj.thousandSeparator(1234); + // cout << obj.thousandSeparator(1234); +} diff --git a/time_base_key_val.cpp b/time_base_key_val.cpp new file mode 100644 index 0000000..c23fb87 --- /dev/null +++ b/time_base_key_val.cpp @@ -0,0 +1,32 @@ +#include "leetcode.h" + +class TimeMap { +public: + unordered_map<string, vector<pair<int, string>>> umvp; + TimeMap() {} + void set(string key, string value, int timestamp) { + umvp[key].push_back({timestamp, value}); + } + string get(string key, int timestamp) { + if (!umvp.count(key)) + return ""; + int start = 0, end = umvp[key].size(); + while (start < end) { + int mid = start + (end - start) / 2; + if (umvp[key][mid].first > timestamp) + end = mid; + else + start = mid + 1; + } + return start > 0 && start <= umvp[key].size() ? umvp[key][start - 1].second + : ""; + } +}; + +int main() { + string key, value; + int timestamp; + TimeMap *obj = new TimeMap(); + obj->set(key, value, timestamp); + string param_2 = obj->get(key, timestamp); +} diff --git a/toeplitz_matrix.cpp b/toeplitz_matrix.cpp new file mode 100644 index 0000000..8a1bec4 --- /dev/null +++ b/toeplitz_matrix.cpp @@ -0,0 +1,30 @@ +#include "leetcode.h" + +class Solution { +public: + bool isToeplitzMatrix(vvd(int) & matrix) { + int m = matrix.size(), n = matrix[0].size(); + for (int i = 1; i < m; i++) + for (int j = 1; j < n; j++) + if (matrix[i][j] != matrix[i - 1][j - 1]) + return false; + return true; + } +}; + +int main() { + Solution obj; + // true - all diagonals have the same elements + vvd(int) matrix = {{1, 2, 3, 4}, {5, 1, 2, 3}, {9, 5, 1, 2}}; + // false - diagonals do not share same elements + vvd(int) matrix2 = {{1, 2}, {2, 2}}; + + if (obj.isToeplitzMatrix(matrix)) + cout << "true"; + else + cout << "false"; + if (obj.isToeplitzMatrix(matrix2)) + cout << "\ntrue"; + else + cout << "\nfalse"; +} diff --git a/toeplitz_matrix.rs b/toeplitz_matrix.rs new file mode 100644 index 0000000..03a46bb --- /dev/null +++ b/toeplitz_matrix.rs @@ -0,0 +1,22 @@ +struct Solution; + +impl Solution { + pub fn is_toeplitz_matrix(matrix: Vec<Vec<i32>>) -> bool { + let (m, n) = (matrix.len(), matrix[0].len()); + for i in 1..m { + for j in 1..n { + if matrix[i][j] != matrix[i - 1][j - 1] { + return false; + } + } + } + true + } +} + +fn main() { + let matrix = vec![vec![1,2,3,4], + vec![5,1,2,3], + vec![9,5,1,2]]; + print!("{}", Solution::is_toeplitz_matrix(matrix)); +} diff --git a/top_k_freq_element.c b/top_k_freq_element.c new file mode 100644 index 0000000..3fd0e09 --- /dev/null +++ b/top_k_freq_element.c @@ -0,0 +1,57 @@ +// 347. Top K Frequent Elements +#include "lib/uthash/src/uthash.h" +#include <stdio.h> +#include <stdlib.h> + +/* + * given an integer array 'nums' and an integer 'k', return the 'k' most + * frequent elements you may return the right answer in any order!!! + */ + +typedef struct { + int idxs[500]; + int num_idx; +} pair; + +typedef struct { + int elem; + int count; + UT_hash_handle hh; +} h_elem; + +int *topKFrequent(int *nums, int nums_size, int k, int *return_size) { + h_elem *count = NULL, *s, *curr; + pair *freq = calloc(sizeof(pair), nums_size + 1); + int *ans = malloc(sizeof(int) * k); + *return_size = 0; + for (int i = 0; i < nums_size; i++) { + HASH_FIND_INT(count, &nums[i], s); + if (s) + s->count++; + else { + s = malloc(sizeof(h_elem)); + s->elem = nums[i]; + s->count = 1; + HASH_ADD_INT(count, elem, s); + } + } + HASH_ITER(hh, count, curr, s) + freq[curr->count].idxs[freq[curr->count].num_idx++] = curr->elem; + for (int i = nums_size; i >= 0; i--) + if (freq[i].num_idx) + for (int j = 0; j < freq[i].num_idx; j++) { + ans[(*return_size)++] = freq[i].idxs[j]; + if (*return_size == k) + return ans; + } + return ans; +} + +int main() { + int n1[] = {1, 1, 1, 2, 2, 3}, n2[] = {1}; + int *r1 = topKFrequent(n1, 6, 2, NULL); + int *r2 = topKFrequent(n2, 1, 1, NULL); + for (int i = 0; i < 6; i++) + printf("%d ", r1[i]); + printf("\n%d ", r1[0]); +} diff --git a/top_k_freq_element.cpp b/top_k_freq_element.cpp new file mode 100644 index 0000000..86d7cb4 --- /dev/null +++ b/top_k_freq_element.cpp @@ -0,0 +1,18 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> topKFrequent(vector<int> &nums, int k) { + unordered_map<int, int> um; + for (int n : nums) + um[n]++; + vector<int> ans; + priority_queue<pair<int, int>> pqp; + for (auto it = um.begin(); it != um.end(); it++) { + pqp.push(make_pair(it->second, it->first)); + if (pqp.size() > (int)um.size() - k) + ans.push_back(pqp.top().second), pqp.pop(); + } + return ans; + } +}; diff --git a/top_k_freq_element.rs b/top_k_freq_element.rs new file mode 100644 index 0000000..82a2b03 --- /dev/null +++ b/top_k_freq_element.rs @@ -0,0 +1,32 @@ +//347. Top K Frequent Elements +struct Solution; + +/* +* given an integer array 'nums' and an integer 'k', return the 'k' most frequent elements. you may +* return the answer in any order. +*/ + +impl Solution { + pub fn top_k_frequent(nums: Vec<i32>, k: i32) -> Vec<i32> { + let mut map = std::collections::HashMap::new(); + for x in nums { + *map.entry(x).or_insert(0) += 1; + } + let mut arr = map.into_iter().collect::<Vec<(i32,i32)>>(); + arr.sort_by(|a,b| 1.1.cmp(&b.1)); + arr.reverse(); + let k = k as usize; + let mut ans = vec![0;k]; + for i in 0..k { + ans[i] = arr[i].0; + } + ans + } +} + +fn main() { + let n1 = vec![1,1,1,2,2,3]; + let n2 = vec![1]; + print!("{}", Solution::top_k_frequent(n1, 2)); //expect: [1,2] + print!("{}", Solution::top_k_frequent(n2, 1)); //expect: [1] +} diff --git a/top_k_freq_words.cpp b/top_k_freq_words.cpp new file mode 100644 index 0000000..eaf31d5 --- /dev/null +++ b/top_k_freq_words.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +struct Compare { + bool operator()(pair<int, string> a, pair<int, string> b) { + if (a.first == b.first) + return a.second > b.second; + else + return a.first < b.first; + } +}; + +class Solution { +public: + vector<string> topKFrequent(vector<string> &words, int k) { + unordered_map<string, int> um; + for (int i = 0; i < words.size(); i++) + um[words[i]]++; + priority_queue<pair<int, string>, vector<pair<int, string>>, Compare> + pqpvpc; + for (auto i : um) + pqpvpc.push({i.second, i.first}); + vector<string> ans; + while (k--) { + ans.push_back(pqpvpc.top().second); + pqpvpc.pop(); + } + return ans; + } +}; diff --git a/top_k_freq_words.rs b/top_k_freq_words.rs new file mode 100644 index 0000000..606c237 --- /dev/null +++ b/top_k_freq_words.rs @@ -0,0 +1,26 @@ +use std::collections::BinaryHeap; +use std::collections::HashMap; + +struct Solution; + +impl Solution { + pub fn top_k_frequent(words: Vec<String>, k: i32) -> Vec<String> { + let mut word_to_freq = HashMap::<String, i32>::new(); + for w in words { + *word_to_freq.entry(w).or_default() += 1; + } + let mut heap = BinaryHeap::<(i32, String)>::new(); + for (word, freq) in word_to_freq { + heap.push((-freq, word)); + if heap.len() > k as usize { + heap.pop(); + } + } + let mut ans: Vec<String> = vec![]; + while let Some((_freq, word)) = heap.pop() { + ans.push(word); + } + ans.reverse(); + ans + } +} diff --git a/transpose_matrix.c b/transpose_matrix.c new file mode 100644 index 0000000..61e5d54 --- /dev/null +++ b/transpose_matrix.c @@ -0,0 +1,20 @@ +// 867. Transpose Matrix +#include "leetcode.h" + +/* + * given a 2d integer array 'matrix', return the transpose of 'matrix'. the + * transpose of a matrix is the matrix flipped over its main diagonal switching + * the matrix's rows and column indices + */ + +int **transpose(int **A, int ARowSize, int const *AColSizes, int **columnSizes, + int *returnSize) { + int **ans = malloc(sizeof(int *) * (*returnSize = *AColSizes)); + *columnSizes = malloc(sizeof(int) * (*AColSizes)); + for (int i = 0; i < (*AColSizes); ++i) { + ans[i] = malloc(sizeof(int) * (*(*columnSizes + i) = ARowSize)); + for (int j = 0; j < ARowSize; ++j) + ans[i][j] = A[j][i]; + } + return ans; +} diff --git a/transpose_matrix.cpp b/transpose_matrix.cpp new file mode 100644 index 0000000..b6ab293 --- /dev/null +++ b/transpose_matrix.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" +#include <vector> + +class Solution { +public: + vector<vector<int>> transpose(vector<vector<int>> &matrix) { + int n = matrix.size(), m = matrix[0].size(); + vector<vector<int>> ans(m, vector<int>(n, 0)); + for (int i = 0; i < n; i++) + for (int j = 0; j < m; j++) + ans[j][i] = matrix[i][j]; + return ans; + } +}; + +int main() { + Solution obj; + vector<vector<int>> matrix; + obj.transpose(matrix); +} diff --git a/transpose_matrix.py b/transpose_matrix.py new file mode 100644 index 0000000..4c2c684 --- /dev/null +++ b/transpose_matrix.py @@ -0,0 +1,28 @@ +# 867. Transpose Matrix + +""" +given a 2d integer array 'matrix', return the transpose of 'matrix'. the +transpose of a matrix is the matrix flipped over its main diagonal switching +the matrix's rows and column indices +""" + + +class Solution(object): + def transpose(self, matrix): + """ + :type matrix: List[List[int]] + :rtype: List[List[int]] + """ + n = len(matrix) + m = len(matrix[0]) + ans = [[0] * n for _ in range(m)] + for i in range(n): + for j in range(m): + ans[j][i] = matrix[i][j] + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.transpose(matrix=[[1, 2, 3], [4, 5, 6], [7, 8, 9]])) + print(obj.transpose(matrix=[[1, 2, 3], [4, 5, 6]])) diff --git a/trapping_rain_water.c b/trapping_rain_water.c new file mode 100644 index 0000000..594efc1 --- /dev/null +++ b/trapping_rain_water.c @@ -0,0 +1,29 @@ +// 42. Trapping Rain Water +#include "leetcode.h" + +/* + * given 'n' non-negative integers representing an elevation map where the width + * of each bar is 1, compute how much water it can trap after raining. + */ + +int trap(int *height, int heightSize) { + int *left = (int *)malloc(heightSize * sizeof(int)); + int *right = (int *)malloc(heightSize * sizeof(int)); + left[0] = height[0]; + right[heightSize - 1] = height[heightSize - 1]; + for (int i = 1; i < heightSize; i++) + left[i] = height[i] > left[i - 1] ? height[i] : left[i - 1]; + for (int i = heightSize - 2; i >= 0; i--) + right[i] = height[i] > right[i + 1] ? height[i] : right[i + 1]; + int ans = 0; + for (int i = 0; i < heightSize; i++) + ans += (fmin(left[i], right[i]) - height[i]); + free(left), free(right); + return ans; +} + +int main() { + int h1[] = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}, h2[] = {4, 2, 0, 3, 2, 5}; + printf("%d\n", trap(h1, ARRAY_SIZE(h1))); // expect: 6 + printf("%d\n", trap(h2, ARRAY_SIZE(h2))); // expect: 9 +} diff --git a/trapping_rain_water.cpp b/trapping_rain_water.cpp new file mode 100644 index 0000000..d2ced43 --- /dev/null +++ b/trapping_rain_water.cpp @@ -0,0 +1,33 @@ +#include "leetcode.h" + +class Solution { +public: + int trap(vector<int> &height) { + if (height.size() <= 2) + return 0; + int n = height.size(), maxLeft = height[0], maxRight = height[n - 1]; + int left = 1, right = n - 2, ans = 0; + while (left <= right) { + if (maxLeft < maxRight) { + if (height[left] > maxLeft) + maxLeft = height[left]; + else + ans += maxLeft - height[left]; + left += 1; + } else { + if (height[right] > maxRight) + maxRight = height[right]; + else + ans += maxRight - height[right]; + right -= 1; + } + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> height = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}; + cout << obj.trap(height); +} diff --git a/trapping_rain_water.py b/trapping_rain_water.py new file mode 100644 index 0000000..28afec3 --- /dev/null +++ b/trapping_rain_water.py @@ -0,0 +1,32 @@ +# 42. Trapping Rain Water + +""" +given 'n' non-negative integers representing an elevation map where the width +of each bar is 1, compute how much water it can trap after raining. +""" + + +class Solution(object): + def trap(self, height): + """ + :type height: List[int] + :rtype: int + """ + n = len(height) + left, right = [0] * n, [0] * n + for i in range(1, n): + left[i] = max(height[i - 1], left[i - 1]) + for i in range(n - 2, -1, -1): + right[i] = max(height[i + 1], right[i + 1]) + ans = 0 + for i in range(n): + level = min(left[i], right[i]) + if level >= height[i]: + ans += level - height[i] + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.trap(height=[0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1])) + print(obj.trap(height=[4, 2, 0, 3, 2, 5])) diff --git a/triangle.cpp b/triangle.cpp new file mode 100644 index 0000000..d7e826b --- /dev/null +++ b/triangle.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + int minimumTotal(vector<vector<int>> &triangle) { + vector<int> ans(triangle.size(), triangle[0][0]); + for (int i = 1; i < triangle.size(); i++) + for (int j = i; j >= 0; j--) { + if (j == 0) + ans[0] += triangle[i][j]; + else if (j == i) + ans[j] = triangle[i][j] + ans[j - 1]; + else + ans[j] = triangle[i][j] + min(ans[j - 1], ans[j]); + } + return *min_element(ans.begin(), ans.end()); + } +}; + +int main() {} diff --git a/trie_prefix.c b/trie_prefix.c new file mode 100644 index 0000000..6211233 --- /dev/null +++ b/trie_prefix.c @@ -0,0 +1,65 @@ +// 208. Implement Trie (Prefix Tree) +#include <stdbool.h> +#include <stdlib.h> + +typedef struct Trie { + struct Trie *children[26]; + bool is_leaf; +} Trie; + +Trie *trieCreate() { + Trie *node = malloc(sizeof(Trie)); + for (int i = 0; i < 26; i++) + node->children[i] = NULL; + node->is_leaf = false; + return node; +} + +void trieInsert(Trie *obj, char *word) { + Trie *tmp = obj; + for (int i = 0; word[i] != '\0'; i++) { + int idx = word[i] - 'a'; + if (tmp->children[idx] == NULL) + tmp->children[idx] = trieCreate(); + tmp = tmp->children[idx]; + } + tmp->is_leaf = true; +} + +bool trieSearch(Trie *obj, char *word) { + Trie *tmp = obj; + for (int i = 0; word[i] != '\0'; i++) { + int idx = word[i] - 'a'; + if (tmp->children[idx] == NULL) + return false; + tmp = tmp->children[idx]; + } + return tmp->is_leaf; +} + +bool trieStartsWith(Trie *obj, char *prefix) { + Trie *tmp = obj; + for (int i = 0; prefix[i] != '\0'; i++) { + int idx = prefix[i] - 'a'; + if (tmp->children[idx] == NULL) + return false; + tmp = tmp->children[idx]; + } + return true; +} + +void trieFree(Trie *obj) { + Trie *tmp = obj; + for (int i = 0; i < 26; i++) + if (tmp->children[i] != NULL) + trieFree(tmp->children[i]); + free(obj); +} + +int main() { + Trie *obj = trieCreate(); + trieInsert(obj, word); + bool param_2 = trieSearch(obj, word); + bool param_3 = trieStartsWith(obj, prefix); + trieFree(obj); +} diff --git a/trie_prefix.cpp b/trie_prefix.cpp new file mode 100644 index 0000000..b56e38b --- /dev/null +++ b/trie_prefix.cpp @@ -0,0 +1,45 @@ +// 208. Implement Trie (Prefix Tree) +#include "leetcode.h" + +class Trie { +public: + Trie() {} + void insert(string word) { + Trie *node = this; + for (char c : word) { + if (!node->next.count(c)) + node->next[c] = new Trie(); + node = node->next[c]; + } + node->is_word = true; + } + bool search(string word) { + Trie *node = this; + for (char c : word) { + if (!node->next.count(c)) + return false; + node = node->next[c]; + } + return node->is_word; + } + bool startsWith(string prefix) { + Trie *node = this; + for (char c : prefix) { + if (!node->next.count(c)) + return false; + node = node->next[c]; + } + return true; + } + +private: + map<char, Trie *> next = {}; + bool is_word = false; +}; + +int main() { + Trie *obj = new Trie(); + obj->insert("Trie"); + bool param_2 = obj->search("Trie"); + bool param_3 = obj->startsWith("Trie"); +} diff --git a/trim_binary_tree.cpp b/trim_binary_tree.cpp new file mode 100644 index 0000000..3f4168a --- /dev/null +++ b/trim_binary_tree.cpp @@ -0,0 +1,47 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> searchRange(vector<int> &nums, int target) { + int s = 0, e = nums.size() - 1; + vector<int> ans(2, -1); + // first position + while (s <= e) { + int m = s + (e - s) / 2; + if (nums[m] < target) + s = m + 1; + else if (nums[m] > target) + e = m - 1; + else { + if (m == s || nums[m] != nums[m - 1]) { + ans[0] = m; + break; + } else { + e = m - 1; + ans[0] = m - 1; + } + } + } + // second position + s = 0, e = nums.size() - 1; + while (s <= e) { + int m = s + (e - s) / 2; + if (nums[m] < target) + s = m + 1; + else if (nums[m] > target) + e = m - 1; + else { + if (m == e || nums[m] != nums[m + 1]) { + ans[1] = m; + break; + } else { + s = m + 1; + ans[1] = m + 1; + } + } + } + return ans; + } +}; + +int main() {} diff --git a/triples_bitwise_and_zero.c b/triples_bitwise_and_zero.c new file mode 100644 index 0000000..c094980 --- /dev/null +++ b/triples_bitwise_and_zero.c @@ -0,0 +1,30 @@ +// 982. Triples with Bitwise AND Equal To Zero +#include "leetcode.h" + +/* + * given an integer array nums, return the number of AND triplets. an AND triple + * is a triple of indices '(i, j, k)' such that '0 <= i < nums.length', '0 <= j + * < nums.length', '0 <= k < nums.length', 'nums[i] & nums[j] & nums[k] == 0' + * where '&' represents the bitwise AND operator + */ + +int countTriplets(int *nums, int nums_size) { + int ans = 0, n = nums_size; + int *filled = calloc(n, sizeof(int)); + for (int i = 0; i < n; i++) { + filled[nums[i]]++; + int cnt = 0; + for (int j = 0; j <= i; j++) + cnt += filled[j]; + if (cnt == i + 1) + ans++; + } + free(filled); + return ans; +} + +int main() { + int n1[] = {2, 1, 3}, n2[] = {0, 0, 0}; + printf("%d\n", countTriplets(n1, ARRAY_SIZE(n1))); // expect: 12 + printf("%d\n", countTriplets(n2, ARRAY_SIZE(n2))); // expect: 27 +} diff --git a/triples_bitwise_and_zero.py b/triples_bitwise_and_zero.py new file mode 100644 index 0000000..0d71669 --- /dev/null +++ b/triples_bitwise_and_zero.py @@ -0,0 +1,28 @@ +# 982. Triples with Bitwise AND Equal To Zero + +""" +given an integer array nums, return the number of AND triplets. an AND triple +is a triple of indices '(i, j, k)' such that '0 <= i < nums.length', '0 <= j +< nums.length', '0 <= k < nums.length', 'nums[i] & nums[j] & nums[k] == 0' +where '&' represents the bitwise AND operator +""" + + +class Solution(object): + def countTriplets(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + n, ans, dict1 = len(nums), 0, collections.Counter(x&y for x in nums for y in nums) + for i in nums: + for j in dict1: + if i & j == 0: + ans += dict1[j] + return ans; + + +if __name__ == "__main__": + obj = Solution() + print(obj.countTriplets([2,1,3])) # expect: 12 + print(obj.countTriplets([0,0,0])) # expect: 27 diff --git a/tuple_same_product.c b/tuple_same_product.c new file mode 100644 index 0000000..18b90bb --- /dev/null +++ b/tuple_same_product.c @@ -0,0 +1,26 @@ +// 1726. Tuple with Same Product +#include "leetcode.h" + +/* + * given an array 'nums' of distinct positive integers return the number of + * tuples '(a,b,c,d)' such that 'a * b = c * d' where 'a,b,c,d' are elements of + * 'nums' and 'a != b != c != d' + */ + +int tupleSameProduct(int *nums, int numsSize) { + int ans = 0, *cnt = (int *)calloc(9999999, sizeof(int)); + for (int i = 0; i < numsSize; i++) + for (int j = 0; j < i; j++) { + const int product = nums[i] * nums[j]; + ans += cnt[product]; + cnt[product]++; + } + free(cnt); + return ans * 8; +} + +int main() { + int n1[] = {2, 3, 4, 6}, n2[] = {1, 2, 4, 5, 10}; + printf("%d\n", tupleSameProduct(n1, ARRAY_SIZE(n1))); // expect: 8 + printf("%d\n", tupleSameProduct(n2, ARRAY_SIZE(n2))); // expect: 16 +} diff --git a/tuple_same_product.py b/tuple_same_product.py new file mode 100644 index 0000000..2d08175 --- /dev/null +++ b/tuple_same_product.py @@ -0,0 +1,28 @@ +# 1726. Tuple with Same Product + +""" +given an array 'nums' of distinct positive integers return the number of +tuples '(a,b,c,d)' such that 'a b = c d' where 'a,b,c,d' are elements of +'nums' and 'a != b != c != d' +""" + + +class Solution(object): + def tupleSameProduct(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + ans, freq = 0, {} + for i in range(len(nums)): + for j in range(i + 1, len(nums)): + key = nums[i] * nums[j] + ans += freq.get(key, 0) + freq[key] = 1 + freq.get(key, 0) + return ans * 8 + + +if __name__ == "__main__": + obj = Solution() + print(obj.tupleSameProduct(nums=[2, 3, 4, 6])) + print(obj.tupleSameProduct(nums=[1, 2, 4, 5, 10])) diff --git a/two_sum.c b/two_sum.c new file mode 100644 index 0000000..33b1cc4 --- /dev/null +++ b/two_sum.c @@ -0,0 +1,42 @@ +// 1. Two Sum +#include <lib/uthash.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given an array of integer 'nums' and an integer 'target', return indices of + * the two numbers such that they add up to target. you may assume that each + * input would have exactly one solution, and you may not use the same element + * twice. return in any order + */ + +typedef struct { + int num; + int idx; + UT_hash_handle h; +} num_t; +u + + int * + twoSum(int *nums, int nums_size, int target, int *res_size) { + int *ans = calloc((*res_size), sizeof(int)); + num_t *hash; +} + +int main() { + int n1[] = {2, 7, 11, 15}, ns1 = 4, t1 = 9, rs1[] = {1, 1}; + int n2[] = {3, 2, 4}, ns2 = 2, t2 = 6, rs2[] = {1, 1}; + int n3[] = {3}, ns3 = 2, t3 = 6, rs3[] = {1, 1}; + int *ts1 = twoSum(n1, ns1, t1, rs1); + int *ts2 = twoSum(n2, ns2, t2, rs2); + int *ts3 = twoSum(n3, ns3, t3, rs3); + for (int i = 0; i < 2; i++) + printf("%d ", ts1[i]); + printf("\n"); + for (int i = 0; i < 2; i++) + printf("%d ", ts2[i]); + printf("\n"); + for (int i = 0; i < 2; i++) + printf("%d ", ts2[i]); + printf("\n"); +} diff --git a/two_sum.cpp b/two_sum.cpp new file mode 100644 index 0000000..e75565d --- /dev/null +++ b/two_sum.cpp @@ -0,0 +1,35 @@ +// 1. Two Sum +#include "leetcode.h" + +class Solution { +public: + vector<int> twoSum(vector<int> &nums, int target) { + vector<int> ans; + unordered_map<int, int> um; + int n = nums.size(); + for (int i = 0; i < n; i++) { + int search_num = target - nums[i]; + if (um.find(search_num) != um.end()) { + ans.push_back(um[search_num]); + ans.push_back(i); + break; + } + um[nums[i]] = i; + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> n1 = {2, 7, 11, 15}, n2 = {3, 2, 4}, n3 = {3, 3}; + for (auto i : obj.twoSum(n1, 9)) + printf("%d ", i); + printf("\n"); + for (auto i : obj.twoSum(n2, 6)) + printf("%d ", i); + printf("\n"); + for (auto i : obj.twoSum(n3, 6)) + printf("%d ", i); + printf("\n"); +} diff --git a/two_sum_2.cpp b/two_sum_2.cpp new file mode 100644 index 0000000..55741ac --- /dev/null +++ b/two_sum_2.cpp @@ -0,0 +1,33 @@ +#include "leetcode.h" +#include <vector> + +class Solution { +public: + vector<int> twoSum(vector<int> &numbers, int target) { + vector<int> ans; + for (int i = 0; i < numbers.size(); i++) { + int low = 0, high = numbers.size() - 1; + while (low <= high) { + int mid = low + (high - low) / 2; + if (numbers[mid] == target - numbers[i]) { + if (mid == i) + low = mid + 1; + else + return {i + 1, mid + 1}; + } else if (numbers[mid] < target - numbers[i]) + low = mid + 1; + else + high = mid - 1; + } + } + return ans; + } +}; + +int main() { + Solution obj; + vector<int> numbers = {2, 7, 11, 15}; + int target = 9; + // expected output: 1,2 + obj.twoSum(numbers, target); +} diff --git a/two_sum_4.cpp b/two_sum_4.cpp new file mode 100644 index 0000000..c25bcc9 --- /dev/null +++ b/two_sum_4.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + bool findTarget(TreeNode *root, int k) { + vector<int> nums; + order(root, nums); + for (int i = 0, j = nums.size() - 1; i < j;) { + if (nums[i] + nums[j] == k) + return true; + (nums[i] + nums[j] < k) ? i++ : j--; + } + return false; + } + +private: + void order(TreeNode *root, vector<int> &nums) { + if (root == NULL) + return; + order(root->left, nums); + nums.push_back(root->val); + order(root->right, nums); + } +}; diff --git a/ugly_number.cpp b/ugly_number.cpp new file mode 100644 index 0000000..8af53f8 --- /dev/null +++ b/ugly_number.cpp @@ -0,0 +1,21 @@ +#include "leetcode.h" + +class Solution { +public: + bool isUgly(int n) { + if (n == 0) + return false; + for (int i : {2, 3, 5}) + while (n % i == 0) + n /= i; + return n == 1; + } +}; + +int main() { + Solution obj; + if (obj.isUgly(6)) + cout << "true"; + else + cout << "false"; +} diff --git a/ugly_number.rs b/ugly_number.rs new file mode 100644 index 0000000..e356ff2 --- /dev/null +++ b/ugly_number.rs @@ -0,0 +1,19 @@ +struct Solution; + +impl Solution { + pub fn is_ugly(mut n: i32) -> bool { + if n == 0 { + return false; + } + for i in vec![2,3,5] { + while n % i == 0 { + n /= i; + } + } + n == 1 + } +} + +fn main() { + print!("{}", Solution::is_ugly(6)); +} diff --git a/ugly_number2.c b/ugly_number2.c new file mode 100644 index 0000000..194514b --- /dev/null +++ b/ugly_number2.c @@ -0,0 +1,31 @@ +// 264. Ugly Number II +#include "leetcode.h" + +/* + * an ugly number is a positive integer whose prime factors are limited to + * 2,3,5. given an integer 'n', return the n'th ugly number + */ + +int nthUglyNumber(int n) { + int *ugly_nums = (int *)malloc(n * sizeof(int)); + ugly_nums[0] = 1; + int idx2 = 0, idx3 = 0, idx5 = 2, f2 = 0, f3 = 3, f5 = 5; + for (int i = 1; i < n; i++) { + int tmp = f2 < f3 ? f2 : f3, min = tmp < f5 ? tmp : f5; + ugly_nums[i] = min; + if (min == f2) + f2 = 2 * ugly_nums[++idx2]; + if (min == f3) + f3 = 3 * ugly_nums[++idx3]; + if (min == f5) + f5 = 5 * ugly_nums[++idx5]; + } + int ans = ugly_nums[n - 1]; + free(ugly_nums); + return ans; +} + +int main() { + printf("%d\n", nthUglyNumber(10)); // expect: 12 + printf("%d\n", nthUglyNumber(1)); // expect: 1 +} diff --git a/ugly_number2.py b/ugly_number2.py new file mode 100644 index 0000000..a2906e1 --- /dev/null +++ b/ugly_number2.py @@ -0,0 +1,28 @@ +# 264. Ugly Number II + +""" +an ugly number is a positive integer whose prime factors are limited to +2,3,5. given an integer 'n', return the n'th ugly number +""" + + +class Solution(object): + def nthUglyNumber(self, n): + """ + :type n: int + :rtype: int + """ + factors, k = [2, 3, 5], 3 + starts, Numbers = [0] * k, [1] + for i in range(n - 1): + candidates = [factors[i] * Numbers[starts[i]] for i in range(k)] + new_num = min(candidates) + Numbers.append(new_num) + starts = [starts[i] + (candidates[i] == new_num) for i in range(k)] + return Numbers[-1] + + +if __name__ == "__main__": + obj = Solution() + print(obj.nthUglyNumber(10)) + print(obj.nthUglyNumber(1)) diff --git a/uncrossed_lines.c b/uncrossed_lines.c new file mode 100644 index 0000000..e56aec8 --- /dev/null +++ b/uncrossed_lines.c @@ -0,0 +1,59 @@ +// 1035. Uncrossed Lines +#include <math.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given two integer arrays 'nums1' and 'num2'. we write the integers of 'nums1' + * and 'nums2' (in the order they are given) on two separate horizontal lines. + * we may draw connecting lines: a straight line connecting two numbers + * 'nums1[i]' and 'nums2[j]' such thatyr + * - 'nums1[i] == nums2[j]' and + * - the line we draw does not intersect any other connecting (non-horizontal) + * line note that a connecting line cannot intereset even at the endpoints. + * return the maximum number of connecting lines we can draw in this way. + */ + +int maxUncrossedLines(int *nums1, int nums1_size, int *nums2, int nums2_size) { + int i, j; + int **dp = (int **)malloc(nums1_size * sizeof(int *)); + for (i = 0; i < nums1_size; i++) + dp[i] = malloc(nums2_size * sizeof(int)); + if (nums1[0] == nums2[0]) + dp[0][0] = 1; + else + dp[0][0] = 0; + for (i = 1; i < nums2_size; i++) { + if (nums1[0] == nums2[i]) + dp[0][i] = 1; + else + dp[0][i] = dp[0][i - 1]; + } + for (i = 1; i < nums1_size; i++) { + if (nums1[i] == nums2[0]) + dp[i][0] = 1; + else + dp[i][0] = dp[i - 1][0]; + } + for (i = 1; i < nums1_size; i++) + for (j = 1; j < nums2_size; j++) { + if (nums1[i] == nums2[j]) + dp[i][j] = 1 + dp[i - 1][j - 1]; + else + dp[i][j] = fmax(dp[i - 1][j], dp[i][j - 1]); + } + int ans = dp[nums1_size - 1][nums2_size - 1]; + for (i = 0; i < nums1_size; i++) + free(dp[i]); + free(dp); + return ans; +} + +int main() { + int n11[] = {1, 4, 2}, n21[] = {1, 2, 4}; + int n12[] = {2, 5, 1, 2, 5}, n22[] = {10, 5, 2, 1, 5, 2}; + int n13[] = {1, 3, 7, 1, 7, 5}, n23[] = {1, 9, 2, 5, 1}; + printf("%d\n", maxUncrossedLines(n11, 3, n21, 3)); // expect: 2 + printf("%d\n", maxUncrossedLines(n12, 5, n22, 6)); // expect: 3 + printf("%d\n", maxUncrossedLines(n13, 6, n23, 5)); // expect: 2 +} diff --git a/uncrossed_lines.cpp b/uncrossed_lines.cpp new file mode 100644 index 0000000..227faa9 --- /dev/null +++ b/uncrossed_lines.cpp @@ -0,0 +1,39 @@ +// 1035. Uncrossed Lines +#include "leetcode.h" + +/* + * given two integer arrays 'nums1' and 'num2'. we write the integers of 'nums1' + * and 'nums2' (in the order they are given) on two separate horizontal lines. + * we may draw connecting lines: a straight line connecting two numbers + * 'nums1[i]' and 'nums2[j]' such thatyr + * - 'nums1[i] == nums2[j]' and + * - the line we draw does not intersect any other connecting (non-horizontal) + * line note that a connecting line cannot intereset even at the endpoints. + * return the maximum number of connecting lines we can draw in this way. + */ + +class Solution { +public: + int maxUncrossedLines(vector<int> &nums1, vector<int> &nums2) { + int n = nums1.size(), m = nums2.size(); + vvd(int) dp(n + 1, vector<int>(m + 1, 0)); + for (int i = 1; i <= n; i++) + for (int j = 1; j <= m; j++) { + if (nums1[i - 1] == nums2[j - 1]) + dp[i][j] = 1 + dp[i - 1][j - 1]; + else + dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]); + } + return dp[n][m]; + } +}; + +int main() { + Solution obj; + vector<int> n11 = {1, 4, 2}, n21 = {1, 2, 4}; + vector<int> n12 = {2, 5, 1, 2, 5}, n22 = {10, 5, 2, 1, 5, 2}; + vector<int> n13 = {1, 3, 7, 1, 7, 5}, n23 = {1, 9, 2, 5, 1}; + printf("%d\n", obj.maxUncrossedLines(n11, n21)); // expect: 2 + printf("%d\n", obj.maxUncrossedLines(n12, n22)); // expect: 3 + printf("%d\n", obj.maxUncrossedLines(n13, n23)); // expect: 2 +} diff --git a/underground_system.cpp b/underground_system.cpp new file mode 100644 index 0000000..fd4fbbf --- /dev/null +++ b/underground_system.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class UndergroundSystem { +public: + unordered_map<int, pair<string, int>> checkIns; + unordered_map<string, pair<int, int>> routes; + UndergroundSystem() {} + void checkIn(int id, string stationName, int t) { + checkIns[id] = {stationName, t}; + } + void checkOut(int id, string stationName, int t) { + auto [stn, start] = checkIns[id]; + checkIns.erase(id); + string route = stn + "," + stationName; + routes[route].first++; + routes[route].second += t - start; + } + double getAverageTime(string startStation, string endStation) { + auto &[count, sum] = routes[startStation + "," + endStation]; + return (double)sum / count; + } +}; + +int main() {} diff --git a/unique_bst.c b/unique_bst.c new file mode 100644 index 0000000..2e1ffad --- /dev/null +++ b/unique_bst.c @@ -0,0 +1,29 @@ +// 96. Unique Binary Search Trees +#include <stdio.h> + +/* + * given an integer 'n', return the number of structurally unique BST's which + * has exactly 'n' nodes of unique values from 1 to 'n' + */ + +int numTrees(int n) { + int rem[n + 1]; + if (!n) + return 1; + if (n == 1 || n == 2) + return n; + rem[0] = 1; + rem[1] = 1; + rem[2] = 2; + for (int i = 3; i <= n; i++) { + rem[i] = 0; + for (int j = 1; j <= i; j++) + rem[i] = rem[i] + rem[i - j] * rem[j - 1]; + } + return rem[n]; +} + +int main() { + printf("%d\n", numTrees(3)); // expect: 5 + printf("%d\n", numTrees(1)); // expect: 1 +} diff --git a/unique_bst.cpp b/unique_bst.cpp new file mode 100644 index 0000000..7aefacd --- /dev/null +++ b/unique_bst.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + int numTrees(int n) { + if (n == 1) + return 1; + vector<int> dp(n + 1); + dp[0] = dp[1] = 1; + for (int i = 2; i <= n; i++) { + for (int j = 0; j < i; j++) { + int k = i - 1 - j; + dp[i] += (dp[j] * dp[k]); + } + } + return dp[n]; + } +}; + +int main() { + Solution obj; + cout << obj.numTrees(3); +} diff --git a/unique_bst2.c b/unique_bst2.c new file mode 100644 index 0000000..8b48961 --- /dev/null +++ b/unique_bst2.c @@ -0,0 +1,63 @@ +// 95. Unique Binary Search Trees II +#include <stdlib.h> + +/* + * given an integer 'n', return all the structurally unique BST's which has + * exactly 'n' nodes of unique values from 1 to 'n'. return the answer in any + * order. + */ + +struct TreeNode { + int val; + struct TreeNode *left; + struct TreeNode *right; +}; + +struct TreeNode **process(int begin, int end, int *return_size, int *tree_num) { + if (begin > end) { + struct TreeNode **res = malloc(sizeof(struct TreeNode *)); + *return_size = 1; + res[0] = NULL; + return res; + } + if (begin == end) { + struct TreeNode *root = malloc(sizeof(struct TreeNode)); + root->val = begin; + root->left = NULL; + root->right = NULL; + struct TreeNode **res = malloc(sizeof(struct TreeNode *)); + res[0] = root; + *return_size = 1; + return res; + } + int idx = 0; + struct TreeNode **res = + malloc(tree_num[end - begin + 1] * sizeof(struct TreeNode *)); + for (int i = begin; i <= end; i++) { + int ln, rn; + struct TreeNode **l = process(begin, i - 1, &ln, tree_num); + struct TreeNode **r = process(i + 1, end, &rn, tree_num); + for (int m = 0; m < ln; m++) { + for (int n = 0; n < rn; n++) { + struct TreeNode *root = malloc(sizeof(struct TreeNode)); + root->val = i; + root->left = l[m]; + root->right = r[n]; + res[idx] = root; + idx++; + } + } + } + *return_size = idx; + return res; +} + +struct Treenode **generateTrees(int n, int *return_size) { + int *tree_num = calloc(n + 1, sizeof(int)); + tree_num[0] = 1; + tree_num[1] = 1; + for (int i = 2; i <= n; i++) + for (int j = 0; j < i; j++) + tree_num[i] += tree_num[j] * tree_num[i - 1 - j]; + return process(1, n, return_size, tree_num); +} diff --git a/unique_bst2.cpp b/unique_bst2.cpp new file mode 100644 index 0000000..438d9b7 --- /dev/null +++ b/unique_bst2.cpp @@ -0,0 +1,34 @@ +// 95. Unique Binary Search Trees II +#include "leetcode.h" + +/* + * given an integer 'n', return all the structurally unique BST's which has + * exactly 'n' nodes of unique values from 1 to 'n'. return the answer in any + * order. + */ + +class Solution { + vector<TreeNode *> build(int from, int to) { + vector<TreeNode *> res; + if (to - from < 0) + res.push_back(0); + if (to - from == 0) + res.push_back(new TreeNode(from)); + if (to - from > 0) + for (int i = 0; i <= to; i++) { + vector<TreeNode *> left = build(from, i - 1); + vector<TreeNode *> right = build(i + 1, to); + for (int j = 0; j < left.size(); j++) + for (int k = 0; k < right.size(); k++) { + TreeNode *height = new TreeNode(i); + height->left = left[j]; + height->right = right[k]; + res.push_back(height); + } + } + return res; + } + +public: + vector<TreeNode *> generateTrees(int n) { return build(1, n); } +}; diff --git a/unique_len_3_palindrome.c b/unique_len_3_palindrome.c new file mode 100644 index 0000000..2f8efc9 --- /dev/null +++ b/unique_len_3_palindrome.c @@ -0,0 +1,44 @@ +// 1930. Unique Length-3 Palindromic Subsequences +#include "leetcode.h" + +/* + * given a string 's', return the number of unique palindromes of length three + * that that are a subsequence of 's'. note that even if there are multiple ways + * to obtain the same subsequence, it is still only counted once. a palindrome + * is a string that reads the same forwards and backwards. a subsequence of a + * string is a new string generated from the original string with some + * characters (can be none) deleted without changing the relative order of thhe + * remaining characters. for example: "ace" is a subsequence of "abcde" + */ + +int countPalindromicSubsequence(char *s) { + int n = strlen(s), ans = 0; + bool *alpha = calloc(26, sizeof(bool)); + bool *tmp; + for (int i = 0; i < n; i++) { + if (alpha[s[i] - 'a']) + continue; + alpha[s[i] - 'a'] = 1; + char c = s[i]; + for (int j = n - 1; j > i + 1; j--) { + if (s[j] == s[i]) { + tmp = calloc(26, sizeof(char)); + for (int k = i + 1; k < j; k++) { + if (!tmp[s[k] - 'a']) { + tmp[s[k] - 'a'] = 1; + ans++; + } + } + break; + } + } + } + return ans; +} + +int main() { + char s1[] = {"aabca"}, s2[] = {"adc"}, s3[] = {"bbcbaba"}; + printf("%d\n", countPalindromicSubsequence(s1)); // expect: 3 + printf("%d\n", countPalindromicSubsequence(s2)); // expect: 0 + printf("%d\n", countPalindromicSubsequence(s3)); // expect: 4 +} diff --git a/unique_len_3_palindrome.py b/unique_len_3_palindrome.py new file mode 100644 index 0000000..a055519 --- /dev/null +++ b/unique_len_3_palindrome.py @@ -0,0 +1,29 @@ +# 1930. Unique Length-3 Palindromic Subsequences +import string + +""" +given a string 's', return the number of unique palindromes of length three +that that are a subsequence of 's'. note that even if there are multiple ways +to obtain the same subsequence, it is still only counted once. a palindrome +is a string that reads the same forwards and backwards. a subsequence of a +string is a new string generated from the original string with some +characters (can be none) deleted without changing the relative order of thhe +remaining characters. for example: "ace" is a subsequence of "abcde" +""" + + +class Solution(object): + def countPalindromicSubsequence(self, s): + ans = 0 + for c in string.ascii_lowercase: + i, j = s.find(c), s.rfind(c) + if i > -1: + ans += len(set(s[i + 1 : j])) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.countPalindromicSubsequence("aabca")) # expect: 3 + print(obj.countPalindromicSubsequence("adc")) # expect: 0 + print(obj.countPalindromicSubsequence("bbcbaba")) # expect: 4 diff --git a/unique_morse_code_words.cpp b/unique_morse_code_words.cpp new file mode 100644 index 0000000..2a6280e --- /dev/null +++ b/unique_morse_code_words.cpp @@ -0,0 +1,25 @@ +#include "leetcode.h" + +class Solution { +public: + int uniqueMorseRepresentations(vector<string> &words) { + vector<string> codes = { + ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", + ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", + "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."}; + set<string> ans; + for (auto word : words) { + string curr = ""; + for (auto ch : word) + curr += codes[ch - 97]; + ans.insert(curr); + } + return ans.size(); + } +}; + +int main() { + Solution obj; + vector<string> words = {"gin", "zen", "gig", "msg"}; + cout << obj.uniqueMorseRepresentations(words); +} diff --git a/unique_num_occurrences.c b/unique_num_occurrences.c new file mode 100644 index 0000000..82449d9 --- /dev/null +++ b/unique_num_occurrences.c @@ -0,0 +1,47 @@ +// 1207. Unique Number of Occurrences +#include "leetcode.h" + +/* + * given an array of integers 'arr', return 'true' if the number of occurences + * of each value in the array is unique or 'false' otherwise + */ + +int cmp(const void *a, const void *b) { + return *(const int *)b - *(const int *)a; +} + +int find_size(int *arr, int arr_size, int *min) { + int max = arr[0]; + for (int i = 1; i < arr_size; i++) { + max = arr[i] > max ? arr[i] : max; + *min = arr[i] < *min ? arr[i] : *min; + } + return *min < 0 ? max + abs(*min) + 1 : max + 1; +} + +bool uniqueOccurences(int *arr, int arr_size) { + int shift = arr[0], size = find_size(arr, arr_size, &shift); + shift = (shift > 0) ? 0 : abs(shift); + int *hash = (int *)calloc(size, sizeof(int)); + for (int i = 0; i < arr_size; i++) + hash[arr[i] + shift]++; + qsort(hash, size, sizeof(int), cmp); + for (int i = 0; i + 1 < size; i++) { + if (!hash[i + 1]) + break; + if (hash[i] == hash[i + 1]) { + free(hash); + return false; + } + } + free(hash); + return true; +} + +int main() { + int a1[] = {1, 2, 2, 1, 1, 3}, a2[] = {1, 2}, + a3[] = {-3, 0, 1, -3, 1, 1, 1, -3, 10, 0}; + printf("%d\n", uniqueOccurences(a1, ARRAY_SIZE(a1))); // expect: 1 + printf("%d\n", uniqueOccurences(a2, ARRAY_SIZE(a2))); // expect: 0 + printf("%d\n", uniqueOccurences(a3, ARRAY_SIZE(a3))); // expect: 1 +} diff --git a/unique_num_occurrences.cpp b/unique_num_occurrences.cpp new file mode 100644 index 0000000..5c4871f --- /dev/null +++ b/unique_num_occurrences.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + bool uniqueOccurrences(vector<int> &arr) { + short m[2001] = {}; + for (auto n : arr) + ++m[n + 1000]; + sort(begin(m), end(m)); + for (auto i = 1; i < 2001; ++i) + if (m[i] && m[i] == m[i - 1]) + return false; + return true; + } +}; + +int main() { + Solution obj; + vector<int> arr = {1, 2, 2, 1, 1, 3}; + if (obj.uniqueOccurrences(arr)) + cout << "true"; + else + cout << "false"; +} diff --git a/unique_num_occurrences.py b/unique_num_occurrences.py new file mode 100644 index 0000000..1ffa9a0 --- /dev/null +++ b/unique_num_occurrences.py @@ -0,0 +1,36 @@ +# 1207. Unique Number of Occurrences + +""" +given an array of integers 'arr', return 'true' if the number of occurences +of each value in the array is unique or 'false' otherwise +""" + + +class Solution(object): + def uniqueOccurrences(self, arr): + """ + :type arr: List[int] + :rtype: bool + """ + arr.sort() + v = [] + i = 0 + while i < len(arr): + cnt = 1 + while i + 1 < len(arr) and arr[i] == arr[i + 1]: + cnt += 1 + i += 1 + v.append(cnt) + i += 1 + v.sort() + for i in range(1, len(v)): + if v[i] == v[i - 1]: + return False + return True + + +if __name__ == "__main__": + obj = Solution() + print(obj.uniqueOccurrences(arr=[1, 2, 2, 1, 1, 3])) + print(obj.uniqueOccurrences(arr=[1, 2])) + print(obj.uniqueOccurrences(arr=[-3, 0, 1, -3, 1, 1, 1, -3, 10, 0])) diff --git a/unique_num_occurrences.rs b/unique_num_occurrences.rs new file mode 100644 index 0000000..d29c580 --- /dev/null +++ b/unique_num_occurrences.rs @@ -0,0 +1,20 @@ +struct Solution; + +impl Solution { + pub fn unique_occurrences(arr: Vec<i32>) -> bool { + let (mut counter, mut set) = ([0; 2001], [false; 1000]); + arr.iter().for_each(|&x| counter[(x + 1000) as usize] += 1); + for &x in counter.iter().filter(|&&x| x > 0) { + match set[x as usize] { + true => return false, + false => set[x as usize] = true + } + } + true + } +} + +fn main() { + let arr = vec![1,2,2,1,1,3]; + print!("{}", Solution::unique_occurrences(arr)); +} diff --git a/unique_paths.cpp b/unique_paths.cpp new file mode 100644 index 0000000..053a92b --- /dev/null +++ b/unique_paths.cpp @@ -0,0 +1,22 @@ +#include "leetcode.h" + +class Solution { +public: + int uniquePaths(int m, int n) { + int dp[m][n]; + for (int i = 0; i < m; i++) { + for (int j = 0; j < n; j++) { + if (i == 0 || j == 0) + dp[i][j] = 1; + else + dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; + } + } + return dp[m - 1][n - 1]; + } +}; + +int main() { + Solution obj; + cout << obj.uniquePaths(3, 7); +} diff --git a/unique_paths2.c b/unique_paths2.c new file mode 100644 index 0000000..608e439 --- /dev/null +++ b/unique_paths2.c @@ -0,0 +1,45 @@ +// 63. Unique Paths II +#include <stdlib.h> +#include <string.h> + +/* + You are given an m x n integer array grid. There is a robot initially located + at the top-left corner (i.e., grid[0][0]). The robot tries to move to the + bottom-right corner (i.e., grid[m - 1][n - 1]). The robot can only move either + down or right at any point in time. + + An obstacle and space are marked as 1 or 0 respectively in grid. A path that + the robot takes cannot include any square that is an obstacle. + + Return the number of possible unique paths that the robot can take to reach + the bottom-right corner. + + The testcases are generated so that the answer will be less than or equal to 2 + * 109. + */ + +int uniquePathsWithObstacles(int **grid, int rSize, int cSize) { + int **arrs = (int **)malloc(sizeof(int *) * rSize); + for (int i = 0; i < rSize; i++) { + arrs[i] = (int *)malloc(sizeof(int) * cSize); + memset(arrs[i], 0, sizeof(int) * cSize); + } + for (int i = 0; i < rSize; i++) + for (int j = 0; j < cSize; j++) { + if (i == 0 && j == 0 && grid[i][j] == 0) { + arrs[i][j] = 1; + continue; + } + if (grid[i][j] == 1) { + arrs[i][j] = 0; + continue; + } + int count = 0; + if (j - 1 > -1) + count += arrs[i][j - 1]; + if (i - 1 > -1) + count += arrs[i - 1][j]; + arrs[i][j] = count; + } + return arrs[rSize - 1][cSize - 1]; +} diff --git a/unique_paths2.cpp b/unique_paths2.cpp new file mode 100644 index 0000000..91a4201 --- /dev/null +++ b/unique_paths2.cpp @@ -0,0 +1,39 @@ +// 63. Unique Paths II +#include "leetcode.h" + +/* + You are given an m x n integer array grid. There is a robot initially located + at the top-left corner (i.e., grid[0][0]). The robot tries to move to the + bottom-right corner (i.e., grid[m - 1][n - 1]). The robot can only move either + down or right at any point in time. + + An obstacle and space are marked as 1 or 0 respectively in grid. A path that + the robot takes cannot include any square that is an obstacle. + + Return the number of possible unique paths that the robot can take to reach + the bottom-right corner. + + The testcases are generated so that the answer will be less than or equal to 2 + * 109. + */ + +class Solution { +public: + int uniquePathsWithObstacles(vector<vector<int>> &obstacleGrid) { + int m = obstacleGrid.size(), n = obstacleGrid[0].size(); + vvd(int) dp(m + 1, vector<int>(n + 1, 0)); + dp[0][1] = 1; + for (int i = 1; i <= m; ++i) + for (int j = 1; j <= n; ++j) + if (!obstacleGrid[i - 1][j - 1]) + dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; + return dp[m][n]; + } +}; + +int main() { + Solution obj; + vvd(int) og1 = {{0, 0, 0}, {0, 1, 0}, {0, 0, 0}}, og2 = {{0, 1}, {0, 0}}; + printf("%d\n", obj.uniquePathsWithObstacles(og1)); // expect: 2 + printf("%d\n", obj.uniquePathsWithObstacles(og2)); // expect: 1 +} diff --git a/unique_paths3.cpp b/unique_paths3.cpp new file mode 100644 index 0000000..3e8eb86 --- /dev/null +++ b/unique_paths3.cpp @@ -0,0 +1,38 @@ +#include "leetcode.h" + +class Solution { +public: + int uniquePathsIII(vvd(int) & grid) { + auto i1 = 0, j1 = 0, t_steps = 0; + for (auto i = 0; i < grid.size(); ++i) + for (auto j = 0; j < grid[0].size(); ++j) { + if (grid[i][j] == 1) + i1 = i, j1 = j; + if (grid[i][j] != -1) + ++t_steps; + } + return dfs(grid, i1, j1, 1, t_steps); + } + +private: + int dfs(vvd(int) & grid, int i, int j, int step, int t_step) { + if (i < 0 || j < 0 || i >= grid.size() || j >= grid[0].size() || + grid[i][j] == -1) + return 0; + if (grid[i][j] == 2) + return step == t_step ? 1 : 0; + grid[i][j] = -1; + int paths = dfs(grid, i + 1, j, step + 1, t_step) + + dfs(grid, i - 1, j, step + 1, t_step) + + dfs(grid, i, j + 1, step + 1, t_step) + + dfs(grid, i, j - 1, step + 1, t_step); + grid[i][j] = 0; + return paths; + } +}; + +int main() { + Solution obj; + vvd(int) grid = {{1, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 2, -1}}; + cout << obj.uniquePathsIII(grid); // expect: 2 +} diff --git a/unique_paths3.rs b/unique_paths3.rs new file mode 100644 index 0000000..b83c50e --- /dev/null +++ b/unique_paths3.rs @@ -0,0 +1,40 @@ +struct Solution; + +impl Solution { + pub fn unique_paths_iii(mut grid: Vec<Vec<i32>>) -> i32 { + let (start_x, start_y) = (0..grid.len()) + .flat_map(|y| (0..grid[0].len()).map(move |x| (x, y))) + .find(|&(x, y)| grid[y][x] == 1) + .expect("grid does not have starting square!"); + let num_empty = grid.iter() + .flat_map(|r| r.iter().filter(|&&c| c != -1)).count(); + Self::dfs(&mut grid, start_x, start_y, num_empty - 1) as _ + } + fn dfs(grid: &mut Vec<Vec<i32>>, x: usize, y: usize, num_empty: usize) -> usize { + if x >= grid[0].len() || y >= grid.len() { + return 0; + } + match grid[y][x] { + 0 | 1 => { + grid[y][x] = -1; + let curr_paths = [(0,1),(1,0),(0,-1),(-1,0)] + .iter() + .map(|&(dx, dy)| ((x as isize + dx) as _, (y as isize + dy) as _)) + .map(|(nx, ny)| Self::dfs(grid, nx, ny, num_empty - 1)).sum(); + grid[y][x] = 0; + curr_paths + } + 2 if num_empty == 0 => 1, + _ => 0 + } + } +} + +fn main() { + let grid = vec![ + vec![1,0,0,0], + vec![0,0,0,0], + vec![0,0,2,-1] + ]; + print!("{}", Solution::unique_paths_iii(grid)); +} diff --git a/utf8_validation.cpp b/utf8_validation.cpp new file mode 100644 index 0000000..0cb96d7 --- /dev/null +++ b/utf8_validation.cpp @@ -0,0 +1,38 @@ +#include "leetcode.h" + +class Solution { +public: + bool validUtf8(vector<int> &data) { + int m1 = 0x80, m2 = 0x20, m3 = 0x10, m4 = 0x08, m5 = 0xC0; + for (int i = 0; i < data.size(); i++) { + if ((m5 & data[i]) == m1) + return false; + int bytes{0}; + if ((m1 & data[i]) == 0) + continue; + else if ((m2 & data[i]) == 0) + bytes = 1; + else if ((m3 & data[i]) == 0) + bytes = 2; + else if ((m4 & data[i]) == 0) + bytes = 3; + else + return false; + while (bytes--) { + i++; + if (i >= data.size() || ((m5 & data[i]) != m1)) + return false; + } + } + return true; + } +}; + +int main() { + Solution obj; + vector<int> data = {197, 130, 1}; + if (obj.validUtf8(data)) + cout << "true"; + else + cout << "false"; +} diff --git a/valid_anagram.c b/valid_anagram.c new file mode 100644 index 0000000..e7f7c45 --- /dev/null +++ b/valid_anagram.c @@ -0,0 +1,33 @@ +// 242. Valid Anagram +#include "leetcode.h" + +/* + * given two strings 's' and 't', return 'true' if 't' is an anagram of 's', and + * false otherwise. an anagram is a word or phrase formed by rearranging the + * letters of a different word or phrase, typically using all the original + * letters exactly once. + */ + +bool isAnagram(char *s, char *t) { + if (strlen(s) != strlen(t)) + return 0; + int mask[256] = {}; + char *c = s; + while (*c) + mask[*c++]++; + c = t; + while (*c) { + if (mask[*c]) + mask[*c++]--; + else + return 0; + } + return 1; +} + +int main() { + char *s1 = "anagram", *t1 = "nagaram"; + char *s2 = "rat", *t2 = "car"; + printf("%d\n", isAnagram(s1, t1)); // expect: true + printf("%d\n", isAnagram(s2, t2)); // expect: false +} diff --git a/valid_anagram.cpp b/valid_anagram.cpp new file mode 100644 index 0000000..2c2586e --- /dev/null +++ b/valid_anagram.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +class Solution { +public: + bool isAnagram(string s, string t) { + if (s == t) + return true; + if (s.size() != t.size()) + return false; + unordered_map<char, int> up; + for (int i = 0; i < s.size(); i++) { + up[s[i]]++; + up[t[i]]--; + } + for (auto it : up) + if (it.second) + return false; + return true; + } +}; + +int main() { + Solution obj; + string s = "anagram", t = "nagaram"; + if (obj.isAnagram(s, t)) + cout << "true"; + else + cout << "false"; +} diff --git a/valid_anagram.py b/valid_anagram.py new file mode 100644 index 0000000..69e19d3 --- /dev/null +++ b/valid_anagram.py @@ -0,0 +1,26 @@ +# 242. Valid Anagram + +""" +given two strings 's' and 't', return 'true' if 't' is an anagram of 's', and +false otherwise. an anagram is a word or phrase formed by rearranging the +letters of a different word or phrase, typically using all the original +letters exactly once. +""" + + +class Solution(object): + def isAnagram(self, s, t): + """ + :type s: str + :type t: str + :rtype: bool + """ + sorted_s = sorted(s) + sorted_t = sorted(t) + return sorted_s == sorted_t + + +if __name__ == "__main__": + obj = Solution() + print(obj.isAnagram(s="anagram", t="nagaram")) + print(obj.isAnagram(s="rat", t="car")) diff --git a/valid_number.cpp b/valid_number.cpp new file mode 100644 index 0000000..6395fe0 --- /dev/null +++ b/valid_number.cpp @@ -0,0 +1,45 @@ +#include "leetcode.h" + +class Solution { +public: + bool isNumber(string s) { + int state = 0, flag = 0; + while (s[0] == ' ' || s[s.size() - 1] == ' ') + s.erase(s.size() - 1, 1); + for (int i = 0; i < s.size(); i++) { + if ('0' <= s[i] && s[i] <= '9') { + flag = 1; + if (state <= 2) + state = 2; + else + state = (state <= 5) ? 5 : 7; + } else if (s[i] == '+' || s[i] == '-') { + if (state == 0 || state == 3) + state++; + else + return false; + } else if (s[i] == '.') { + if (state <= 2) + state = 6; + else + return false; + } else if (s[i] == 'e') { + if (flag && (state == 2 || state == 6 || state == 7)) + state = 3; + else + return false; + } else + return false; + } + return (state == 2 || state == 5 || (flag && state == 6) || state == 7); + } +}; + +int main() { + Solution obj; + string s = "3"; + if (obj.isNumber(s)) + cout << "true"; + else + cout << "false"; +} diff --git a/valid_palindrome2.c b/valid_palindrome2.c new file mode 100644 index 0000000..d001717 --- /dev/null +++ b/valid_palindrome2.c @@ -0,0 +1,31 @@ +// 680. Valid Palindrome II +#include "leetcode.h" + +/* + * given a string 's', return 'true' if the 's' can be palindrome after deleting + * at most one charater from it. + */ + +bool check(char *s, int n) { + if (n <= 1) + return 1; + for (int i = 0; i < n / 2; i++) + if (s[i] != s[n - i - 1]) + return 0; + return 1; +} + +bool validPalindrome(char *s) { + int n = strlen(s); + for (int i = 0; i < n / 2; i++) + if (s[i] != s[n - i - 1]) + return check(&s[i], n - 1 - 2 * i); + return 1; +} + +int main() { + char *s1 = "aba", *s2 = "abca", *s3 = "abc"; + printf("%d\n", validPalindrome(s1)); // expect: 1 + printf("%d\n", validPalindrome(s2)); // expect: 1 + printf("%d\n", validPalindrome(s3)); // expect: 0 +} diff --git a/valid_palindrome2.py b/valid_palindrome2.py new file mode 100644 index 0000000..35d7298 --- /dev/null +++ b/valid_palindrome2.py @@ -0,0 +1,28 @@ +# 680. Valid Palindrome II + +""" +given a string 's', return 'true' if the 's' can be palindrome after deleting +at most one charater from it. +""" + + +class Solution(object): + def validPalindrome(self, s): + """ + :type s: str + :rtype: bool + """ + left, right = 0, len(s) - 1 + while left < right: + if s[left] != s[right]: + one, two = s[left:right], s[left + 1 : right + 1] + return one == one[::-1] or two == two[::-1] + left, right = left + 1, right - 1 + return True + + +if __name__ == "__main__": + obj = Solution() + print(obj.validPalindrome("aba")) # expect: True + print(obj.validPalindrome("abca")) # expect: True + print(obj.validPalindrome("abc")) # expect: False diff --git a/valid_parentheses.c b/valid_parentheses.c new file mode 100644 index 0000000..720fef4 --- /dev/null +++ b/valid_parentheses.c @@ -0,0 +1,47 @@ +// 20. Valid Parentheses +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a string 's' containing just the characters '(, ), {, }, [, ]', + * determine if the input string is valid. a input string is valid if open + * brackets must be closed by the same type of brackets. open brackets must be + * closed in the correct order. every close bracket has a corresponding open + * bracket of the same type. + */ + +bool isValid(char *s) { + int len = strlen(s); + if (len % 2) + return false; + int n = len / 2, idx = 0; + char *stack = malloc(n), c, top; + for (int i = 0; i < len; i++) { + c = s[i]; + if (c == '(' || c == '[' || c == '{') { + if (idx == n) + return false; + else + stack[idx++] = c; + } else { + if (!idx) + return false; + top = stack[idx - 1]; + if (top == '(' && c == ')' || top == '[' && c == ']' || + top == '{' && c == '}') + idx--; + else + return false; + } + } + return !idx; +} + +int main() { + char s1[] = {"()"}, s2[] = {"()[]{}"}, s3[] = {"(]"}; + printf("%d\n", isValid(s1)); // expect: 1 + printf("%d\n", isValid(s2)); // expect: 1 + printf("%d\n", isValid(s3)); // expect: 0 +} diff --git a/valid_parentheses.cpp b/valid_parentheses.cpp new file mode 100644 index 0000000..9bab082 --- /dev/null +++ b/valid_parentheses.cpp @@ -0,0 +1,43 @@ +// 20. Valid Parentheses +#include "leetcode.h" + +/* + * given a string 's' containing just the characters '(, ), {, }, [, ]', + * determine if the input string is valid. a input string is valid if open + * brackets must be closed by the same type of brackets. open brackets must be + * closed in the correct order. every close bracket has a corresponding open + * bracket of the same type. + */ + +class Solution { +public: + bool isValid(string s) { + stack<char> stk; + for (int i = 0; i < s.size(); i++) { + char ch = s[i]; + if (ch == '(' || ch == '{' || ch == '[') + stk.push(ch); + else { + if (!stk.empty()) { + char top = stk.top(); + if ((ch == ')' && top == '(') || (ch == '}' && top == '{') || + (ch == ']' && top == '[')) + stk.pop(); + else + return false; + } else + return false; + } + } + if (stk.empty()) + return true; + return false; + } +}; + +int main() { + Solution obj; + printf("%d\n", obj.isValid("()")); // expect: 1 + printf("%d\n", obj.isValid("()[]{}")); // expect: 1 + printf("%d\n", obj.isValid("(]")); // expect: 0 +} diff --git a/valid_parentheses_string.c b/valid_parentheses_string.c new file mode 100644 index 0000000..efd86f0 --- /dev/null +++ b/valid_parentheses_string.c @@ -0,0 +1,42 @@ +// 678. Valid Parenthesis String +#include "leetcode.h" + +/* + * given a string 's' containing only three types of characters, return true if + * 's' is valid. the following rules define a valid string: any left parenthesis + * must have a corresponding right parenthesis. any right parenthesis must have + * a corresponding left parenthesis. left parenthesis must go before the + * corresponding right parenthesis. start could be treated as a single right + * parenthesis, a single left parenthesis, or an empty string. + */ + +bool checkValidString(char *s) { + int n = strlen(s), cnt = 0; + for (int i = 0; i < n; i++) { + if (s[i] == '(' || s[i] == '*') + cnt++; + else { + cnt--; + if (cnt < 0) + return 0; + } + } + cnt = 0; + for (int i = n - 1; i >= 0; i--) { + if (s[i] == ')' || s[i] == '*') + cnt++; + else { + cnt--; + if (cnt < 0) + return 0; + } + } + return 1; +} + +int main() { + char *s1 = "()", *s2 = "(*)", *s3 = "(*))"; + printf("%d\n", checkValidString(s1)); // expect: 1 + printf("%d\n", checkValidString(s2)); // expect: 1 + printf("%d\n", checkValidString(s3)); // expect: 1 +} diff --git a/valid_parentheses_string.py b/valid_parentheses_string.py new file mode 100644 index 0000000..be5ad6c --- /dev/null +++ b/valid_parentheses_string.py @@ -0,0 +1,32 @@ +# 678. Valid Parenthesis String + +""" +given a string 's' containing only three types of characters, return true if +'s' is valid. the following rules define a valid string: any left parenthesis +must have a corresponding right parenthesis. any right parenthesis must have +a corresponding left parenthesis. left parenthesis must go before the +corresponding right parenthesis. start could be treated as a single right +parenthesis, a single left parenthesis, or an empty string. +""" + + +class Solution(object): + def checkValidString(self, s): + """ + :type s: str + :rtype: bool + """ + cmin, cmax = 0, 0 + for i in s: + cmax = cmax - 1 if i == ")" else cmax + 1 + cmin = cmin + 1 if i == "(" else max(cmin - 1, 0) + if cmax < 0: + return False + return cmin == 0 + + +if __name__ == "__main__": + obj = Solution() + print(obj.checkValidString("()")) + print(obj.checkValidString("(*)")) + print(obj.checkValidString("(*))")) diff --git a/valid_stack_seq.c b/valid_stack_seq.c new file mode 100644 index 0000000..5db9b75 --- /dev/null +++ b/valid_stack_seq.c @@ -0,0 +1,42 @@ +// 946. Validate Stack Sequences +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * given two integer arrays 'pushed' & 'popped' each with distinct + * values, return true if this could have been the result of a sequence + * of push and pop operations on an initially empty stack, or false otherwise + */ + +bool validateStackSequences(int *pushed, int pushed_size, int *popped, + int popped_size) { + int i = 0, j = 0, k = 0; + int *s = (int *)malloc(pushed_size * sizeof(int)); + while (k >= 0 && k < pushed_size && j < popped_size) { + if (k > 0 && s[k - 1] == popped[j]) { + k--; + j++; + } else { + if (i < pushed_size) { + if (pushed[i] == popped[j]) { + i++; + j++; + } else + s[k++] = pushed[i++]; + } else { + free(s); + return false; + } + } + } + free(s); + return true; +} + +int main() { + int pushed[] = {1, 2, 3, 4, 5}; + int p1[] = {4, 5, 3, 2, 1}, p2[] = {4, 3, 5, 1, 2}; + printf("%d\n", validateStackSequences(pushed, 5, p1, 5)); // expect: 1 + printf("%d\n", validateStackSequences(pushed, 5, p2, 5)); // expect: 0 +} diff --git a/valid_stack_seq.cpp b/valid_stack_seq.cpp new file mode 100644 index 0000000..62250db --- /dev/null +++ b/valid_stack_seq.cpp @@ -0,0 +1,32 @@ +// 946. Validate Stack Sequences +#include "leetcode.h" + +/* + * given two integer arrays 'pushed' & 'popped' each with distinct + * values, return true if this could have been the result of a sequence + * of push and pop operations on an initially empty stack, or false otherwise + */ + +class Solution { +public: + bool validateStackSequences(vector<int> &pushed, vector<int> &popped) { + stack<int> s; + int i = 0; + for (int x : pushed) { + s.push(x); + while (s.size() && s.top() == popped[i]) { + s.pop(); + i++; + } + } + return !s.size(); + } +}; + +int main() { + Solution obj; + vector<int> pushed = {1, 2, 3, 4, 5}; + vector<int> p1 = {4, 5, 3, 2, 1}, p2 = {4, 3, 5, 1, 2}; + printf("%d\n", obj.validateStackSequences(pushed, p1)); // expect: 1 + printf("%d\n", obj.validateStackSequences(pushed, p2)); // expect: 0 +} diff --git a/valid_sudoku.cpp b/valid_sudoku.cpp new file mode 100644 index 0000000..0843d67 --- /dev/null +++ b/valid_sudoku.cpp @@ -0,0 +1,38 @@ +#include "leetcode.h" +#include <vector> + +class Solution { +public: + bool isValidSudoku(vvd(char) & board) { + vector<set<char>> rows(9), cols(9), blck(9); + for (int i = 0; i < 9; i++) + for (int j = 0; j < 9; j++) + if (board[i][j] != '.') { + int m = board[i][j], n = (i / 3) * 3 + j / 3; + if (!rows[i].emplace(m).second) // rows + return false; + if (!cols[j].emplace(m).second) // columns + return false; + if (!blck[n].emplace(m).second) // blocks + return false; + } + return true; + } +}; + +int main() { + Solution obj; + vvd(char) board = {{'8', '3', '.', '.', '7', '.', '.', '.', '.'}, + {'6', '.', '.', '1', '9', '5', '.', '.', '.'}, + {'.', '9', '8', '.', '.', '.', '.', '6', '.'}, + {'8', '.', '.', '.', '6', '.', '.', '.', '3'}, + {'4', '.', '.', '8', '.', '3', '.', '.', '1'}, + {'7', '.', '.', '.', '2', '.', '.', '.', '6'}, + {'.', '6', '.', '.', '.', '.', '2', '8', '.'}, + {'.', '.', '.', '4', '1', '9', '.', '.', '5'}, + {'.', '.', '.', '.', '8', '.', '.', '7', '9'}}; + if (obj.isValidSudoku(board)) + cout << "true"; + else + cout << "false"; +} diff --git a/valid_sudoku.rs b/valid_sudoku.rs new file mode 100644 index 0000000..3c2f591 --- /dev/null +++ b/valid_sudoku.rs @@ -0,0 +1,27 @@ +struct Solution; + +impl Solution { + pub fn is_valid_sudoku(board: Vec<Vec<char>>) -> bool { + let mut rows: [u16; 9] = [0; 9]; + let mut cols: [u16; 9] = [0; 9]; + let mut blck: [u16; 9] = [0; 9]; + for i in 0..9 { + for j in 0..9 { + match board[i][j] { + '.' => continue, + c => { + let b: usize = (i / 3) * 3 + (j / 3); + let curr = 1 << (c.to_digit(10).unwrap()); + if rows[i] & curr != 0 || cols[j] & curr != 0 || blck[b] & curr != 0 { + return false; + } + rows[i] |= curr; + cols[j] |= curr; + blck[b] |= curr; + } + } + } + } + true + } +} diff --git a/validate_bst.cpp b/validate_bst.cpp new file mode 100644 index 0000000..0785d47 --- /dev/null +++ b/validate_bst.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + bool isValidBST(TreeNode *root) { + if (!root) + return true; + inOrder(root); + for (int i = 1; i < tree.size(); i++) + if (tree[i] <= tree[i - 1]) + return false; + return true; + } + +private: + vector<int> tree; + void inOrder(TreeNode *root) { + if (!root) + return; + inOrder(root->left); + tree.push_back(root->val); + inOrder(root->right); + } +}; diff --git a/validate_bst_node.c b/validate_bst_node.c new file mode 100644 index 0000000..160b33f --- /dev/null +++ b/validate_bst_node.c @@ -0,0 +1,77 @@ +// 1361. Validate Binary Tree Nodes +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + +/* + * you have n binary trees nodes numbered from 0 to n - 1 where node i has two + * children left_child and right_child. return true if any only if all the given + * nodes from exactly one valid binary tree. if node i has no left children, + * then left_child[i] will equal -1. note that the nodes have no values and that + * we only use the node numbers in this problem. + */ + +bool validateBinaryTreeNodes(int n, int *left_child, int left_child_size, + int *right_child, int right_child_size) { + bool *flag = calloc(n, sizeof(bool)); + for (int i = 0; i < n; i++) { + if (left_child[i] == -1) + continue; + flag[left_child[i]] = true; + } + for (int i = 0; i < n; i++) { + if (right_child[i] == -1) + continue; + flag[right_child[i]] = true; + } + int root = -1; + for (int i = 0; i < n; i++) { + if (!flag[i]) { + if (root == -1) + root = i; + else + return false; + } + } + if (root == -1) + return false; + bool *visited = calloc(n, sizeof(bool)); + int *stack = malloc(2 * n * sizeof(int)); + int count = 0; + stack[count] = root; + count++; + int p = 0, node = 0; + + while (p < count) { + node++; + int left = left_child[stack[p]]; + int right = right_child[stack[p]]; + visited[stack[p]] = true; + p++; + if (left != -1) { + if (visited[left] == true) + return false; + stack[count] = left; + count++; + } + if (right != -1) { + if (visited[right] == true) + return false; + stack[count] = right; + count++; + } + } + free(flag), free(visited); + if (node == n) + return true; + return false; +} + +int main() { + int lc1[] = {1, -1, 3, -1}, rc1[] = {2, -1, -1, -1}; + int lc2[] = {1, -1, 3, -1}, rc2[] = {2, 3, -1, -1}; + int lc3[] = {1, 0}, rc3[] = {-1, -1}; + printf("%d\n", validateBinaryTreeNodes(4, lc1, 4, rc1, 4)); // expect: 1 + printf("%d\n", validateBinaryTreeNodes(4, lc2, 4, rc2, 4)); // expect: 0 + printf("%d\n", validateBinaryTreeNodes(2, lc3, 2, rc3, 2)); // expect: 0 +} diff --git a/validate_bst_node.py b/validate_bst_node.py new file mode 100644 index 0000000..6312f7a --- /dev/null +++ b/validate_bst_node.py @@ -0,0 +1,62 @@ +# 1361. Validate Binary Tree Nodes +from collections import defaultdict + +""" +you have n binary trees nodes numbered from 0 to n - 1 where node i has two +children left_child and right_child. return true if any only if all the given +nodes from exactly one valid binary tree. if node i has no left children, +then left_child[i] will equal -1. note that the nodes have no values and that +we only use the node numbers in this problem. +""" + + +class Solution: + def validateBinaryTreeNodes(self, n, left_child, right_child): + graph = defaultdict(list) + in_degree = [0] * n + + for node in range(n): + left, right = left_child[node], right_child[node] + if left != -1: + graph[node].append(left) + in_degree[left] += 1 + if right != -1: + graph[node].append(right) + in_degree[right] += 1 + + root_candidates = [node for node in range(n) if in_degree[node] == 0] + + if len(root_candidates) != 1: + return False + root = root_candidates[0] + + queue = [root] + seen = set([root]) + + while queue: + node = queue.pop(0) + if node in graph: + for child in graph[node]: + if child in seen: + return False + seen.add(child) + queue.append(child) + + return len(seen) == n + + +if __name__ == "__main__": + obj = Solution() + print( + obj.validateBinaryTreeNodes( + n=4, left_child=[1, -1, 3, -1], right_child=[2, -1, -1, -1] + ) + ) # expect: True + print( + obj.validateBinaryTreeNodes( + n=4, left_child=[1, -1, 3, -1], right_child=[2, 3, -1, -1] + ) + ) # expect: False + print( + obj.validateBinaryTreeNodes(n=2, left_child=[1, 0], right_child=[-1, -1]) + ) # expect: True diff --git a/verify_alien_dict.c b/verify_alien_dict.c new file mode 100644 index 0000000..c0fe1f0 --- /dev/null +++ b/verify_alien_dict.c @@ -0,0 +1,34 @@ +// 953. Verifying an Alien Dictionary +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * in an alien language, they also use english lowercase letters but in + * different 'order'. the 'order' of the alphabet is some permutation of + * lowercase letters. given a sequence of 'words' written in the alien language, + * and the 'order' of the alphabet, return 1 if and only if the given 'words' + * are sorted lexicographically in this alien language. + */ + +bool cmp(char *a, char *b, int *j) { + int sizeA = strlen(a), sizeB = strlen(b); + for (int i = 0; i < sizeA && i < sizeB; i++) { + if (j[a[i] - 'a'] < j[b[i] - 'a']) + return true; + else if (j[a[i] - 'a'] > j[b[i] - 'a']) + return false; + } + return sizeA < sizeB; +} + +bool isAlienSorted(char **words, int wordsSize, char *order) { + int j[26] = {0}; + for (int i = 0; i < 26; i++) + j[order[i] - 'a'] = i; + for (int i = 0; i < wordsSize - 1; i++) + if (!cmp(words[i], words[i + 1], j)) + return false; + return true; +} diff --git a/verify_alien_dict.cpp b/verify_alien_dict.cpp new file mode 100644 index 0000000..009ac52 --- /dev/null +++ b/verify_alien_dict.cpp @@ -0,0 +1,42 @@ +// 953. Verifying an Alien Dictionary +#include "leetcode.h" + +/* + * in an alien language, they also use english lowercase letters but in + * different 'order'. the 'order' of the alphabet is some permutation of + * lowercase letters. given a sequence of 'words' written in the alien language, + * and the 'order' of the alphabet, return 1 if and only if the given 'words' + * are sorted lexicographically in this alien language. + */ + +class Solution { +public: + bool isAlienSorted(vector<string> &words, string order) { + size_t indices[26]{}; + for (size_t i = 0; i < order.size(); ++i) + indices[order[i] - 'a'] = i; + return is_sorted(words.begin(), words.end(), + [&indices](const string &w1, const string &w2) { + auto l1 = w1.size(), l2 = w2.size(); + for (auto i = 0; i < min(l1, l2); ++i) { + auto c1 = w1[i], c2 = w2[i]; + if (c1 != c2) + return indices[c1 - 'a'] < indices[c2 - 'a']; + } + return l1 < l2; + }); + } +}; + +int main() { + Solution obj; + vector<string> words1 = {"hello", "leetcode"}; + vector<string> words2 = {"word", "world", "row"}; + vector<string> words3 = {"apple", "app"}; + cout << obj.isAlienSorted(words1, "hlabcdefgijkmnopqrstuvwxyz") + << endl; // expect: 1 + cout << obj.isAlienSorted(words2, "worldabcefghijkmnpqstuvxyz") + << endl; // expect: 0 + cout << obj.isAlienSorted(words3, "abcdefghijklmnopqrstuvwxyz") + << endl; // expect: 0 +} diff --git a/vertical_order_bst.cpp b/vertical_order_bst.cpp new file mode 100644 index 0000000..e8bf5bf --- /dev/null +++ b/vertical_order_bst.cpp @@ -0,0 +1,29 @@ +#include "leetcode.h" + +class Solution { +public: + vvd(int) verticalTraversal(TreeNode *root) { + map<int, map<int, multiset<int>>> mmm; + queue<pair<TreeNode *, pair<int, int>>> qpp; + qpp.push({root, {0, 0}}); + while (!qpp.empty()) { + auto p = qpp.front(); + qpp.pop(); + TreeNode *node = p.first; + int x = p.second.first, y = p.second.second; + mmm[x][y].insert(node->val); + if (node->left) + qpp.push({node->left, {x - 1, y + 1}}); + if (node->right) + qpp.push({node->right, {x + 1, y + 1}}); + } + vvd(int) ans; + for (auto q : mmm) { + vector<int> col; + for (auto p : q.second) + col.insert(col.end(), p.second.begin(), p.second.end()); + ans.push_back(col); + } + return ans; + } +}; diff --git a/vowels_substrings.c b/vowels_substrings.c new file mode 100644 index 0000000..ead6293 --- /dev/null +++ b/vowels_substrings.c @@ -0,0 +1,28 @@ +// 2063. Vowels of All Substrings +#include <stdio.h> +#include <string.h> + +/* + * given a string 'word, return thesum of the number of vowels (a, e, i, o, u) + * in every substring of 'word'. a substringis a contiguous (non-empty) sequence + * of characters within a string. note, due to the large constraints, the answer + * may not fit in a signed 32-bit integer. please be careful during + * calculates... + */ + +long long countVowels(char *word) { + long long ans = 0; + int n = strlen(word); + for (int i = 0; i < n; i++) + if (word[i] == 'a' || word[i] == 'e' || word[i] == 'i' || word[i] == 'o' || + word[i] == 'u') + ans += (long long)(i + 1) * (n - i); + return ans; +} + +int main() { + char w1[] = {"aba"}, w2[] = {"abc"}, w3[] = {"ltcd"}; + printf("%lld\n", countVowels(w1)); // expect: 6 + printf("%lld\n", countVowels(w2)); // expect: 3 + printf("%lld\n", countVowels(w3)); // expect: 0 +} diff --git a/vowels_substrings.py b/vowels_substrings.py new file mode 100644 index 0000000..0993983 --- /dev/null +++ b/vowels_substrings.py @@ -0,0 +1,26 @@ +# 2063. Vowels of All Substrings + +""" +given a string 'word, return thesum of the number of vowels (a, e, i, o, u) +in every substring of 'word'. a substringis a contiguous (non-empty) sequence +of characters within a string. note, due to the large constraints, the answer +may not fit in a signed 32-bit integer. please be careful during +calculates... +""" + + +class Solution(object): + def countVowels(self, word): + ans, n = 0, len(word) + d = {"a": 1, "e": 1, "i": 1, "o": 1, "u": 1} + for i in range(n): + if word[i] in d: + ans += (n - i) * (i + 1) + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.countVowels("aba")) # expect: 6 + print(obj.countVowels("abc")) # expect: 3 + print(obj.countVowels("ltcd")) # expect: 0 diff --git a/ways_make_fair_array.c b/ways_make_fair_array.c new file mode 100644 index 0000000..a4acd64 --- /dev/null +++ b/ways_make_fair_array.c @@ -0,0 +1,35 @@ +// 1664. Ways to Make a Fair Array +#include "leetcode.h" + +/* + * you are given an integer array 'nums'. you can choose exactly one index and + * remove the element. notice that the index of the elements may change after + * the removal. for example, if 'nums = [6,1,7,4,1]' choosing to remove index 1 + * results in 'nums = [6,7,4,1]'. an array is fair is the sum of the odd indexed + * values equals the sume of the even indexed values. return the number of + * indices that you could choose such that after the removal, 'nums' is fair. + */ + +int waysToMakeFair(int *nums, int nums_size) { + int n = nums_size, ans = 0; + int *pre_sum = (int *)malloc((n + 4) * sizeof(int)); + int *suf_sum = (int *)malloc((n + 4) * sizeof(int)); + pre_sum[0] = 0, pre_sum[1] = 0, pre_sum[n + 2] = 0, pre_sum[n + 3] = 0; + suf_sum[0] = 0, suf_sum[1] = 0, suf_sum[n + 2] = 0, suf_sum[n + 3] = 0; + for (int i = 2; i < n + 2; i++) + pre_sum[i] = pre_sum[i - 2] + nums[i - 2]; + for (int i = n + 1; i > 1; i--) + suf_sum[i] = suf_sum[i + 2] + nums[i - 2]; + for (int i = 2; i <= n + 1; i++) + if (pre_sum[i - 2] + suf_sum[i + 1] == pre_sum[i - 1] + suf_sum[i + 2]) + ans++; + free(pre_sum), free(suf_sum); + return ans; +} + +int main() { + int n1[] = {2, 1, 6, 4}, n2[] = {1, 1, 1}, n3[] = {1, 2, 3}; + printf("%d\n", waysToMakeFair(n1, ARRAY_SIZE(n1))); // expect: 1 + printf("%d\n", waysToMakeFair(n2, ARRAY_SIZE(n2))); // expect: 3 + printf("%d\n", waysToMakeFair(n3, ARRAY_SIZE(n3))); // expect: 0 +} diff --git a/ways_make_fair_array.py b/ways_make_fair_array.py new file mode 100644 index 0000000..e6fa972 --- /dev/null +++ b/ways_make_fair_array.py @@ -0,0 +1,32 @@ +# 1664. Ways to Make a Fair Array + +""" +you are given an integer array 'nums'. you can choose exactly one index and +remove the element. notice that the index of the elements may change after +the removal. for example, if 'nums = [6,1,7,4,1]' choosing to remove index 1 +results in 'nums = [6,7,4,1]'. an array is fair is the sum of the odd indexed +values equals the sume of the even indexed values. return the number of +indices that you could choose such that after the removal, 'nums' is fair. +""" + + +class Solution(object): + def waysToMakeFair(self, nums): + """ + :type nums: List[int] + :rtype: int + """ + s1, s2 = [0, 0], [sum(nums[0::2]), sum(nums[1::2])] + ans = 0 + for i, j in enumerate(nums): + s2[i % 2] -= j + ans += s1[0] + s2[1] == s1[1] + s2[0] + s1[i % 2] += j + return ans + + +if __name__ == "__main__": + obj = Solution() + print(obj.waysToMakeFair(nums=[2, 1, 6, 4])) + print(obj.waysToMakeFair(nums=[1, 1, 1])) + print(obj.waysToMakeFair(nums=[1, 2, 3])) diff --git a/ways_to_paint_nx3_grid.cpp b/ways_to_paint_nx3_grid.cpp new file mode 100644 index 0000000..b661af8 --- /dev/null +++ b/ways_to_paint_nx3_grid.cpp @@ -0,0 +1,20 @@ +#include "leetcode.h" + +class Solution { +public: + int numOfWays(int n) { + long a = 6, b = 6, c, d, mod = 1e9 + 7; + for (int i = 1; i < n; ++i) { + c = a * 3 + b * 2; + d = a * 2 + b * 2; + a = c % mod; + b = d % mod; + } + return (a + b) % mod; + } +}; + +int main() { + Solution obj; + cout << obj.numOfWays(1); +} diff --git a/where_will_ball_fall.cpp b/where_will_ball_fall.cpp new file mode 100644 index 0000000..ee859b7 --- /dev/null +++ b/where_will_ball_fall.cpp @@ -0,0 +1,50 @@ +#include "leetcode.h" + +class Solution { +public: + vector<int> findBall(vvd(int) & grid) { + int m = grid.size(), n = grid[0].size(); + vvd(int) ugrid(m * 3, vector<int>(n * 3)); + for (auto i = 0; i < m; i++) + for (auto j = 0; j < n; j++) { + ugrid[i * 3 + 1][j * 3 + 1] = 1; + ugrid[i * 3][j * 3] = ugrid[i * 3 + 2][j * 3 + 2] = grid[i][j] == 1; + ugrid[i * 3][j * 3 + 2] = ugrid[i * 3 + 2][j * 3] = grid[i][j] != 1; + } + vector<int> ans; + for (auto i = 0; i < n; ++i) + ans.push_back(drop(i * 3 + 1, ugrid, m * 3, n * 3)); + return ans; + } + +private: + vector<pair<int, int>> dir{{1, 0}, {0, -1}, {0, 1}}; + int drop(int pos, vvd(int) & ugrid, int m, int n) { + queue<pair<int, int>> qp; + qp.push({0, pos}); + while (!qp.empty()) { + auto [i, j] = qp.front(); + qp.pop(); + if (i == m - 1) + return j / 3; + ugrid[i][j] = 1; + for (auto [di, dj] : dir) + if (j + dj >= 0 && j + dj < n && !ugrid[i + di][j + dj]) { + qp.push({i + di, j + dj}); + break; + } + } + return -1; + } +}; + +int main() { + Solution obj; + vvd(int) grid = {{1, 1, 1, -1, -1}, + {1, 1, 1, -1, -1}, + {-1, -1, -1, 1, 1}, + {1, 1, 1, 1, -1}, + {-1, -1, -1, -1, -1}}; + for (auto i : obj.findBall(grid)) + cout << i << ' '; +} diff --git a/where_will_ball_fall.rs b/where_will_ball_fall.rs new file mode 100644 index 0000000..6a1bb58 --- /dev/null +++ b/where_will_ball_fall.rs @@ -0,0 +1,38 @@ +struct Solution; + +impl Solution { + pub fn find_ball(grid: Vec<Vec<i32>>) -> Vec<i32> { + let n = grid[0].len(); + if n == 1 { + return vec![-1]; + } + (0..n).map(|i| {Self::exits(&grid, 0, i)}).collect() + } + fn exits(grid: &Vec<Vec<i32>>, row: usize, i: usize) -> i32 { + let (m, n) = (grid.len(), grid[0].len()); + if i == usize::MAX ||i >= n { + return -1; + } + let i2 = i + grid[row][i] as usize; + if i2 >= n || i2 == usize::MAX { + return -1; + } + let (dir1, dir2) = (grid[row][i], grid[row][i2]); + if dir1 != dir2 { + return -1; + } + if row == m - 1 { + return i2 as i32; + } + Self::exits(&grid, row + 1, i2) + } +} + +fn main() { + let grid = vec![vec![1,1,1,-1,-1], + vec![1,1,1,-1,-1], + vec![-1,-1,-1,1,1], + vec![1,1,1,1,-1], + vec![-1,-1,-1,-1,-1]]; + print!("{:?}", Solution::find_ball(grid)); +} diff --git a/widest_vert_two_point.c b/widest_vert_two_point.c new file mode 100644 index 0000000..8f5929e --- /dev/null +++ b/widest_vert_two_point.c @@ -0,0 +1,36 @@ +// 1637. Widest Vertical Area Between Two Points Containing No Points +#include "leetcode.h" + +/* + * given 'n' points on a 2d plane where 'points [i] = [x[i], y[i]]', return the + * widest veritcal area between two points such that no points are inside the + * area. a vertical area is an area of fixed width extending infinitely along + * the y-axis. the widest vertical area is the one with the maximum width. note + * that the points on the edge of a vertical area are not considred included in + * the area. + */ + +int cmp(const void **a, const void **b) { + int **pa = (const int **)a; + int **pb = (const int **)b; + return pa[0][0] - pb[0][0]; +} + +// int maxWidthOfVerticalArea(int **points, int points_size, +// int *points_col_size) { +int maxWidthOfVerticalArea(int r, int c, int points[r][c], int points_size) { + qsort(points, points_size, sizeof(int **), cmp); + int area = 0; + for (int i = 0; i + 1 < points_size; i++) + area = points[i + 1][0] - points[i][0] > area + ? points[i + 1][0] - points[i][0] + : area; + return area; +} + +int main() { + int p1[4][2] = {{8, 7}, {9, 9}, {7, 4}, {9, 7}}, + p2[6][2] = {{3, 1}, {9, 0}, {1, 0}, {1, 4}, {5, 3}, {8, 3}}; + printf("%d\n", maxWidthOfVerticalArea(4, 2, p1, 4)); // expect: 1 + printf("%d\n", maxWidthOfVerticalArea(6, 2, p2, 6)); // expect: 3 +} diff --git a/widest_vert_two_point.py b/widest_vert_two_point.py new file mode 100644 index 0000000..36c19de --- /dev/null +++ b/widest_vert_two_point.py @@ -0,0 +1,32 @@ +# 1637. Widest Vertical Area Between Two Points Containing No Points + +""" +given 'n' points on a 2d plane where 'points [i] = [x[i], y[i]]', return the +widest veritcal area between two points such that no points are inside the +area. a vertical area is an area of fixed width extending infinitely along +the y-axis. the widest vertical area is the one with the maximum width. note +that the points on the edge of a vertical area are not considred included in +the area. +""" + + +class Solution(object): + def maxWidthOfVerticalArea(self, points): + """ + :type points: List[List[int]] + :rtype: int + """ + area = sorted({x for x, y in points}) + return max([b - a for a, b in zip(area, area[1:])] + [0]) + + +if __name__ == "__main__": + obj = Solution() + print( + obj.maxWidthOfVerticalArea(points=[[8, 7], [9, 9], [7, 4], [9, 7]]) + ) # expect: 1 + print( + obj.maxWidthOfVerticalArea( + points=[[3, 1], [9, 0], [1, 0], [1, 4], [5, 3], [8, 8]] + ) + ) # expect: 3 diff --git a/wiggle_subsequence.cpp b/wiggle_subsequence.cpp new file mode 100644 index 0000000..22376d4 --- /dev/null +++ b/wiggle_subsequence.cpp @@ -0,0 +1,23 @@ +#include "leetcode.h" + +class Solution { +public: + int wiggleMaxLength(vector<int> &nums) { + int ans = 1, i = 1; + while (i < nums.size() && nums[i] == nums[i - 1]) + i++; + if (i == nums.size()) + return 1; + bool upper = nums[i - 1] > nums[i]; + for (; i < nums.size(); i++) + if ((upper && nums[i] < nums[i - 1]) || !upper && nums[i] > nums[i - 1]) + upper = !upper, ans++; + return ans; + } +}; + +int main() { + Solution obj; + vector<int> nums = {1, 17, 5, 10, 13, 15, 10, 5, 16, 8}; + cout << obj.wiggleMaxLength(nums); +} diff --git a/wildcard_matching.cpp b/wildcard_matching.cpp new file mode 100644 index 0000000..23a6538 --- /dev/null +++ b/wildcard_matching.cpp @@ -0,0 +1,24 @@ +#include "leetcode.h" + +class Solution { +public: + bool isMatch(string s, string p) { + int m = s.length(), n = p.length(); + int i = 0, j = 0, astr = -1, match; + while (i < m) { + if (j < n && p[j] == '*') + match = i, astr = j++; + else if (j < n && (s[i] == p[j] || p[j] == '?')) + i++, j++; + else if (astr >= 0) + i = ++match, j = astr + 1; + else + return false; + } + while (j < n && p[j] == '*') + j++; + return j == n; + } +}; + +int main() {} diff --git a/word_break.c b/word_break.c new file mode 100644 index 0000000..46c76cc --- /dev/null +++ b/word_break.c @@ -0,0 +1,68 @@ +// 139. Word Break +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * given a string 's' and a dictionary of strings 'word_dict', return 'true' if + * 's' can be segmented into a space-separated sequence of one or more + * dictionary words. note that the same word in the dictionary may be reused + * multiple times in the segmentation. + */ + +bool process(char *s, char **word_dict, int word_dict_size, int *word_dict_len, + int len) { + bool res = false; + if (!len) + return true; + for (int i = 0; i < word_dict_size; i++) + if (!strncmp(s, word_dict[i], word_dict_len[i])) + if (process(&s[word_dict_len[i]], word_dict, word_dict_size, + word_dict_len, len - word_dict_len[i])) { + res = true; + break; + } + return res; +} + +static int string_compare(const void *p1, const void *p2) { + return strlen(*(char **)p1) - strlen(*(char **)p2); +} + +bool wordBreak(char *s, char **word_dict, int word_dict_size) { + int i, j, n = strlen(s); + bool *flag = (bool *)calloc(n + 1, sizeof(bool)); + qsort(word_dict, word_dict_size, sizeof(char *), string_compare); + int *word_dict_len = (int *)malloc(word_dict_size * sizeof(int)); + for (i = 0; i < word_dict_size; i++) + word_dict_len[i] = strlen(word_dict[i]); + int size, begin; + flag[0] = true; + for (i = 1; i <= n; i++) { + for (j = 0; j < word_dict_size; j++) { + if (word_dict_len[j] > i) + break; + else { + begin = i - word_dict_len[j]; + if (!strncmp(word_dict[j], &s[begin], word_dict_len[j])) + if (flag[begin]) { + flag[i] = true; + break; + } + } + } + } + bool ans = flag[n]; + free(flag), free(word_dict_len); + return ans; +} + +int main() { + char s1[] = {"leetcode"}, s2[] = {"applepenapple"}, s3[] = {"catsanddog"}; + char wd1[2][4] = {{"leet"}, {"code"}}, wd2[2][5] = {{"apple"}, {"pen"}}, + wd3[5][4] = {{"cats"}, {"dog"}, {"sand"}, {"and"}, {"cat"}}; + printf("%d\n", wordBreak(s1, wd1, 2)); // expect: 1 + printf("%d\n", wordBreak(s2, wd2, 2)); // expect: 1 + printf("%d\n", wordBreak(s3, wd3, 5)); // expect: 0 +} diff --git a/word_break.cpp b/word_break.cpp new file mode 100644 index 0000000..aa580c9 --- /dev/null +++ b/word_break.cpp @@ -0,0 +1,38 @@ +// 139. Word Break +#include "leetcode.h" + +/* + * given a string 's' and a dictionary of strings 'word_dict', return 'true' if + * 's' can be segmented into a space-separated sequence of one or more + * dictionary words. note that the same word in the dictionary may be reused + * multiple times in the segmentation. + */ + +class Solution { +public: + bool wordBreak(string s, unordered_set<string> &word_dict) { + if (!word_dict.size()) + return false; + vector<bool> dp(s.size() + 1, false); + dp[0] = true; + for (int i = 1; i <= s.size(); i++) + for (int j = i - 1; j >= 0; j--) + if (dp[j]) { + string word = s.substr(j, i - j); + if (word_dict.find(word) != word_dict.end()) { + dp[i] = true; + break; + } + } + return dp[s.size()]; + } +}; + +int main() { + Solution obj; + unordered_set<string> wd1 = {"leet", "code"}, wd2 = {"apple", "pen"}, + wd3 = {"cats", "dog", "sand", "and", "cat"}; + printf("%d\n", obj.wordBreak("leetcode", wd1)); // expect: 1 + printf("%d\n", obj.wordBreak("applepenapple", wd2)); // expect: 1 + printf("%d\n", obj.wordBreak("catsandog", wd3)); // expect: 0 +} diff --git a/word_break2.c b/word_break2.c new file mode 100644 index 0000000..41dcfd8 --- /dev/null +++ b/word_break2.c @@ -0,0 +1,64 @@ +// 140. Word Break II +#include "leetcode.h" + +/* + * given a string 's' and a dictionary of strings 'wordDict', add spaces in 's' + * to construct a sentence where each word is a valid dictionary word. return + * all such possible sentences in any order. note that the same word in the + * dictionary may be reused mutliple times in the segmentation. + */ + +void dfs(char *s, char **dict, int dict_size, char **res, int *return_size, + int *idx, int map_size, int len) { + if (*s == '\0') { + res[*return_size] = (char *)malloc(len * sizeof(char)); + char *head = res[*return_size]; + for (int i = 0; i < map_size; ++i) { + int n = strlen(dict[idx[i]]); + strcpy(head, dict[idx[i]]); + head[n] = ' '; + head += len++; + } + res[*return_size][len - 1] = '\0'; + ++(*return_size); + return; + } + for (int i = 0; i < dict_size; ++i) { + int n = strlen(dict[i]); + if (!strncmp(s, dict[i], n)) { + idx[map_size] = i; + dfs(s + n, dict, dict_size, res, return_size, idx, map_size + 1, + len + n + 1); + } + } +} + +char **wordBreak(char *s, char **wordDict, int wordDictSize, int *returnSize) { + char **ans = (char **)malloc(500 * sizeof(char *)); + int *idx = (int *)malloc(500 * sizeof(int)); + *returnSize = 0; + dfs(s, wordDict, wordDictSize, ans, returnSize, idx, 0, 0); + free(idx); + return ans; +} + +int main() { + char *s1 = "catsanddog", *s2 = "pineapplepenapple", *s3 = "catsandog"; + char *wd1[] = {"cat", "cats", "and", "sand", "dog"}, + *wd2[] = {"apple", "pen", "applepen", "pine", "pineapple"}, + *wd3[] = {"cats", "dog", "sand", "and", "cat"}; + int rs1, rs2, rs3; + char **wb1 = wordBreak(s1, (char **)wd1, ARRAY_SIZE(wd1), &rs1); + char **wb2 = wordBreak(s2, (char **)wd2, ARRAY_SIZE(wd2), &rs2); + char **wb3 = wordBreak(s3, (char **)wd3, ARRAY_SIZE(wd3), &rs3); + for (int i = 0; i < rs1; i++) + printf("%s ", wb1[i]); // expect: "cats and dog","cat sand dog" + printf("\n"); + for (int i = 0; i < rs2; i++) + printf("%s ", wb2[i]); // "pine apple pen apple","pineapple pen apple","pine + // applepen apple" + printf("\n"); + for (int i = 0; i < rs3; i++) + printf("%s ", wb3[i]); // expect: null + printf("\n"); +} diff --git a/word_break2.py b/word_break2.py new file mode 100644 index 0000000..7c741c8 --- /dev/null +++ b/word_break2.py @@ -0,0 +1,49 @@ +# 140. Word Break II + +""" +given a string 's' and a dictionary of strings 'wordDict', add spaces in 's' +to construct a sentence where each word is a valid dictionary word. return +all such possible sentences in any order. note that the same word in the +dictionary may be reused mutliple times in the segmentation. +""" + + +class Solution(object): + def dfs(self, s, wordDict, memo): + if s in memo: + return memo[s] + if not s: + return [] + res = [] + for word in wordDict: + if not s.startswith(word): + continue + if len(word) == len(s): + res.append(word) + else: + res_rest = self.dfs(s[len(word) :], wordDict, memo) + for item in res_rest: + item = word + " " + item + res.append(item) + memo[s] = res + return res + + def wordBreak(self, s, wordDict): + """ + :type s: str + :type wordDict: List[str] + :rtype: List[str] + """ + return self.dfs(s, wordDict, {}) + + +if __name__ == "__main__": + obj = Solution() + print(obj.wordBreak(s="catsanddog", wordDict=["cat", "cats", "and", "sand", "dog"])) + print( + obj.wordBreak( + s="pineapplepenapple", + wordDict=["apple", "pen", "applepen", "pine", "pineapple"], + ) + ) + print(obj.wordBreak(s="catsandog", wordDict=["cats", "dog", "sand", "and", "cat"])) diff --git a/word_ladder.cpp b/word_ladder.cpp new file mode 100644 index 0000000..dfe6b00 --- /dev/null +++ b/word_ladder.cpp @@ -0,0 +1,39 @@ +#include "leetcode.h" + +class Solution { +public: + int ladderLength(string beginWord, string endWord, vector<string> &wordList) { + unordered_set<string> dict(wordList.begin(), wordList.end()); + queue<string> q; + q.push(beginWord); + int ladder = 1; + while (!q.empty()) { + int n = q.size(); // + for (int i = 0; i < n; i++) { + string word = q.front(); + q.pop(); + if (word == endWord) + return ladder; + dict.erase(word); + for (int j = 0; j < word.size(); j++) { + char c = word[j]; + for (int k = 0; k < 26; k++) { + word[j] = 'a' + k; + if (dict.find(word) != dict.end()) + q.push(word); + } + word[j] = c; + } + } + ladder++; + } + return 0; + } +}; + +int main() { + Solution obj; + string beginWord = "hit", endWord = "cog"; + vector<string> wordList = {"hot", "dot", "dog", "lot", "log", "cog"}; + cout << obj.ladderLength(beginWord, endWord, wordList); +} diff --git a/word_ladder2.cpp b/word_ladder2.cpp new file mode 100644 index 0000000..7473ad2 --- /dev/null +++ b/word_ladder2.cpp @@ -0,0 +1,47 @@ +#include "leetcode.h" + +class Solution { +public: + vector<vector<string>> findLadders(string beginWord, string endWord, + vector<string> &wordList) { + unordered_map<string, int> um; + vector<vector<string>> ans; + for (const auto w : wordList) + um.insert({w, INT_MAX}); + um[beginWord] = 0; + queue<pair<string, vector<string>>> qpv; + qpv.push({beginWord, {beginWord}}); + while (!qpv.empty()) { + auto n = qpv.front(); + qpv.pop(); + string w = n.first; + auto v = n.second; + if (w == endWord) + ans.push_back(v); + continue; + for (int i = 0; i < w.size(); i++) { + string t = w; + for (char c = 'a'; c <= 'z'; c++) { + t[i] = c; + if (t == w) + continue; + if (um.find(t) == um.end()) + continue; + if (um[t] < (int)v.size()) + continue; + um[t] = (int)v.size(); + v.push_back(t); + qpv.push({t, v}); + v.pop_back(); + } + } + } + return ans; + } +}; + +int main() { + Solution obj; + string beginWord = "hit", endWord = "cog"; + vector<string> wordList = {"hot", "dot", "dog", "lot", "log", "cog"}; +} diff --git a/word_pattern.cpp b/word_pattern.cpp new file mode 100644 index 0000000..26ccbfd --- /dev/null +++ b/word_pattern.cpp @@ -0,0 +1,25 @@ +#include "leetcode.h" + +class Solution { +public: + bool wordPattern(string pattern, string s) { + vector<int> patMap(26, 0); + unordered_map<string, int> strMap; + int i = 0, n = pattern.size(); + istringstream ss(s); + string token; + for (string token; ss >> token; ++i) { + if (i == n || patMap[pattern[i] - 'a'] != strMap[token]) + return false; + patMap[pattern[i] - 'a'] = strMap[token] = i + 1; + } + return i == n; + } +}; + +int main() { + Solution obj; + testBool(obj.wordPattern("abba", "dog cat cat dog")); // true + testBool(obj.wordPattern("abba", "dog cat cat fish")); // false + testBool(obj.wordPattern("aaaa", "dog cat cat dog")); // false +} diff --git a/word_pattern.rs b/word_pattern.rs new file mode 100644 index 0000000..6161b40 --- /dev/null +++ b/word_pattern.rs @@ -0,0 +1,26 @@ +struct Solution; + +impl Solution { + pub fn word_pattern(pattern: String, s: String) -> bool { + use std::collections::{HashMap, HashSet}; + if pattern.len() != s.matches(' ').count() + 1 { + return false; + } + let (mut hm, mut word_set) = (HashMap::new(), HashSet::new()); + for (word, c) in s.split_ascii_whitespace().zip(pattern.chars()) { + if let Some(w) = hm.insert(c, word) { + if w != word { + return false; + } + } else if !word_set.insert(word) { + return false; + } + } + true + } +} + +fn main() { + let (pattern, s) = (String::from("abba"), String::from("dog cat cat dog")); + print!("{}", Solution::word_pattern(pattern, s)); +} diff --git a/word_search.c b/word_search.c new file mode 100644 index 0000000..dceb401 --- /dev/null +++ b/word_search.c @@ -0,0 +1,34 @@ +// 79. Word Search +#include "leetcode.h" + +/* + * given an 'm * n' grid of characters 'board' and a string 'word', return 1 if + * the word exists in the grid. the word can be constructed from letters of + * sequentially adjacent cells, where adjacent cells are horizontally or + * vertically neighbouring the same letter cell may not be used more than once. + */ + +bool dfs(char **board, int r_size, int c_size, int r, int c, char *word, + int s_len, int k) { + if (k == s_len) + return 1; + if (r < 0 || c < 0 || r > r_size - 1 || c > c_size - 1 || + board[r][c] != word[k]) + return 0; + char tmp = board[r][c]; + bool res = dfs(board, r_size, c_size, r + 1, c, word, s_len, k + 1) | + dfs(board, r_size, c_size, r - 1, c, word, s_len, k + 1) | + dfs(board, r_size, c_size, r, c + 1, word, s_len, k + 1) | + dfs(board, r_size, c_size, r, c - 1, word, s_len, k + 1); + board[r][c] = tmp; + return res; +} + +bool exist(char **board, int boardSize, int *boardColSize, char *word) { + int r_size = boardSize, c_size = boardColSize[0], s_len = strlen(word); + for (int r = 0; r < r_size; r++) + for (int c = 0; c < c_size; c++) + if (dfs(board, r_size, c_size, r, c, word, s_len, 0)) + return 1; + return 0; +} diff --git a/word_search.cpp b/word_search.cpp new file mode 100644 index 0000000..bbd072f --- /dev/null +++ b/word_search.cpp @@ -0,0 +1,53 @@ +#include "leetcode.h" + +class Solution { +public: + bool exist(vvd(char) & board, string word) { + int dirs[5] = {0, -1, 0, 1, 0}; + map<char, int> cnt; + int m = board.size(), n = board[0].size(), l = word.size(); + + for (char c : word) + cnt[c] += 1; + + if (cnt[word[0]] > cnt[word[l - 1]]) + reverse(word.begin(), word.end()); + + function<bool(int, int, int)> dfs; + dfs = [&](int i, int j, int s) -> bool { + if (s == l) + return true; + + if (i < 0 or i >= m or j < 0 or j >= n) + return false; + if (board[i][j] != word[s]) + return false; + + board[i][j] = '#'; + for (int d = 0; d < 4; ++d) + if (dfs(i + dirs[d], j + dirs[d + 1], s + 1)) + return true; + board[i][j] = word[s]; + + return false; + }; + + for (int i = 0; i < m; ++i) + for (int j = 0; j < n; ++j) + if (dfs(i, j, 0)) + return true; + + return false; + } +}; + +int main() { + Solution obj; + vvd(char) board = { + {'A', 'B', 'C', 'E'}, {'S', 'F', 'C', 'S'}, {'A', 'D', 'E', 'E'}}; + string word = "ABCCED"; + if (obj.exist(board, word)) + cout << "true"; + else + cout << "false"; +} diff --git a/word_search.py b/word_search.py new file mode 100644 index 0000000..0c8bcbb --- /dev/null +++ b/word_search.py @@ -0,0 +1,68 @@ +# 79. Word Search + +""" +given an 'm * n' grid of characters 'board' and a string 'word', return 1 if +the word exists in the grid. the word can be constructed from letters of +sequentially adjacent cells, where adjacent cells are horizontally or +vertically neighbouring the same letter cell may not be used more than once. +""" + + +class Solution(object): + def dfs(self, board, i, j, word): + if len(word) == 0: + return True + if ( + i < 0 + or i >= len(board) + or j < 0 + or j >= len(board[0]) + or word[0] != board[i][j] + ): + return False + tmp = board[i][j] + board[i][j] = "#" + res = ( + self.dfs(board, i + 1, j, word[1:]) + or self.dfs(board, i - 1, j, word[1:]) + or self.dfs(board, i, j + 1, word[1:]) + or self.dfs(board, i, j - 1, word[1:]) + ) + board[i][j] = tmp + return res + + def exist(self, board, word): + """ + :type board: List[List[str]] + :type word: str + :rtype: bool + """ + if not board: + return False + for i in range(len(board)): + for j in range(len(board[0])): + if self.dfs(board, i, j, word): + return True + return False + + +if __name__ == "__main__": + obj = Solution() + print( + obj.exist( + board=[["A", "B", "C", "E"], ["S", "F", "C", "S"], ["A", "D", "E", "E"]], + word="ABCCED", + ) + ) + print( + obj.exist( + board=[["A", "B", "C", "E"], ["S", "F", "C", "S"], ["A", "D", "E", "E"]], + word="SEE", + ) + ) + print( + obj.exist( + board=[["A", "B", "C", "E"], ["S", "F", "C", "S"], ["A", "D", "E", "E"]], + word="ABCB", + ) + ) diff --git a/word_search2.cpp b/word_search2.cpp new file mode 100644 index 0000000..8163966 --- /dev/null +++ b/word_search2.cpp @@ -0,0 +1,70 @@ +#include "leetcode.h" + +struct Trie { + bool isEnd; + string word; + Trie *child[26]; + Trie() { + isEnd = false; + word = ""; + for (int i = 0; i < 26; i++) + child[i] = NULL; + } +}; + +class Solution { +public: + vector<string> ans; + vector<string> findWords(vvd(char) & board, vector<string> &words) { + int n = board.size(), m = board[0].size(); + for (auto w : words) + insert(w); + for (int i = 0; i < n; i++) + for (int j = 0; j < m; j++) + dfs(board, i, j, n, m, root); + return ans; + } + +private: + vector<int> dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1}; + Trie *root = new Trie(); + void insert(string &s) { + int n = s.size(); + Trie *curr = root; + for (int i = 0; i < n; i++) { + int idx = s[i] - 'a'; + if (curr->child[idx] == NULL) + curr->child[idx] = new Trie(); + curr = curr->child[idx]; + } + curr->isEnd = true; + curr->word = s; + } + void dfs(vvd(char) & board, int i, int j, int n, int m, Trie *curr) { + if (i < 0 || i >= n || j < 0 || j >= m || board[i][j] == '#') + return; + int idx = board[i][j] - 'a'; + if (curr->child[idx] == NULL) + return; + curr = curr->child[idx]; + if (curr->isEnd) { + ans.push_back(curr->word); + curr->isEnd = false; + } + char val = board[i][j]; + board[i][j] = '#'; + for (int k = 0; k < 4; k++) { + int newI = i + dx[k], newJ = j + dy[k]; + dfs(board, newI, newJ, n, m, curr); + } + board[i][j] = val; + } +}; + +int main() { + Solution obj; + vvd(char) board = {{'a', 'b'}, {'c', 'd'}}; + vector<string> words = {"abcb"}; + for (auto i : obj.findWords(board, words)) + cout << i << endl; +} diff --git a/word_search2.rs b/word_search2.rs new file mode 100644 index 0000000..2c61941 --- /dev/null +++ b/word_search2.rs @@ -0,0 +1,59 @@ +#[derive(Default)] +struct Solution; + +struct Trie { + child: [Option<Box<Trie>>; 26], + is_end: bool +} + +impl Solution { + pub fn find_words(board: Vec<Vec<char>>, words: Vec<String>) -> Vec<String> { + let mut trie = Trie::default(); + for w in words { + let mut node = &mut trie; + for u in w.bytes() { + node = node.child[(u - b'a') as usize].get_or_insert(Default::default()); + } + node.is_end = true; + } + let (mut board, mut ans) = (board, Vec::new()); + for i in 0..board.len() { + for j in 0..board[0].len() { + Self::backtrack( + &mut board, + &mut trie, + (i, j), + &mut String::new(), + &mut ans + ); + } + } + ans + } + fn backtrack(board: &mut Vec<Vec<char>>, trie: &mut Trie, pos: (usize, usize), s: &mut String, ans: &mut Vec<String>) { + let c = board[pos.0][pos.1]; + if let Some(node) = &mut trie.child[(c as u8 - b'a') as usize] { + s.push(c); + if node.is_end { + ans.push(s.clone()); + node.is_end = false; + } + board[pos.0][pos.1] = '*'; + for d in [0,1,0,!0,0].windows(2) { + let i = pos.0.wrapping_add(d[0]); + let j = pos.1.wrapping_add(d[1]); + if (0..board.len()).contains(&i) && (0..board[0].len()).contains(&j) && board[i][j] != '*' { + Self::backtrack(board, node, (i, j), s, ans); + } + } + board[pos.0][pos.1] = c; + s.pop(); + } + } +} + +fn main() { + let board = vec![vec!['a','b'], vec!['c','d']]; + let words = vec!["abcb".to_string()]; + print!("{:?}", Solution::find_words(board, words)); +} diff --git a/word_subsets.cpp b/word_subsets.cpp new file mode 100644 index 0000000..ea4c1f9 --- /dev/null +++ b/word_subsets.cpp @@ -0,0 +1,34 @@ +#include "leetcode.h" + +class Solution { +public: + vector<string> wordSubsets(vector<string> &words1, vector<string> &words2) { + int bFreq[26] = {0}, check[26] = {0}; + int cMax = 0; + vector<string> ans; + for (string word : words2) { + for (char c : word) + check[c - 'a']++; + for (int j = 0; j < 26; j++) { + int diff = check[j] - bFreq[j]; + if (diff > 0) + cMax += diff, bFreq[j] += diff; + } + if (cMax > 10) + return ans; + fill(check, check + 26, 0); + } + for (string word : words1) { + int j; + for (char c : word) + check[c - 'a']++; + for (j = 0; j < 26; j++) + if (check[j] < bFreq[j]) + break; + if (j == 26) + ans.push_back(word); + fill(check, check + 26, 0); + } + return ans; + } +}; diff --git a/zigzag_conversion.c b/zigzag_conversion.c new file mode 100644 index 0000000..836b196 --- /dev/null +++ b/zigzag_conversion.c @@ -0,0 +1,65 @@ +// 6. Zigzag Conversion +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * the string "PAYPALISHIRING" is written in zigzag pattern on a given number + * of rows like this: + * P A H N + * A P L S I I G + * Y I R + * and then read line by line: "PAHNAPLSIIGYIR". write function that will take + * a string and mak this conversion give a number of rows. + */ + +char *convert(char *s, int numRows) { + const int len = strlen(s); + if (numRows == 1 || len == 1) + return s; + int sub_len; + if (numRows == 2) + sub_len = len / 2 + len % 2; + else + sub_len = len / (numRows - 1); + int *id = calloc(numRows, sizeof(int)); + char **substr = malloc(numRows * sizeof(char *)); + for (int i = 0; i < numRows; i++) + substr[i] = malloc((sub_len + 1) * sizeof(char)); + substr[0][0] = s[0]; + id[0] = 1; + int state = 1, pos; + while (state < len) { + // down + for (int i = 1; i < numRows && state < len; i++) { + pos = id[i]; + substr[i][pos] = s[state]; + state++; + id[i]++; + } + // up + for (int i = numRows - 2; i >= 0 && state < len; i--) { + pos = id[i]; + substr[i][pos] = s[state]; + state++; + id[i]++; + } + } + pos = 0; + for (int i = 0; i < numRows; i++) { + strncpy(&s[pos], substr[i], id[i]); + pos += i; + } + for (int i = 0; i < numRows; i++) + free(substr[i]); + free(substr); + free(id); + return s; +} + +int main() { + char s1_2[] = "PAYPALISHIRING", s3[] = "A"; + printf("%s\n", convert(s1_2, 3)); // expect: PAHNAPLSIIGYIR + printf("%s\n", convert(s1_2, 4)); // expect: PINALSIGYAHRPI + printf("%s\n", convert(s3, 1)); // expect: A +} diff --git a/zigzag_conversion.cpp b/zigzag_conversion.cpp new file mode 100644 index 0000000..aa3fba6 --- /dev/null +++ b/zigzag_conversion.cpp @@ -0,0 +1,43 @@ +// 6. Zigzag Conversion +#include "leetcode.h" + +/* + * the string "PAYPALISHIRING" is written in zigzag pattern on a given number + * of rows like this: + * P A H N + * A P L S I I G + * Y I R + * and then read line by line: "PAHNAPLSIIGYIR". write function that will take + * a string and mak this conversion give a number of rows. + */ + +class Solution { +public: + string convert(string s, int numRows) { + if (numRows <= 1) + return s; + const int len = (int)s.size(); + string *str = new string[numRows]; + int row = 0, step = 1; + for (int i = 0; i < len; ++i) { + str[row].push_back(s[i]); + if (row == 0) + step = 1; + else if (row == numRows - 1) + step = -1; + row += step; + } + s.clear(); + for (int i = 0; i < numRows; ++i) + s.append(str[i]); + delete[] str; + return s; + } +}; + +int main() { + Solution obj; + cout << obj.convert("PAYPALISHIRING", 3) << endl; // expect: PAHNAPLSIIGYIR + cout << obj.convert("PAYPALISHIRING", 4) << endl; // expect: PINALSIGYAHRPI + cout << obj.convert("A", 1) << endl; // expect: A +} |