diff --git a/.gitignore b/.gitignore index 1f1c65c40..25a4d2a65 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea algorithms-java/out +*.class diff --git a/README.md b/README.md index 3f71fe9be..3091c6a5c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,30 @@ LeetCode | # | Title | Solution | Difficulty | |---| ----- | -------- | ---------- | +|377|[Combination Sum IV](https://leetcode.com/problems/combination-sum-iv/) | [C++](./algorithms/cpp/combinationSumIV/combinationSumIV.cpp)|Medium| +|376|[Wiggle Subsequence](https://leetcode.com/problems/wiggle-subsequence/) | [C++](./algorithms/cpp/wiggleSubsequence/wiggleSubsequence.cpp)|Medium| +|350|[Intersection of Two Arrays II](https://leetcode.com/problems/intersection-of-two-arrays-ii/) | [C++](./algorithms/cpp/intersectionOfTwoArraysII/intersectionOfTwoArraysII.cpp)|Easy| +|349|[Intersection of Two Arrays](https://leetcode.com/problems/intersection-of-two-arrays/) | [C++](./algorithms/cpp/intersectionOfTwoArrays/intersectionOfTwoArrays.cpp)|Easy| +|347|[Top K Frequent Elements](https://leetcode.com/problems/top-k-frequent-elements/) | [C++](./algorithms/cpp/topKFrequentElements/topKFrequentElements.cpp)|Medium| +|345|[Reverse Vowels of a String](https://leetcode.com/problems/reverse-vowels-of-a-string/) | [C++](./algorithms/cpp/reverseVowelsOfAString/reverseVowelsOfAString.cpp)|Easy| +|344|[Reverse String](https://leetcode.com/problems/reverse-string/) | [C++](./algorithms/cpp/reverseString/ReverseString.cpp)|Easy| +|343|[Integer Break](https://leetcode.com/problems/integer-break/) | [C++](./algorithms/cpp/integerBreak/IntegerBreak.cpp)|Medium| +|342|[Power of Four](https://leetcode.com/problems/power-of-four/) | [C++](./algorithms/cpp/powerOfFour/PowerOfFour.cpp)|Easy| +|341|[Flatten Nested List Iterator](https://leetcode.com/problems/flatten-nested-list-iterator/) | [C++](./algorithms/cpp/flattenNestedListIterator/FlattenNestedListIterator.cpp)|Medium| +|338|[Counting Bits](https://leetcode.com/problems/counting-bits/) | [C++](./algorithms/cpp/countingBits/CountingBits.cpp)|Medium| +|337|[House Robber III](https://leetcode.com/problems/house-robber-iii/) | [C++](./algorithms/cpp/houseRobber/houseRobberIII.cpp)|Medium| +|334|[Increasing Triplet Subsequence](https://leetcode.com/problems/increasing-triplet-subsequence/) | [C++](./algorithms/cpp/increasingTripletSubsequence/increasingTripletSubsequence.cpp)|Medium| +|330|[Patching Array](https://leetcode.com/problems/patching-array/) | [C++](./algorithms/cpp/patchingArray/PatchingArray.cpp)|Medium| +|329|[Longest Increasing Path in a Matrix](https://leetcode.com/problems/longest-increasing-path-in-a-matrix/) | [C++](./algorithms/cpp/longestIncreasingPathInAMatrix/LongestIncreasingPathInAMatrix.cpp)|Medium| +|328|[Odd Even Linked List](https://leetcode.com/problems/odd-even-linked-list/) | [C++](./algorithms/cpp/oddEvenLinkedList/OddEvenLinkedList.cpp)|Easy| +|327|[Count of Range Sum](https://leetcode.com/problems/count-of-range-sum/) | [C++](./algorithms/cpp/countOfRangeSum/CountOfRangeSum.cpp)|Hard| +|326|[Power of Three](https://leetcode.com/problems/power-of-three/) | [C++](./algorithms/cpp/powerOfThree/PowerOfThree.cpp)|Easy| +|322|[Coin Change](https://leetcode.com/problems/coin-change/) | [C++](./algorithms/cpp/coinChange/coinChange.cpp)|Medium| +|321|[Create Maximum Number](https://leetcode.com/problems/create-maximum-number/) | [C++](./algorithms/cpp/createMaximumNumber/CreateMaximumNumber.cpp)|Hard| +|319|[Bulb Switcher](https://leetcode.com/problems/bulb-switcher/) | [C++](./algorithms/cpp/bulbSwitcher/bulbSwitcher.cpp)|Medium| |315|[Count of Smaller Numbers After Self](https://leetcode.com/problems/count-of-smaller-numbers-after-self/) | [C++](./algorithms/cpp/countOfSmallerNumbersAfterSelf/countOfSmallerNumbersAfterSelf.cpp)|Hard| +|312|[Burst Balloons](https://leetcode.com/problems/burst-balloons/) | [C++](./algorithms/cpp/burstBalloons/BurstBalloons.cpp)|Hard| +|310|[Minimum Height Trees](https://leetcode.com/problems/minimum-height-trees/) | [C++](./algorithms/cpp/minimumHeightTrees/MinimumHeightTrees.cpp)|Medium| |307|[Range Sum Query - Mutable](https://leetcode.com/problems/range-sum-query-mutable/) | [C++](./algorithms/cpp/rangeSumQuery-Immutable/rangeSumQuery-Mutable/RangeSumQueryMutable.cpp)|Medium| |306|[Additive Number](https://leetcode.com/problems/additive-number/) | [C++](./algorithms/cpp/additiveNumber/AdditiveNumber.cpp)|Medium| |304|[Range Sum Query 2D - Immutable](https://leetcode.com/problems/range-sum-query-2d-immutable/) | [C++](./algorithms/cpp/rangeSumQuery2D-Immutable/RangeSumQuery2dImmutable.cpp)|Medium| @@ -24,6 +47,7 @@ LeetCode |285|[Inorder Successor in BST](https://leetcode.com/problems/inorder-successor-in-bst/) ♥ | [Java](./algorithms/java/src/inorderSuccessorInBST/inorderSuccessorInBST.java)|Medium| |284|[Peeking Iterator](https://leetcode.com/problems/peeking-iterator/) | [C++](./algorithms/cpp/peekingIterator/PeekingIterator.cpp)|Medium| |283|[Move Zeroes](https://leetcode.com/problems/move-zeroes/) | [C++](./algorithms/cpp/moveZeroes/moveZeroes.cpp)|Easy| +|282|[Expression Add Operators](https://leetcode.com/problems/expression-add-operators/) | [C++](./algorithms/cpp/expressionAddOperators/ExpressionAddOperators.cpp)|Hard| |279|[Perfect Squares](https://leetcode.com/problems/perfect-squares/) | [C++](./algorithms/cpp/perfectSquares/PerfectSquares.cpp)|Medium| |278|[First Bad Version](https://leetcode.com/problems/first-bad-version/)| [C++](./algorithms/cpp/firstBadVersion/FirstBadVersion.cpp), [Java](./algorithms/java/src/firstBadVersion/firstBadVersion.java)|Easy| |275|[H-Index II](https://leetcode.com/problems/h-index-ii/)| [C++](./algorithms/cpp/h-Index/h-Index.II.cpp)|Medium| @@ -32,6 +56,7 @@ LeetCode |268|[Missing Number](https://leetcode.com/problems/missing-number/)| [C++](./algorithms/cpp/missingNumber/MissingNumber.cpp)|Medium| |264|[Ugly Number II](https://leetcode.com/problems/ugly-number-ii/)| [C++](./algorithms/cpp/uglyNumber/UglyNumber.II.cpp)|Medium| |263|[Ugly Number](https://leetcode.com/problems/ugly-number/)| [C++](./algorithms/cpp/uglyNumber/UglyNumber.cpp)|Easy| +|260|[Single Number III](https://leetcode.com/problems/single-number-iii/)| [C++](./algorithms/cpp/singleNumber/singleNumber.III.cpp)|Medium| |258|[Add Digits](https://leetcode.com/problems/add-digits/)| [C++](./algorithms/cpp/addDigits/addDigits.cpp)|Easy| |257|[Binary Tree Paths](https://leetcode.com/problems/binary-tree-paths/)| [C++](./algorithms/cpp/binaryTreePaths/binaryTreePaths.cpp)|Easy| |242|[Valid Anagram](https://leetcode.com/problems/valid-anagram/)| [C++](./algorithms/cpp/anagrams/ValidAnagram.cpp)|Easy| @@ -114,7 +139,7 @@ LeetCode |149|[Max Points on a Line](https://oj.leetcode.com/problems/max-points-on-a-line/)| [C++](./algorithms/cpp/maxPointsOnALine/maxPointsOnALine.cpp)|Hard| |148|[Sort List](https://oj.leetcode.com/problems/sort-list/)| [C++](./algorithms/cpp/sortList/sortList.cpp)|Medium| |147|[Insertion Sort List](https://oj.leetcode.com/problems/insertion-sort-list/)| [C++](./algorithms/cpp/insertionSortList/insertionSortList.cpp)|Medium| -|146|[LRU Cache](https://oj.leetcode.com/problems/lru-cache/)| [C++](./algorithms/cpp/LRUCache/LRUCache.cpp)|Hard| +|146|[LRU Cache](https://oj.leetcode.com/problems/lru-cache/)| [C++](./algorithms/cpp/LRUCache/LRUCache.cpp), [Java](./algorithms/java/src/lruCache/LRUCache.java)|Hard| |145|[Binary Tree Postorder Traversal](https://oj.leetcode.com/problems/binary-tree-postorder-traversal/)| [C++](./algorithms/cpp/binaryTreePostorderTraversal/binaryTreePostorderTraversal.cpp)|Hard| |144|[Binary Tree Preorder Traversal](https://oj.leetcode.com/problems/binary-tree-preorder-traversal/)| [C++](./algorithms/cpp/binaryTreePreorderTraversal/binaryTreePreorderTraversal.cpp), [Java](./algorithms/java/src/binaryTreePreorderTraversal/binaryTreePreorderTraversal.java)|Medium| |143|[Reorder List](https://oj.leetcode.com/problems/reorder-list/)| [C++](./algorithms/cpp/reorderList/reorderList.cpp)|Medium| diff --git a/algorithms/cpp/3Sum/3Sum.cpp b/algorithms/cpp/3Sum/3Sum.cpp index 0b38716e4..711550183 100644 --- a/algorithms/cpp/3Sum/3Sum.cpp +++ b/algorithms/cpp/3Sum/3Sum.cpp @@ -71,7 +71,7 @@ vector > threeSum(vector &num) { result.push_back(v); // Continue search for all triplet combinations summing to zero. //skip the duplication - while(low0 && num[high]==num[high-1]) high--; low++; high--; diff --git a/algorithms/cpp/bulbSwitcher/bulbSwitcher.cpp b/algorithms/cpp/bulbSwitcher/bulbSwitcher.cpp new file mode 100644 index 000000000..d4f51736b --- /dev/null +++ b/algorithms/cpp/bulbSwitcher/bulbSwitcher.cpp @@ -0,0 +1,80 @@ +// Source : https://leetcode.com/problems/bulb-switcher/ +// Author : Calinescu Valentin, Hao Chen +// Date : 2015-12-28 + +/*************************************************************************************** + * + * There are n 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's off or turning off if it's on). For the nth round, you only toggle the + * last bulb. Find how many bulbs are on after n rounds. + * + * Example: + * + * Given n = 3. + * + * At first, the three bulbs are [off, off, off]. + * After first round, the three bulbs are [on, on, on]. + * After second round, the three bulbs are [on, off, on]. + * After third round, the three bulbs are [on, off, off]. + * + * So you should return 1, because there is only one bulb is on. + * + ***************************************************************************************/ + + /* Solution + * -------- + * + * We know, + * - if a bulb can be switched to ON eventually, it must be switched by ODD times + * - Otherwise, if a bulb has been switched by EVEN times, it will be OFF eventually. + * So, + * - If bulb `i` ends up ON if and only if `i` has an ODD numbers of divisors. + * And we know, + * - the divisors come in pairs. for example: + * 12 - [1,12] [2,6] [3,4] [6,2] [12,1] (the 12th bulb would be switched by 1,2,3,4,6,12) + * - the pairs means almost all of the numbers are switched by EVEN times. + * + * But we have a special case - square numbers + * - A square number must have a divisors pair with same number. such as 4 - [2,2], 9 - [3,3] + * - So, a square number has a ODD numbers of divisors. + * + * At last, we figure out the solution is: + * + * Count the number of the squre numbers!! + */ + +class Solution { +public: + int bulbSwitch(int n) { + int cnt = 0; + for (int i=1; i*i<=n; i++) { + cnt++; + } + return cnt; + } +}; + + + + /* + * Solution 1 - O(1) + * ========= + * + * We notice that for every light bulb on position i there will be one toggle for every + * one of its divisors, given that you toggle all of the multiples of one number. The + * total number of toggles is irrelevant, because there are only 2 possible positions(on, + * off). We quickly find that 2 toggles cancel each other so given that the start position + * is always off a light bulb will be in if it has been toggled an odd number of times. + * The only integers with an odd number of divisors are perfect squares(because the square + * root only appears once, not like the other divisors that form pairs). The problem comes + * down to finding the number of perfect squares <= n. That number is the integer part of + * the square root of n. + * + */ +class Solution { +public: + int bulbSwitch(int n) { + return (int)sqrt(n); + } +}; diff --git a/algorithms/cpp/bullsAndCows/bullsAndCows.cpp b/algorithms/cpp/bullsAndCows/bullsAndCows.cpp index f91550532..feeb1bb89 100644 --- a/algorithms/cpp/bullsAndCows/bullsAndCows.cpp +++ b/algorithms/cpp/bullsAndCows/bullsAndCows.cpp @@ -42,8 +42,8 @@ class Solution { } string getHint01(string secret, string guess) { - int appears_in_secret[10], appears_in_guess[10], bulls[10]; - int total_bulls, total_cows; + int appears_in_secret[10] = {0}, appears_in_guess[10] = {0}, bulls[10] = {0}; + int total_bulls = 0, total_cows = 0; for(int i = 0; i < secret.size(); i++) appears_in_secret[secret[i] - '0']++; for(int i = 0; i < guess.size(); i++) diff --git a/algorithms/cpp/burstBalloons/BurstBalloons.cpp b/algorithms/cpp/burstBalloons/BurstBalloons.cpp new file mode 100644 index 000000000..901f2e8eb --- /dev/null +++ b/algorithms/cpp/burstBalloons/BurstBalloons.cpp @@ -0,0 +1,104 @@ +// Source : https://leetcode.com/problems/burst-balloons/ +// Author : Hao Chen +// Date : 2016-01-17 + +/*************************************************************************************** + * + * Given n balloons, indexed from 0 to n-1. Each balloon is painted with a + * number on it represented by array nums. + * + * You are asked to burst all the balloons. If the you burst + * balloon i you will get nums[left] * nums[i] * nums[right] coins. Here left + * and right are adjacent indices of i. After the burst, the left and right + * then becomes adjacent. + * + * Find the maximum coins you can collect by bursting the balloons wisely. + * + * Note: + * (1) You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can + * not burst them. + * (2) 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100 + * + * Example: + * + * Given [3, 1, 5, 8] + * + * Return 167 + * + * nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> [] + * coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167 + * + * Credits:Special thanks to @dietpepsi for adding this problem and creating all test + * cases. + ***************************************************************************************/ + + + +class Solution { +public: + int maxCoins(vector& nums) { + //remove all of zero item + nums.erase(remove_if(nums.begin(), nums.end(), [](int n){return n==0;}), nums.end()); + + //add 1 for head and tail + nums.insert(nums.begin(),1); + nums.push_back(1); + + int n = nums.size(); + vector< vector > matrix(n, vector(n,0)); + + return maxCoins_DP(nums, matrix); + return maxCoins_DC(nums, matrix, 0, n-1); + } + + + //Divide and Conquer + // + // If we seprate the array to two part, left part and right part. + // + // Then, we will find in this problem the left and right become adjacent + // and have effects on the maxCoins in the future. + // + // So, if we think reversely, if the balloon i is the last balloon of all to burst, + // the left and right section now has well defined boundary and do not affect each other! + // Therefore we can do either recursive method with memoization + // + int maxCoins_DC(vector& nums, vector>& matrix, int low, int high) { + if (low + 1 == high) return 0; + if (matrix[low][high] > 0) return matrix[low][high]; + int result = 0; + for (int i = low + 1; i < high; ++i){ + result = max(result, nums[low] * nums[i] * nums[high] + + maxCoins_DC(nums, matrix, low, i) + + maxCoins_DC(nums, matrix, i, high)); + } + matrix[low][high] = result; + return result; + } + + //Dynamic Programming + // + // using the same idea of above + // + int maxCoins_DP(vector& nums, vector>& dp) { + int n = nums.size(); + for (int k = 2; k < n; ++k) { + for (int low = 0; low < n - k; low++){ + int high = low + k; + for (int i = low + 1; i < high; ++i) + dp[low][high] = max( dp[low][high], + nums[low] * nums[i] * nums[high] + dp[low][i] + dp[i][high]); + } + } + return dp[0][n - 1]; + } + +private: + void printVector(vector& nums) { + cout << "nums: "; + for (auto n: nums) { + cout << n << ' '; + } + cout << '\n'; + } +}; diff --git a/algorithms/cpp/coinChange/coinChange.cpp b/algorithms/cpp/coinChange/coinChange.cpp new file mode 100644 index 000000000..2b7d9b296 --- /dev/null +++ b/algorithms/cpp/coinChange/coinChange.cpp @@ -0,0 +1,83 @@ +// Source : https://leetcode.com/problems/coin-change/ +// Author : Calinescu Valentin, Hao Chen +// Date : 2015-12-28 + +/*************************************************************************************** + * + * You are given coins of different denominations and a total amount of money amount. + * Write a function to compute the fewest number of coins that you need to make up that + * amount. If that amount of money cannot be made up by any combination of the coins, + * return -1. + * + * Example 1: + * coins = [1, 2, 5], amount = 11 + * return 3 (11 = 5 + 5 + 1) + * + * Example 2: + * coins = [2], amount = 3 + * return -1. + * + * Note: + * You may assume that you have an infinite number of each kind of coin. + * + * Credits: + * Special thanks to @jianchao.li.fighter for adding this problem and creating all test + * cases. + * + ***************************************************************************************/ + /* + * Solution 1 - O(N * amount) + * ========= + * + * This problem can be solved using dynamic programming, thus building the optimal + * solution from previous smaller ones. For every coin of value t and every sum of money + * i the sum can be traced back to a previous sum i - t that was already computed and uses + * the smallest number of coins possible. This way we can construct every sum i as the + * minimum of all these previous sums for every coin value. To be sure we'll find a minimum + * we can populate the solution vector with an amount bigger than the maximum possible, + * which is amount + 1(when the sum is made up of only coins of value 1). The only exception + * is sol[0] which is 0 as we need 0 coins to have a sum of 0. In the end we need to look + * if the program found a solution in sol[amount] or it remained the same, in which case we + * can return -1. + * + */ +class Solution { +public: + + int coinChange(vector& coins, int amount) { + int sol[amount + 1]; + sol[0] = 0; + for(int i = 1; i <= amount; i++) + sol[i] = amount + 1; + for(int i = 0; i < coins.size(); i++) + { + for(int j = coins[i]; j <= amount; j++) + sol[j] = min(sol[j], sol[j - coins[i]] + 1); + } + if(sol[amount] != amount + 1) + return sol[amount]; + else + return -1; + } +}; + + +//Another DP implmentation, same idea above +class Solution { +public: + int coinChange(vector& coins, int amount) { + const int MAX = amount +1; + vector dp(amount+1, MAX); + dp[0]=0; + + for(int i=1; i<=amount; i++) { + for (int j=0; j= coins[j]) { + dp[i] = min( dp[i], dp[i-coins[j]] + 1 ); + } + } + } + + return dp[amount]==MAX ? -1 : dp[amount]; + } +}; diff --git a/algorithms/cpp/combinationSumIV/combinationSumIV.cpp b/algorithms/cpp/combinationSumIV/combinationSumIV.cpp new file mode 100644 index 000000000..d3006375d --- /dev/null +++ b/algorithms/cpp/combinationSumIV/combinationSumIV.cpp @@ -0,0 +1,68 @@ +// Source : https://leetcode.com/problems/combination-sum-iv/ +// Author : Calinescu Valentin +// Date : 2016-08-07 + +/*************************************************************************************** + * + * Given an integer array with all positive numbers and no duplicates, find the number + * of possible combinations that add up to a positive integer target. + * + * Example: + * + * nums = [1, 2, 3] + * target = 4 + * + * The possible combination ways are: + * (1, 1, 1, 1) + * (1, 1, 2) + * (1, 2, 1) + * (1, 3) + * (2, 1, 1) + * (2, 2) + * (3, 1) + * + * Note that different sequences are counted as different combinations. + * + * Therefore the output is 7. + * Follow up: + * What if negative numbers are allowed in the given array? + * How does it change the problem? + * What limitation we need to add to the question to allow negative numbers? + * + ***************************************************************************************/ + + /* Solution + * -------- + * 1) Dynamic Programming - O(N * target) + * + * We notice that any sum S can be written as S_prev + nums[i], where S_prev is a sum of + * elements from nums and nums[i] is one element of the array. S_prev is always smaller + * than S so we can create the array sol, where sol[i] is the number of ways one can + * arrange the elements of the array to obtain sum i, and populate it from 1 to target, + * as the solution for i is made up of previously computed ones for numbers smaller than + * i. The final answer is sol[target], which is returned at the end. + * + * Follow up: + * + * If the array contains negative numbers as well as positive ones we can run into a cycle + * where some subset of the elements have sum 0 so they can always be added to an existing + * sum, leading to an infinite number of solutions. The limitation that we need is a rule + * to be followed by the input data, that which doesn't allow this type of subsets to exist. + */ +class Solution { +public: + int combinationSum4(vector& nums, int target) { + int sol[target + 1]; + sol[0] = 1;//starting point, only 1 way to obtain 0, that is to have 0 elements + for(int i = 1; i <= target; i++) + { + sol[i] = 0; + for(int j = 0; j < nums.size(); j++) + { + if(i >= nums[j])//if there is a previously calculated sum to add nums[j] to + sol[i] += sol[i - nums[j]]; + } + } + return sol[target]; + } +}; diff --git a/algorithms/cpp/countOfRangeSum/CountOfRangeSum.cpp b/algorithms/cpp/countOfRangeSum/CountOfRangeSum.cpp new file mode 100644 index 000000000..81b1f21bb --- /dev/null +++ b/algorithms/cpp/countOfRangeSum/CountOfRangeSum.cpp @@ -0,0 +1,163 @@ +// Source : https://leetcode.com/problems/count-of-range-sum/ +// Author : Hao Chen +// Date : 2016-01-15 + +/*************************************************************************************** + * + * Given an integer array nums, return the number of range sums that lie in [lower, + * upper] inclusive. + * + * Range sum S(i, j) is defined as the sum of the elements in nums between indices + * i and + * j (i ≤ j), inclusive. + * + * Note: + * A naive algorithm of O(n2) is trivial. You MUST do better than that. + * + * Example: + * Given nums = [-2, 5, -1], lower = -2, upper = 2, + * Return 3. + * The three ranges are : [0, 0], [2, 2], [0, 2] and their respective sums are: -2, -1, 2. + * + * Credits:Special thanks to @dietpepsi for adding this problem and creating all test + * cases. + * + ***************************************************************************************/ + + +/* + * At first of all, we can do preprocess to calculate the prefix sums + * + * S[i] = S(0, i), then S(i, j) = S[j] - S[i]. + * + * Note: S(i, j) as the sum of range [i, j) where j exclusive and j > i. + * + * With these prefix sums, it is trivial to see that with O(n^2) time we can find all S(i, j) + * in the range [lower, upper] + * + * int countRangeSum(vector& nums, int lower, int upper) { + * int n = nums.size(); + * long[] sums = new long[n + 1]; + * for (int i = 0; i < n; ++i) { + * sums[i + 1] = sums[i] + nums[i]; + * } + * int ans = 0; + * for (int i = 0; i < n; ++i) { + * for (int j = i + 1; j <= n; ++j) { + * if (sums[j] - sums[i] >= lower && sums[j] - sums[i] <= upper) { + * ans++; + * } + * } + * } + * delete []sums; + * return ans; + * } + * + * The above solution would get time limit error. + * + * Recall `count smaller number after self` where we encountered the problem + * + * count[i] = count of nums[j] - nums[i] < 0 with j > i + * + * Here, after we did the preprocess, we need to solve the problem + * + * count[i] = count of a <= S[j] - S[i] <= b with j > i + * + * In other words, if we maintain the prefix sums sorted, and then are able to find out + * - how many of the sums are less than 'lower', say num1, + * - how many of the sums are less than 'upper + 1', say num2, + * Then 'num2 - num1' is the number of sums that lie within the range of [lower, upper]. + * + */ + +class Node{ + public: + long long val; + int cnt; //amount of the nodes + Node *left, *right; + Node(long long v):val(v), cnt(1), left(NULL), right(NULL) {} +}; + +// a tree stores all of prefix sums +class Tree{ + public: + Tree():root(NULL){ } + ~Tree() { freeTree(root); } + + void Insert(long long val) { + Insert(root, val); + } + int LessThan(long long sum, int val) { + return LessThan(root, sum, val, 0); + } + + private: + Node* root; + + //general binary search tree insert algorithm + void Insert(Node* &root, long long val) { + if (!root) { + root = new Node(val); + return; + } + + root->cnt++; + + if (val < root->val ) { + Insert(root->left, val); + }else if (val > root->val) { + Insert(root->right, val); + } + } + //return how many of the sums less than `val` + // - `sum` is the new sums which hasn't been inserted + // - `val` is the `lower` or `upper+1` + int LessThan(Node* root, long long sum, int val, int res) { + + if (!root) return res; + + if ( sum - root->val < val) { + //if (sum[j, i] < val), which means all of the right branch must be less than `val` + //so we add the amounts of sums in right branch, and keep going the left branch. + res += (root->cnt - (root->left ? root->left->cnt : 0) ); + return LessThan(root->left, sum, val, res); + }else if ( sum - root->val > val) { + //if (sum[j, i] > val), which means all of left brach must be greater than `val` + //so we just keep going the right branch. + return LessThan(root->right, sum, val, res); + }else { + //if (sum[j,i] == val), which means we find the correct place, + //so we just return the the amounts of right branch.] + return res + (root->right ? root->right->cnt : 0); + } + } + void freeTree(Node* root){ + if (!root) return; + if (root->left) freeTree(root->left); + if (root->right) freeTree(root->right); + delete root; + } + +}; + + + +class Solution { +public: + int countRangeSum(vector& nums, int lower, int upper) { + Tree tree; + tree.Insert(0); + long long sum = 0; + int res = 0; + + for (int n : nums) { + sum += n; + int lcnt = tree.LessThan(sum, lower); + int hcnt = tree.LessThan(sum, upper + 1); + res += (hcnt - lcnt); + tree.Insert(sum); + } + + return res; + } +}; diff --git a/algorithms/cpp/countOfSmallerNumbersAfterSelf/countOfSmallerNumbersAfterSelf.cpp b/algorithms/cpp/countOfSmallerNumbersAfterSelf/countOfSmallerNumbersAfterSelf.cpp index cac1435c4..badec47d2 100644 --- a/algorithms/cpp/countOfSmallerNumbersAfterSelf/countOfSmallerNumbersAfterSelf.cpp +++ b/algorithms/cpp/countOfSmallerNumbersAfterSelf/countOfSmallerNumbersAfterSelf.cpp @@ -1,5 +1,5 @@ // Source : https://leetcode.com/problems/count-of-smaller-numbers-after-self/ -// Author : Calinescu Valentin +// Author : Calinescu Valentin, Hao Chen // Date : 2015-12-08 /*************************************************************************************** @@ -73,3 +73,80 @@ class Solution { return sol; } }; + + +/*************************************************************************************** + * Another solution - Binary Search Tree + ***************************************************************************************/ + + +class BinarySearchTreeNode +{ + public: + int val; + int less; // count of members less than val + int count; // count of members equal val + BinarySearchTreeNode *left, *right; + BinarySearchTreeNode(int value) : val(value), less(0),count(1),left(NULL), right(NULL) {} +}; + +class BinarySearchTree +{ + private: + BinarySearchTreeNode* root; + public: + BinarySearchTree(const int value):root(new BinarySearchTreeNode(value)){ } + ~BinarySearchTree() { + freeTree(root); + } + void insert(const int value, int &numLessThan) { + insert(root, value, numLessThan); + } + private: + void freeTree(BinarySearchTreeNode* root){ + if (root == NULL) return; + if (root->left) freeTree(root->left); + if (root->right) freeTree(root->right); + delete root; + } + + void insert(BinarySearchTreeNode* root, const int value, int &numLessThan) { + + if(value < root->val) { // left + root->less++; + if(root->left == NULL) { + root->left = new BinarySearchTreeNode(value); + }else{ + this->insert(root->left, value, numLessThan); + } + } else if(value > root->val) { // right + numLessThan += root->less + root->count; + if(!root->right) { + root->right = new BinarySearchTreeNode(value); + }else{ + this->insert(root->right, value, numLessThan); + } + } else { + numLessThan += root->less; + root->count++; + return; + } + } +}; + +class Solution { + public: + vector countSmaller(vector& nums) { + vector counts(nums.size()); + if(nums.size() == 0) return counts; + + BinarySearchTree tree(nums[nums.size()-1]); + + for(int i = nums.size() - 2; i >= 0; i--) { + int numLessThan = 0; + tree.insert( nums[i], numLessThan); + counts[i] = numLessThan; + } + return counts; + } +}; diff --git a/algorithms/cpp/countingBits/CountingBits.cpp b/algorithms/cpp/countingBits/CountingBits.cpp new file mode 100644 index 000000000..0bfe843b1 --- /dev/null +++ b/algorithms/cpp/countingBits/CountingBits.cpp @@ -0,0 +1,67 @@ +// Source : https://leetcode.com/problems/counting-bits/ +// Author : Hao Chen +// Date : 2016-05-30 + +/*************************************************************************************** + * + * Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ + * num calculate the number of 1's in their binary representation and return them as an + * array. + * + * Example: + * For num = 5 you should return [0,1,1,2,1,2]. + * + * Follow up: + * + * It is very easy to come up with a solution with run time O(n*sizeof(integer)). But + * can you do it in linear time O(n) /possibly in a single pass? + * Space complexity should be O(n). + * Can you do it like a boss? Do it without using any builtin function like + * __builtin_popcount in c++ or in any other language. + * + * You should make use of what you have produced already. + * Divide the numbers in ranges like [2-3], [4-7], [8-15] and so on. And try to + * generate new range from previous. + * Or does the odd/even status of the number help you in calculating the number of 1s? + * + * Credits:Special thanks to @ syedee for adding this problem and creating all test + * cases. + ***************************************************************************************/ + +class Solution { +public: + /* + * Initialization + * + * bits_cnt[0] => 0000 => 0 + * bits_cnt[1] => 0001 => 1 + * + * if the number has 2 bits (2, 3), then we can split the binary to two parts, + * 2 = 10 + 0 and 3= 10 + 1, then we can reuse the bits_cnt[0] and bits_cnt[1] + * + * bits_cnt[2] => 0010 => 0010 + 0 => 1 + bits_cnt[0]; + * bits_cnt[3] => 0011 => 0010 + 1 => 1 + bits_cnt[1]; + * + * if the number has 3 bits (4,5,6,7), then we can split the binary to two parts, + * 4 = 100 + 0, 5 = 100 + 01, 6= 100 + 10, 7 = 100 +11 + * then we can reuse the bits_cnt[0] and bits_cnt[1] + * + * bits_cnt[4] => 0110 => 0100 + 00 => 1 + bits_cnt[0]; + * bits_cnt[5] => 0101 => 0100 + 01 => 1 + bits_cnt[1]; + * bits_cnt[6] => 0110 => 0100 + 10 => 1 + bits_cnt[2]; + * bits_cnt[7] => 0111 => 0100 + 11 => 1 + bits_cnt[3]; + * + * so, we can have the solution: + * + * bits_cnt[x] = bits_cnt[x & (x-1) ] + 1; + * + */ + vector countBits(int num) { + vector bits_cnt(num+1, 0); + + for (int i=1; i<=num; i++) { + bits_cnt[i] = bits_cnt[i & (i-1)] + 1; + } + return bits_cnt; + } +}; diff --git a/algorithms/cpp/createMaximumNumber/CreateMaximumNumber.cpp b/algorithms/cpp/createMaximumNumber/CreateMaximumNumber.cpp new file mode 100644 index 000000000..dc88f9a41 --- /dev/null +++ b/algorithms/cpp/createMaximumNumber/CreateMaximumNumber.cpp @@ -0,0 +1,152 @@ +// Source : https://leetcode.com/problems/create-maximum-number/ +// Author : Hao Chen +// Date : 2016-01-21 + +/*************************************************************************************** + * + * Given two arrays of length m and n with digits 0-9 representing two numbers. + * Create the maximum number of length k from digits of the two. The relative + * order of the digits + * from the same array must be preserved. Return an array of the k digits. You + * should try to optimize your time and space complexity. + * + * Example 1: + * + * nums1 = [3, 4, 6, 5] + * nums2 = [9, 1, 2, 5, 8, 3] + * k = 5 + * return [9, 8, 6, 5, 3] + * + * Example 2: + * + * nums1 = [6, 7] + * nums2 = [6, 0, 4] + * k = 5 + * return [6, 7, 6, 0, 4] + * + * Example 3: + * + * nums1 = [3, 9] + * nums2 = [8, 9] + * k = 3 + * return [9, 8, 9] + * + * Credits:Special thanks to @dietpepsi for adding this problem and creating all test + * cases. + ***************************************************************************************/ + + + +/* + * Solution + * -------- + * + * 1) We split the `K` to two parts : `i` & `k-i` 0<= i <= k + * + * 2) Find the max number for both arrays with giving the length `i` and `k-i` + * - sub1 = FindMaxNumber(num1, len=i); + * - sub2 = FindMaxNumber(num2, len=k-i); + * Here, we need use stack-way to solve find the max number. + * + * 3) Merge two arrays + * - solution = Merge(sub1, sub2); + * Here, we need be careful if a two number are same which one we need to take. For examples: + * [6,7] + * [6,0,4] + * 5 + * + * [2,5,6,4,4,0] + * [7,3,8,0,6,5,7,6,2] + * 15 + * + * 4) compare with the last solution + * - result = max(result, solution); + * + * + */ + + +class Solution { +public: + vector maxNumber(vector& nums1, vector& nums2, int k) { + vector result; + int len1 = nums1.size(); + int len2 = nums2.size(); + for (int i=0; i<=k; i++){ + if (len1 < i || len2 < k-i) continue; + vector sub1 = findMaxSubArray(nums1, i); + vector sub2 = findMaxSubArray(nums2, k-i); + vector merge = mergeTwoArrays(sub1, sub2); + if (compareTwoArray(merge, 0, result, 0)) { + result = merge; + } + } + return result; + } + + + bool compareTwoArray(vector& nums1, int start1, vector& nums2, int start2) { + int n1 = nums1.size(); + int n2 = nums2.size(); + for(; start1 nums2[start2]) return true; + if (nums1[start1] < nums2[start2]) return false; + } + //if num1 still have numbers, return true, else return false + return start1 < nums1.size(); + } + + vector mergeTwoArrays(vector& nums1, vector& nums2) { + vector result; + int len1 = nums1.size(); + int len2 = nums2.size(); + int pos1=0, pos2=0; + while ( pos1 < len1 && pos2 < len2 ){ + // Be careful if two numbers are equal. consider the following case + // case 1: [6,7], [6,0,4] - we have same item - 6 + // case 2: [4,0,2], [2,0,3,1] - we have same item - 0 + // which one we need to merge? + // We need compare the rest of array. + if (nums1[pos1] == nums2[pos2]){ + result.push_back( compareTwoArray(nums1, pos1+1, nums2, pos2+1) ? + nums1[pos1++] : nums2[pos2++]); + }else { + result.push_back(nums1[pos1] > nums2[pos2] ? + nums1[pos1++] : nums2[pos2++]); + } + } + + if (pos1 < len1){ + result.insert(result.end(), nums1.begin()+pos1, nums1.end()); + } + if (pos2 < len2) { + result.insert(result.end(), nums2.begin()+pos2, nums2.end()); + } + + return result; + } + + + // using a stack method to find the max sub-array + // k <= nums.size() + vector findMaxSubArray(vector& nums, int k) { + int len = nums.size(); + if ( k >= len ) return nums; + vector result(k, 0); + int idx = 0; // the postion for result array + for (int i=0; i the last element of result[], + // and we still have enough numbers, + // then pop up the item + while (idx>0 && k - idx < len - i && result[idx-1] < nums[i]) { + idx--; + } + //push the number into the result[] + if (idx < k) { + result[idx++] = nums[i]; + } + } + return result; + } + +}; diff --git a/algorithms/cpp/editDistance/editDistance.cpp b/algorithms/cpp/editDistance/editDistance.cpp index ec5612658..776e9661a 100644 --- a/algorithms/cpp/editDistance/editDistance.cpp +++ b/algorithms/cpp/editDistance/editDistance.cpp @@ -75,7 +75,7 @@ using namespace std; * "" 0 1 2 3 4 5 * a 1 0 1 2 3 4 * b 2 1 0 1 2 3 - * b 3 2 1 1 1 2 + * b 3 2 1 1 2 2 * */ int min(int x, int y, int z) { diff --git a/algorithms/cpp/expressionAddOperators/ExpressionAddOperators.cpp b/algorithms/cpp/expressionAddOperators/ExpressionAddOperators.cpp new file mode 100644 index 000000000..573d4fd26 --- /dev/null +++ b/algorithms/cpp/expressionAddOperators/ExpressionAddOperators.cpp @@ -0,0 +1,81 @@ +// Source : https://leetcode.com/problems/expression-add-operators/ +// Author : Hao Chen +// Date : 2016-01-16 + +/*************************************************************************************** + * + * Given a string that contains only digits 0-9 and a target value, return all + * possibilities to add binary operators (not unary) +, -, or * between the digits so + * they evaluate to the target value. + * + * Examples: + * "123", 6 -> ["1+2+3", "1*2*3"] + * "232", 8 -> ["2*3+2", "2+3*2"] + * "105", 5 -> ["1*0+5","10-5"] + * "00", 0 -> ["0+0", "0-0", "0*0"] + * "3456237490", 9191 -> [] + * + * Credits:Special thanks to @davidtan1890 for adding this problem and creating all + * test cases. + ***************************************************************************************/ + + +class Solution { +public: + vector addOperators(string num, int target) { + vector result; + if (num.size() == 0) return result; + helper(num, target, result, "", 0, 0, 0, ' '); + return result; + } + + //DFS algorithm + void helper(const string &num, const int target, //`num` and `target` never change + vector& result, // the array store all of the answers + string solution, //the current potential answer. + int idx, // the current index of `num` array + long long val, // the current value we calculated so far + long long prev, // the lastest value we used for calculation, which used for operation prioirty adjustment + char preop ) // the latest "+" or "-" operation, which used for operation prioirty adjustment + { + + if (target == val && idx == num.size()){ + result.push_back(solution); + return; + } + if (idx == num.size()) return; + + string n; + long long v=0; + for(int i=idx; i &num) { } // The array is rotated - // Spli it into two part, the minimal value must be the rotated part + // Split it into two part, the minimal value must be the rotated part // if the left part is rotated, warch the left part if (num[low] > num [mid]){ diff --git a/algorithms/cpp/flattenNestedListIterator/FlattenNestedListIterator.cpp b/algorithms/cpp/flattenNestedListIterator/FlattenNestedListIterator.cpp new file mode 100644 index 000000000..e62484864 --- /dev/null +++ b/algorithms/cpp/flattenNestedListIterator/FlattenNestedListIterator.cpp @@ -0,0 +1,74 @@ +// Source : https://leetcode.com/problems/flatten-nested-list-iterator/ +// Author : Hao Chen +// Date : 2016-05-30 + +/*************************************************************************************** + * + * Given a nested list of integers, implement an iterator to flatten it. + * + * Each element is either an integer, or a list -- whose elements may also be integers + * or other lists. + * + * Example 1: + * Given the list [[1,1],2,[1,1]], + * + * By calling next repeatedly until hasNext returns false, the order of elements + * returned by next should be: [1,1,2,1,1]. + * + * Example 2: + * Given the list [1,[4,[6]]], + * + * By calling next repeatedly until hasNext returns false, the order of elements + * returned by next should be: [1,4,6]. + ***************************************************************************************/ + +/** + * // This is the interface that allows for creating nested lists. + * // You should not implement it, or speculate about its implementation + * class NestedInteger { + * public: + * // Return true if this NestedInteger holds a single integer, rather than a nested list. + * bool isInteger() const; + * + * // 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 getInteger() const; + * + * // 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 + * const vector &getList() const; + * }; + */ +class NestedIterator { +private: + vector v; + int index; + void flatten(vector &nestedList) { + for (auto item : nestedList){ + if (item.isInteger()){ + v.push_back( item.getInteger() ); + }else{ + flatten( item.getList() ); + } + } + } +public: + NestedIterator(vector &nestedList) { + flatten(nestedList); + index = 0; + } + + int next() { + return v[index++]; + } + + bool hasNext() { + return (index < v.size() ); + } +}; + +/** + * Your NestedIterator object will be instantiated and called as such: + * NestedIterator i(nestedList); + * while (i.hasNext()) cout << i.next(); + */ diff --git a/algorithms/cpp/houseRobber/houseRobberIII.cpp b/algorithms/cpp/houseRobber/houseRobberIII.cpp new file mode 100644 index 000000000..8bb4aeadf --- /dev/null +++ b/algorithms/cpp/houseRobber/houseRobberIII.cpp @@ -0,0 +1,88 @@ +// Source : https://leetcode.com/problems/house-robber-iii/ +// Author : Calinescu Valentin +// Date : 2016-04-29 + +/*************************************************************************************** + * + * The thief has found himself a new place for his thievery again. There is only one + * entrance to this area, called the "root." Besides the root, each house has one and + * only one parent house. After a tour, the smart thief realized that "all houses in + * this place forms a binary tree". It will automatically contact the police if two + * directly-linked houses were broken into on the same night. + * + * Determine the maximum amount of money the thief can rob tonight without alerting the + * police. + * + * Example 1: + * 3 + * / \ + * 2 3 + * \ \ + * 3 1 + * Maximum amount of money the thief can rob = 3 + 3 + 1 = 7. + * Example 2: + * 3 + * / \ + * 4 5 + * / \ \ + * 1 3 1 + * Maximum amount of money the thief can rob = 4 + 5 = 9. + * Credits: + * Special thanks to @dietpepsi for adding this problem and creating all test cases. + * + ***************************************************************************************/ +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ + /* + * Solution 1 - O(N log N) + * ========= + * + * We can use a recursive function that computes the solution for every node of the tree + * using the previous solutions calculated for the left and right subtrees. At every step + * we have 2 options: + * + * 1) Take the value of the current node + the solution of the left and right subtrees of + * each of the left and right children of the current node. + * 2) Take the solution of the left and right subtrees of the current node, skipping over + * its value. + * + * This way we can make sure that we do not pick 2 adjacent nodes. + * + * If we implemented this right away we would get TLE. Thus, we need to optimize the + * algorithm. One key observation would be that we only need to compute the solution for + * a certain node once. We can use memoization to calculate every value once and then + * retrieve it when we get subsequent calls. As the header of the recursive function + * doesn't allow additional parameters we can use a map to link every node(a pointer) to + * its solution(an int). For every call the map lookup of an element and its insertion + * take logarithmic time and there are a constant number of calls for each node. Thus, the + * algorithm takes O(N log N) time to finish. + * + */ +class Solution { +public: + map dict; + int rob(TreeNode* root) { + if(root == NULL) + return 0; + else if(dict.find(root) == dict.end()) + { + int lwith = rob(root->left); + int rwith = rob(root->right); + int lwithout = 0, rwithout = 0; + if(root->left != NULL) + lwithout = rob(root->left->left) + rob(root->left->right); + if(root->right != NULL) + rwithout = rob(root->right->left) + rob(root->right->right); + //cout << lwith << " " << rwith << " " << lwithout << " " << rwithout << '\n'; + dict[root] = max(root->val + lwithout + rwithout, lwith + rwith); + } + return dict[root]; + } +}; diff --git a/algorithms/cpp/increasingTripletSubsequence/increasingTripletSubsequence.cpp b/algorithms/cpp/increasingTripletSubsequence/increasingTripletSubsequence.cpp new file mode 100644 index 000000000..a53f3d7bd --- /dev/null +++ b/algorithms/cpp/increasingTripletSubsequence/increasingTripletSubsequence.cpp @@ -0,0 +1,43 @@ +// Source : https://leetcode.com/problems/increasing-triplet-subsequence/ +// Author : Calinescu Valentin +// Date : 2016-02-27 + +/*************************************************************************************** + * + * Given an unsorted array return whether an increasing subsequence of length 3 exists + * or not in the array. + * + * Formally the function should: + * Return true if there exists i, j, k + * such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false. + * Your algorithm should run in O(n) time complexity and O(1) space complexity. + * + * Examples: + * Given [1, 2, 3, 4, 5], + * return true. + * + * Given [5, 4, 3, 2, 1], + * return false. + * + ***************************************************************************************/ +class Solution { +public: + bool increasingTriplet(vector& nums) { + bool solution = false; + if(nums.size()) + { + int first = nums[0]; + int second = 0x7fffffff; //MAX_INT so we can always find something smaller than it + for(int i = 1; i < nums.size() && !solution; i++) + { + if(nums[i] > second) + solution = true; + else if(nums[i] > first && nums[i] < second) + second = nums[i]; + else if(nums[i] < first) + first = nums[i]; + } + } + return solution; + } +}; diff --git a/algorithms/cpp/integerBreak/IntegerBreak.cpp b/algorithms/cpp/integerBreak/IntegerBreak.cpp new file mode 100644 index 000000000..21f78bb82 --- /dev/null +++ b/algorithms/cpp/integerBreak/IntegerBreak.cpp @@ -0,0 +1,46 @@ +// Source : https://leetcode.com/problems/integer-break/ +// Author : Hao Chen +// Date : 2016-05-29 + +/*************************************************************************************** + * + * Given a positive integer n, break it into the sum of at least two positive integers + * and maximize the product of those integers. Return the maximum product you can get. + * + * For example, given n = 2, return 1 (2 = 1 + 1); given n = 10, return 36 (10 = 3 + 3 + * + 4). + * + * Note: you may assume that n is not less than 2. + * + * There is a simple O(n) solution to this problem. + * You may check the breaking results of n ranging from 7 to 10 to discover the + * regularities. + * + * Credits:Special thanks to @jianchao.li.fighter for adding this problem and creating + * all test cases. + ***************************************************************************************/ + +class Solution { +public: + // As the hint said, checking the n with ranging from 7 to 10 to discover the regularities. + // n = 7, 3*4 = 12 + // n = 8, 3*3*2 = 18 + // n = 9, 3*3*3 = 27 + // n = 10, 3*3*4 = 36 + // n = 11, 3*3*3*2 = 54 + // + // we can see we can break the number by 3 if it is greater than 4; + // + int integerBreak(int n) { + if ( n == 2 ) return 1; + if ( n == 3 ) return 2; + int result = 1; + while( n > 4 ) { + result *= 3; + n -= 3; + } + result *= n; + return result; + } +}; + diff --git a/algorithms/cpp/intersectionOfTwoArrays/intersectionOfTwoArrays.cpp b/algorithms/cpp/intersectionOfTwoArrays/intersectionOfTwoArrays.cpp new file mode 100644 index 000000000..0b20ecc77 --- /dev/null +++ b/algorithms/cpp/intersectionOfTwoArrays/intersectionOfTwoArrays.cpp @@ -0,0 +1,31 @@ +// Source : https://leetcode.com/problems/intersection-of-two-arrays/ +// Author : Calinescu Valentin +// Date : 2016-05-20 + +/*************************************************************************************** + * + * Given two arrays, write a function to compute their intersection. + * + * Example: + * Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2]. + * + * Note: + * Each element in the result must be unique. + * The result can be in any order. + * + ***************************************************************************************/ +class Solution { +public: + set inter1, inter2;//we use sets so as to avoid duplicates + vector solution; + vector intersection(vector& nums1, vector& nums2) { + for(int i = 0; i < nums1.size(); i++) + inter1.insert(nums1[i]);//get all of the unique elements in nums1 sorted + for(int i = 0; i < nums2.size(); i++) + if(inter1.find(nums2[i]) != inter1.end())//search inter1 in O(logN) + inter2.insert(nums2[i]);//populate the intersection set + for(set::iterator it = inter2.begin(); it != inter2.end(); ++it) + solution.push_back(*it);//copy the set into a vector + return solution; + } +}; diff --git a/algorithms/cpp/intersectionOfTwoArraysII/intersectionOfTwoArraysII.cpp b/algorithms/cpp/intersectionOfTwoArraysII/intersectionOfTwoArraysII.cpp new file mode 100644 index 000000000..3b20ef791 --- /dev/null +++ b/algorithms/cpp/intersectionOfTwoArraysII/intersectionOfTwoArraysII.cpp @@ -0,0 +1,61 @@ +// Source : https://leetcode.com/problems/intersection-of-two-arrays-ii/ +// Author : Calinescu Valentin +// Date : 2016-05-22 + +/*************************************************************************************** + * + * Given two arrays, write a function to compute their intersection. + * + * Example: + * Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2, 2]. + * + * Note: + * Each element in the result should appear as many times as it shows in both arrays. + * The result can be in any order. + * + * Follow up: + * What if the given array is already sorted? How would you optimize your algorithm? + * What if nums1's size is small compared to num2's size? Which algorithm is better? + * What if elements of nums2 are stored on disk, and the memory is limited such that you + * cannot load all elements into the memory at once? + * + ***************************************************************************************/ + + /* Solution + * -------- + * + * Follow up: + * + * 1)If the given array is already sorted we can skip the sorting. + * + * 2)If nums1 is significantly smaller than nums2 we can only sort nums1 and then binary + * search every element of nums2 in nums1 with a total complexity of (MlogN) or if nums2 + * is already sorted we can search every element of nums1 in nums2 in O(NlogM) + * + * 3)Just like 2), we can search for every element in nums2, thus having an online + * algorithm. + */ + +class Solution { // O(NlogN + MlogM) +public: + vector intersect(vector& nums1, vector& nums2) { + sort(nums1.begin(), nums1.end());//we sort both vectors in order to intersect + sort(nums2.begin(), nums2.end());//them later in O(N + M), where N = nums1.size() + vector solution; //M = nums2.size() + int index = 0; + bool finished = false; + for(int i = 0; i < nums1.size() && !finished; i++) + { + while(index < nums2.size() && nums1[i] > nums2[index])//we skip over the + index++;//smaller elements in nums2 + if(index == nums2.size())//we have reached the end of nums2 so we have no more + finished = true;//elements to add to the intersection + else if(nums1[i] == nums2[index])//we found a common element + { + solution.push_back(nums1[i]); + index++; + } + } + return solution; + } +}; diff --git a/algorithms/cpp/longestIncreasingPathInAMatrix/LongestIncreasingPathInAMatrix.cpp b/algorithms/cpp/longestIncreasingPathInAMatrix/LongestIncreasingPathInAMatrix.cpp new file mode 100644 index 000000000..a7e6a4423 --- /dev/null +++ b/algorithms/cpp/longestIncreasingPathInAMatrix/LongestIncreasingPathInAMatrix.cpp @@ -0,0 +1,81 @@ +// Source : https://leetcode.com/problems/longest-increasing-path-in-a-matrix/ +// Author : Hao Chen +// Date : 2016-01-21 + +/*************************************************************************************** + * + * Given an integer matrix, find the length of the longest increasing path. + * + * From each cell, you can either move to four directions: left, right, up or down. You + * may NOT move diagonally or move outside of the boundary (i.e. wrap-around is not + * allowed). + * + * Example 1: + * + * nums = [ + * [>9, 9, 4], + * [>6, 6, 8], + * [>2,>1, 1] + * ] + * + * Return 4 + * + * The longest increasing path is [1, 2, 6, 9]. + * + * Example 2: + * + * nums = [ + * [>3,>4,>5], + * [ 3, 2,>6], + * [ 2, 2, 1] + * ] + * + * Return 4 + * + * The longest increasing path is [3, 4, 5, 6]. Moving diagonally is not allowed. + * + * Credits:Special thanks to @dietpepsi for adding this problem and creating all test + * cases. + ***************************************************************************************/ + + +class Solution { +public: + int longestIncreasingPath(vector>& matrix) { + int result = 0; + int row = matrix.size(); + int col = row ? matrix[0].size() : 0; + vector> path = vector>(row, vector(col, 0)); + for (int r = 0; r < row; r++) { + for (int c = 0; c < col; c++) { + result = max(result, helper(matrix, path, row, col, r, c)); + } + } + return result; + } + + int helper(vector>& matrix, vector>& path, const int row, const int col, int r, int c) { + + if (path[r][c]>0) return path[r][c]; + + int maxPath = 0; + + int tmp = matrix[r][c]; + matrix[r][c]=INT_MIN; + if (r < row-1 && tmp < matrix[r+1][c]) { + maxPath = max(maxPath, helper(matrix, path, row, col, r+1, c)); + } + if (c < col-1 && tmp < matrix[r][c+1]) { + maxPath = max(maxPath, helper(matrix, path, row, col, r, c+1)); + } + if (r > 0 && tmp < matrix[r-1][c]) { + maxPath = max(maxPath, helper(matrix, path, row, col, r-1, c)); + } + if (c > 0 && tmp < matrix[r][c-1]) { + maxPath = max(maxPath, helper(matrix, path, row, col, r, c-1)); + } + matrix[r][c] = tmp; + path[r][c] = maxPath + 1; + return path[r][c]; + } +}; diff --git a/algorithms/cpp/longestIncreasingSubsequence/longestIncreasingSubsequence.cpp b/algorithms/cpp/longestIncreasingSubsequence/longestIncreasingSubsequence.cpp index 70a7fadab..30c65e9f4 100644 --- a/algorithms/cpp/longestIncreasingSubsequence/longestIncreasingSubsequence.cpp +++ b/algorithms/cpp/longestIncreasingSubsequence/longestIncreasingSubsequence.cpp @@ -1,5 +1,5 @@ // Source : https://leetcode.com/problems/longest-increasing-subsequence/ -// Author : Calinescu Valentin +// Author : Calinescu Valentin, Hao Chen // Date : 2015-11-06 /*************************************************************************************** @@ -22,6 +22,30 @@ * ***************************************************************************************/ + + +// O(n^2) - dynamic programming +class Solution { +public: + int lengthOfLIS(vector& nums) { + + int len = nums.size(); + int maxLen = 0; + vector dp(len, 1); + + for (int i=0; i > &matrix) { if (matrix.size()<=0 || matrix[0].size()<=0) return 0; int row = matrix.size(); int col = matrix[0].size(); - vector< vector > heights(row, vector col); + vector< vector > heights(row, vector(col)); int maxArea = 0; for(int i=0; i findMinHeightTrees(int n, vector>& edges) { + //corner case + if ( n <= 1 ) return {0}; + + //construct a edges search data stucture + vector> graph(n); + for (auto e : edges) { + graph[e.first].insert(e.second); + graph[e.second].insert(e.first); + } + + //find all of leaf nodes + vector current; + for (int i=0; i next; + for (int node : current) { + for (int neighbor : graph[node]) { + graph[neighbor].erase(node); + if (graph[neighbor].size() == 1) next.push_back(neighbor); + } + } + if (next.empty()) break; + current = next; + } + return current; + } + +}; diff --git a/algorithms/cpp/nextPermutation/nextPermutation.cpp b/algorithms/cpp/nextPermutation/nextPermutation.cpp index 404c4b86c..8d4ab294e 100644 --- a/algorithms/cpp/nextPermutation/nextPermutation.cpp +++ b/algorithms/cpp/nextPermutation/nextPermutation.cpp @@ -33,11 +33,11 @@ * 2 1 3 4 * ... * - * The pattern as below: + * The pattern can be descripted as below: * - * 1) find the first place which num[i-1] < num[i] - * 2) find the first number from n-1 to i which >= num[i-1] - * 3) swap the 2) num with num[i-1] + * 1) from n-1 to 0, find the first place [i-1] which num[i-1] < num[i] + * 2) from n-1 to i, find the first number from n-1 to i which >= num[i-1] + * 3) swap the 2) num with the num[i-1] * 4) sort the sub-array [i, n) //actuall sort is fine as well * * For example: diff --git a/algorithms/cpp/oddEvenLinkedList/OddEvenLinkedList.cpp b/algorithms/cpp/oddEvenLinkedList/OddEvenLinkedList.cpp new file mode 100644 index 000000000..6a206978e --- /dev/null +++ b/algorithms/cpp/oddEvenLinkedList/OddEvenLinkedList.cpp @@ -0,0 +1,53 @@ +// Source : https://leetcode.com/problems/odd-even-linked-list/ +// Author : Hao Chen +// Date : 2016-01-16 + +/*************************************************************************************** + * + * Given a singly linked list, group all odd nodes together followed by the even nodes. + * Please note here we are talking about the node number and not the value in the nodes. + * + * You should try to do it in place. The program should run in O(1) space complexity + * and O(nodes) time complexity. + * + * Example: + * Given 1->2->3->4->5->NULL, + * return 1->3->5->2->4->NULL. + * + * Note: + * The relative order inside both the even and odd groups should remain as it was in + * the input. + * The first node is considered odd, the second node even and so on ... + * + * Credits:Special thanks to @aadarshjajodia for adding this problem and creating all + * test cases. + ***************************************************************************************/ + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode(int x) : val(x), next(NULL) {} + * }; + */ +class Solution { +public: + ListNode* oddEvenList(ListNode* head) { + if (!head) return head; + ListNode* pOdd = head; + ListNode* p = head->next; + ListNode* pNext = NULL; + while(p && (pNext=p->next)) { + + p->next = pNext->next; + pNext->next = pOdd->next; + pOdd->next = pNext; + + p = p->next; + pOdd = pOdd->next; + + } + return head; + } +}; diff --git a/algorithms/cpp/patchingArray/PatchingArray.cpp b/algorithms/cpp/patchingArray/PatchingArray.cpp new file mode 100644 index 000000000..18b7ee51b --- /dev/null +++ b/algorithms/cpp/patchingArray/PatchingArray.cpp @@ -0,0 +1,115 @@ +// Source : https://leetcode.com/problems/patching-array/ +// Author : Hao Chen +// Date : 2016-03-01 + +/*************************************************************************************** + * + * Given a sorted positive integer array nums and an integer n, add/patch elements to + * the array such that any number in range [1, n] inclusive can be formed by the sum of + * some elements in the array. Return the minimum number of patches required. + * + * Example 1: + * nums = [1, 3], n = 6 + * Return 1. + * + * Combinations of nums are [1], [3], [1,3], which form possible sums of: 1, 3, 4. + * Now if we add/patch 2 to nums, the combinations are: [1], [2], [3], [1,3], [2,3], + * [1,2,3]. + * Possible sums are 1, 2, 3, 4, 5, 6, which now covers the range [1, 6]. + * So we only need 1 patch. + * + * Example 2: + * nums = [1, 5, 10], n = 20 + * Return 2. + * The two patches can be [2, 4]. + * + * Example 3: + * nums = [1, 2, 2], n = 5 + * Return 0. + * + * Credits:Special thanks to @dietpepsi for adding this problem and creating all test + * cases. + ***************************************************************************************/ + + +class Solution { +public: + int minPatches(vector& nums, int n) { + return minPatches_02(nums, n); + return minPatches_01(nums, n); + } + + + // Greedy Algorithm + // (Assume the array is sorted already) + // + // Let do some observation at first, + // + // 1) if we have [1,2] then we can cover 1, 2, 3 + // 2) if we have [1,2,3] then we can cover 1,2,3,4,5,6 + // So, it looks we can simply add all of nums together, then we can find out max number we can reach. + // + // 3) if we have [1,2,5], we can see + // 3.1) [1,2] can cover 1,2,3, but we cannot reach 4, + // 3.2) then we patch 4, then we have [1,2,4] which can cover 1,2,3(1+2),4,5(1+4),6(2+4), 7(1+2+4) + // 3.3) we can see [1,2,4] can reach to 7 - sum all of them + // 3.4) then [1,2,4,5], we can reach to 12 - 1,2,3,4,5,6,7,8(1+2+5),9(4+5),10(1+4+5), 11(2+4+5), 12(1+2+4+5) + // + // So, we can have figure out our solution + // + // 0) considering the `n` we need to cover. + // 1) maintain a variable we are trying to patch, suppose named `try_patch` + // 2) if `try_patch` >= nums[i] then, we just keep add the current array item, + // and set the `try_patch` to the next patch candidate number - `sum+1` + // 3) if `try_patch` < nums[i], which means we need to patch. + // + int minPatches_01(vector& nums, int n) { + long covered = 0; //avoid integer overflow + int patch_cnt = 0; + int i = 0; + while (i= nums[i]) { + covered += nums[i]; + i++; + } else { // if the `try_patch` cannot cover the current item, then we find the number we need to patch + patch_cnt++; + //cout << "patch " << try_patch << endl; + covered = covered + try_patch; + } + + if (covered >=n) break; + } + //for the case - [1], 7 + //the above while-loop just process all of the numbers in the array, + //but we might not reach the goal, so, we need keep patching. + while (covered < n) { + int try_patch = covered + 1; + patch_cnt++; + //cout << "patch " << try_patch << endl; + covered = covered + try_patch; + } + return patch_cnt; + } + + + //The following solution just re-organizes the solution above, and make it shorter + int minPatches_02(vector& nums, int n) { + long covered = 0; + int patch_cnt = 0; + int i = 0; + while ( covered < n){ + if (i0 ? (1162261467%n==0) : false; + } + + void init(unordered_map& power ){ + int p = 1; + power[1]=true; + while(1){ + p *= 3; + power[p] = true; + if (p > INT_MAX/3) break; + + } + } + bool isPowerOfThree01(int n) { + static unordered_map power; + if (power.size()==0) init(power); + return power.find(n) != power.end(); + } + + bool isPowerOfThree_loop(int n) { + for(;n>0;n /= 3){ + if (n==1 || n==3) return true; + if (n%3 != 0) return false; + } + return false; + } + + bool isPowerOfThree_recursive(int n) { + if ( n == 1 || n == 3) return true; + if ( n==0 || n%3 != 0 ) return false; + return isPowerOfThree_recursive(n/3); + } +}; diff --git a/algorithms/cpp/reverseString/ReverseString.cpp b/algorithms/cpp/reverseString/ReverseString.cpp new file mode 100644 index 000000000..c0f41088b --- /dev/null +++ b/algorithms/cpp/reverseString/ReverseString.cpp @@ -0,0 +1,24 @@ +// Source : https://leetcode.com/problems/reverse-string/ +// Author : Hao Chen +// Date : 2016-05-29 + +/*************************************************************************************** + * + * Write a function that takes a string as input and returns the string reversed. + * + * Example: + * Given s = "hello", return "olleh". + ***************************************************************************************/ + +class Solution { +public: + string reverseString(string s) { + int len = s.size(); + for (int i=0; i vowels; + set vows; + vows.insert('a'); + vows.insert('A'); + vows.insert('e'); + vows.insert('E'); + vows.insert('i'); + vows.insert('I'); + vows.insert('o'); + vows.insert('O'); + vows.insert('u'); + vows.insert('U'); + string result; + for(int i = 0; i < s.size(); i++) + { + if(vows.find(s[i]) != vows.end()) + vowels.push_back(s[i]); + } + for(int i = 0; i < s.size(); i++) + { + if(vows.find(s[i]) != vows.end()) + { + result.push_back(vowels.back()); + vowels.pop_back(); + } + else + result.push_back(s[i]); + } + return result; + } +}; diff --git a/algorithms/cpp/reverseWordsInAString/reverseWordsInAString.cpp b/algorithms/cpp/reverseWordsInAString/reverseWordsInAString.cpp index b3f4d6147..89edd1062 100644 --- a/algorithms/cpp/reverseWordsInAString/reverseWordsInAString.cpp +++ b/algorithms/cpp/reverseWordsInAString/reverseWordsInAString.cpp @@ -1,5 +1,5 @@ // Source : https://oj.leetcode.com/problems/reverse-words-in-a-string/ -// Author : Hao Chen +// Author : Hao Chen, Siwei Xu // Date : 2014-06-16 /********************************************************************************** @@ -24,9 +24,13 @@ **********************************************************************************/ #include +#include +#include +#include #include #include #include +#include // for std::reverse using namespace std; void reverseWords(string &s) { @@ -71,7 +75,82 @@ void reverseWords(string &s) { } cout << "[" << s << "]" < -- Handwaving +void reverseWords2(string &s) { + if (s.length() == 0) return; + + string result = ""; + if (s[s.length()-1] == ' ') { + int last = s.find_last_not_of(' ') + 1; + s.erase(last, s.length() - last); + } + + int first = s.find_first_not_of(' ', 0); + while (first != string::npos) { + int wend = s.find(' ', first); // word end + if (wend == string::npos) wend = s.length(); + + string word = s.substr(first, wend - first); + reverse(word.begin(), word.end()); + result += word; + + first = s.find_first_not_of(' ', wend); // next word + if (first == string::npos) break; + + result += ' '; + } + reverse(result.begin(), result.end()); + s.swap(result); +} + + +// C solution in O(1) space +void reverse(char *b, char *e) { + for (--e; e - b > 0; b++, e--) { + char t = *b; + *b = *e; + *e = t; + } +} + +void reverseWords(char *s) { + char *p = s, *ws = NULL, *last = s; + + while (*p && *p == ' ') p++; // skip leading space + ws = p; + + for ( ; *p; p++) { + while (*p && *p != ' ') p++; // find word end + + reverse(ws, p); + strncpy(last, ws, p-ws); + last += (p-ws); + + while (*p && *p == ' ') p++; // for next word + ws = p; + + if (*p == '\0') break; + *last++ = ' '; + } + reverse(s, last); + *last = '\0'; +} + +void test() { +#define TEST(str) do { \ + char* s = strdup(str); \ + printf("\"%s\" => ", s); \ + reverseWords(s); \ + printf("\"%s\"\n\n", s); \ + free(s); \ + } while (0) + + TEST(" the blue sky is blue "); + TEST(" "); +} + + main() { string s; @@ -85,4 +164,5 @@ main() s="i love cpp"; reverseWords(s); + test(); } diff --git a/algorithms/cpp/singleNumber/singleNumber.III.cpp b/algorithms/cpp/singleNumber/singleNumber.III.cpp new file mode 100644 index 000000000..d2f86bd52 --- /dev/null +++ b/algorithms/cpp/singleNumber/singleNumber.III.cpp @@ -0,0 +1,94 @@ +// Source : https://leetcode.com/problems/single-number-iii/ +// Author : Hao Chen +// Date : 2016-01-16 + +/*************************************************************************************** + * + * Given an array of numbers nums, in which exactly two elements appear only once and + * all the other elements appear exactly twice. Find the two elements that appear only + * once. + * + * For example: + * + * Given nums = [1, 2, 1, 3, 2, 5], return [3, 5]. + * + * Note: + * + * The order of the result is not important. So in the above example, [5, 3] is also + * correct. + * Your algorithm should run in linear runtime complexity. Could you implement it using + * only constant space complexity? + * + * Credits:Special thanks to @jianchao.li.fighter for adding this problem and creating + * all test cases. + ***************************************************************************************/ + + +/* + * For the problem - only one number appears once when all other numbers appears exactly twice. + * + * We know, we can XOR all of the array elements. Since X^X is zero, and X^0 is X, + * so all of the duplicated number will zero themselves out, and the only number would be the result. + * + * However, this solution cannot be applied directly to finding two numbers that appear once each. + * + * Suppose that these numbers that appear once are X and Y, and all other numbers appear twice. + * If we decide to XOR all the array's elements, the overall result would actually be `X^Y`. + * + * Unfortunately, there is no way to extract J and K out of their XOR. + * + * But since X and Y are different, we are sure that X^Y is different than zero. + * + * This information is valuable in sense that we know pieces of information that differ. + * If we pick up any bit that is 1 in X XOR Y, we can use it as a mask to test each element of the array. + * + * Obviously, that mask will be the discriminator between X and Y - + * + * Only one of them will have value 1 at that particular position. + * + * + * Now that we have the mask with exactly one bit set to 1, we can walk through the array once again. + * + * But this time we are going to maintain two XORed results. + * + * - One for numbers that have bit 1 at the mask's position + * - Another for numbers that have bit 0 at that position + * + * In this way, we are sure that all duplicates will go into the same pile. + * + * But likewise, we are sure that X and Y will go into separate piles. + * + * So, the overall result is that + * - the first XORed result will be equal to X + * - and the second XORed result will be equal to Y + * +*/ + +class Solution { +public: + vector singleNumber(vector& nums) { + int allxor = 0; + for (int n : nums) { + allxor ^= n; + } + int mask = 1; + while ( (mask & allxor) == 0 ) { + mask <<= 1; + } + + int zero = 0; + int one = 0; + for (int n : nums) { + if (n & mask ){ + one ^= n; + }else { + zero ^= n; + } + } + + vector result; + result.push_back(zero); + result.push_back(one); + return result; + } +}; diff --git a/algorithms/cpp/topKFrequentElements/topKFrequentElements.cpp b/algorithms/cpp/topKFrequentElements/topKFrequentElements.cpp new file mode 100644 index 000000000..245c3ba0b --- /dev/null +++ b/algorithms/cpp/topKFrequentElements/topKFrequentElements.cpp @@ -0,0 +1,65 @@ +// Source : https://leetcode.com/problems/top-k-frequent-elements/ +// Author : Calinescu Valentin +// Date : 2016-05-02 + +/*************************************************************************************** + * + * Given a non-empty array of integers, return the k most frequent elements. + * + * For example, + * Given [1,1,1,2,2,3] and k = 2, return [1,2]. + * + * Note: + * You may assume k is always valid, 1 ≤ k ≤ number of unique elements. + * Your algorithm's time complexity must be better than O(n log n), where n is the + * array's size. + * + ***************************************************************************************/ + +class Solution { +public: + struct element//structure consisting of every distinct number in the vector, + //along with its frequency + { + int number, frequency; + bool operator < (const element arg) const + { + return frequency < arg.frequency; + } + }; + priority_queue sol;//we use a heap so we have all of the elements sorted + //by their frequency + vector solution; + + vector topKFrequent(vector& nums, int k) { + sort(nums.begin(), nums.end()); + int i = 1; + for(; i < nums.size(); i++) + { + int freq = 1; + while(i < nums.size() && nums[i] == nums[i - 1]) + { + i++; + freq++; + } + element el; + el.number = nums[i - 1]; + el.frequency = freq; + sol.push(el); + } + if(i == nums.size())//if we have 1 distinct element as the last + { + element el; + el.number = nums[nums.size() - 1]; + el.frequency = 1; + sol.push(el); + } + while(k)//we extract the first k elements from the heap + { + solution.push_back(sol.top().number); + sol.pop(); + k--; + } + return solution; + } +}; diff --git a/algorithms/cpp/wiggleSubsequence/wiggleSubsequence.cpp b/algorithms/cpp/wiggleSubsequence/wiggleSubsequence.cpp new file mode 100644 index 000000000..5631e5713 --- /dev/null +++ b/algorithms/cpp/wiggleSubsequence/wiggleSubsequence.cpp @@ -0,0 +1,88 @@ +// Source : https://leetcode.com/problems/wiggle-subsequence/ +// Author : Calinescu Valentin +// Date : 2016-08-08 + +/*************************************************************************************** + * + * A sequence of numbers is called a wiggle sequence if the differences between + * successive numbers strictly alternate between positive and negative. The first + * difference (if one exists) may be either positive or negative. A sequence with fewer + * than two elements is trivially a wiggle sequence. + * + * For example, [1,7,4,9,2,5] is a wiggle sequence because the differences (6,-3,5,-7,3) + * are alternately positive and negative. In contrast, [1,4,7,2,5] and [1,7,4,5,5] are + * not wiggle sequences, the first because its first two differences are positive and + * the second because its last difference is zero. + * + * Given a sequence of integers, return the length of the longest subsequence that is a + * wiggle sequence. A subsequence is obtained by deleting some number of elements + * (eventually, also zero) from the original sequence, leaving the remaining elements in + * their original order. + * + * Examples: + * Input: [1,7,4,9,2,5] + * Output: 6 + * The entire sequence is a wiggle sequence. + * + * Input: [1,17,5,10,13,15,10,5,16,8] + * Output: 7 + * There are several subsequences that achieve this length. One is [1,17,10,13,10,16,8]. + * + * Input: [1,2,3,4,5,6,7,8,9] + * Output: 2 + * + * Follow up: + * Can you do it in O(n) time? + * + ***************************************************************************************/ + + /* Solution + * -------- + * 1) O(N) + * + * We notice that adding a new number to an existing subsequence means finding one that + * is smaller or bigger than the previous number, according to the difference between the + * previous number and the number before that as we always need to alternate between increasing + * and decreasing subsequences. If we encounter increasing or decreasing sequences of 2 or + * more consecutive numbers we can treat the entire subsequence as a number, because that way + * we can always be sure we don't miss any solution, as finding a number smaller than any + * number of an increasing subsequence is guaranteed to be smaller than the biggest number + * in the subsequence. Thus, we can only check the difference between consecutive numbers. + * + * Follow up: + * + * The time complexity is already O(N). + */ +class Solution { +public: + int wiggleMaxLength(vector& nums) { + int solution = 0;//if we have an empty vector the solution is 0 + if(nums.size()) + { + solution = 1; + int bigger = 0;//0 is the starting point to be followed by either an increasing or decreasing sequence + for(int i = 1; i < nums.size(); i++) + { + if(nums[i] == nums[i - 1]) + continue;//we can ignore duplicates as they can always be omitted + else if(nums[i] > nums[i - 1]) + { + if(bigger == 0 || bigger == 2) + { + bigger = 1;//1 means we now have an increasing sequence + solution++; + } + } + else //if(nums[i] < nums[i - 1]) + { + if(bigger == 0 || bigger == 1) + { + bigger = 2;//2 means we now have a decreasing sequence + solution++; + } + } + } + } + return solution; + } +}; diff --git a/algorithms/java/src/lruCache/LRUCache.java b/algorithms/java/src/lruCache/LRUCache.java new file mode 100644 index 000000000..5ea5c2950 --- /dev/null +++ b/algorithms/java/src/lruCache/LRUCache.java @@ -0,0 +1,45 @@ +/* +Analogous to the C++ solution at: +https://github.com/haoel/leetcode/blob/625ad10464701fc4177b9ef33c8ad052d0a7d984/algorithms/cpp/LRUCache/LRUCache.cpp +which uses linked list + hash map. But the Java stdlib provides LinkedHashMap +which already implements that for us, making this solution shorter. + +This could also be done by using, but that generates +some inheritance boilerplate, and ends up taking the same number of lines: +https://github.com/cirosantilli/haoel-leetcode/commit/ff04930b2dc31f270854e40b560723577c7b49fd +*/ + +import java.util.LinkedHashMap; +import java.util.Iterator; + +public class LRUCache { + + private int capacity; + private LinkedHashMap map; + + public LRUCache(int capacity) { + this.capacity = capacity; + this.map = new LinkedHashMap<>(); + } + + public int get(int key) { + Integer value = this.map.get(key); + if (value == null) { + value = -1; + } else { + this.set(key, value); + } + return value; + } + + public void set(int key, int value) { + if (this.map.containsKey(key)) { + this.map.remove(key); + } else if (this.map.size() == this.capacity) { + Iterator it = this.map.keySet().iterator(); + it.next(); + it.remove(); + } + map.put(key, value); + } +} diff --git a/algorithms/java/src/lruCache/LRUCacheTest.java b/algorithms/java/src/lruCache/LRUCacheTest.java new file mode 100644 index 000000000..b8166873e --- /dev/null +++ b/algorithms/java/src/lruCache/LRUCacheTest.java @@ -0,0 +1,49 @@ +import java.util.ArrayList; + +import org.junit.Test; +import static org.junit.Assert.*; + +public class LRUCacheTest { + + private LRUCache c; + + public LRUCacheTest() { + this.c = new LRUCache(2); + } + + @Test + public void testCacheStartsEmpty() { + assertEquals(c.get(1), -1); + } + + @Test + public void testSetBelowCapacity() { + c.set(1, 1); + assertEquals(c.get(1), 1); + assertEquals(c.get(2), -1); + c.set(2, 4); + assertEquals(c.get(1), 1); + assertEquals(c.get(2), 4); + } + + @Test + public void testCapacityReachedOldestRemoved() { + c.set(1, 1); + c.set(2, 4); + c.set(3, 9); + assertEquals(c.get(1), -1); + assertEquals(c.get(2), 4); + assertEquals(c.get(3), 9); + } + + @Test + public void testGetRenewsEntry() { + c.set(1, 1); + c.set(2, 4); + assertEquals(c.get(1), 1); + c.set(3, 9); + assertEquals(c.get(1), 1); + assertEquals(c.get(2), -1); + assertEquals(c.get(3), 9); + } +} diff --git a/scripts/comments.sh b/scripts/comments.sh index 1d518fe24..6fe2e15f2 100755 --- a/scripts/comments.sh +++ b/scripts/comments.sh @@ -1,7 +1,7 @@ #!/bin/bash set -e -AUTHOR="Hao Chen" +AUTHOR="NOBODY" LEETCODE_URL=https://leetcode.com/problems/ LEETCODE_NEW_URL=https://leetcode.com/problems/ LEETCODE_OLD_URL=https://oj.leetcode.com/problems/ @@ -23,6 +23,18 @@ function usage() echo -e "" } +function get_author_name() +{ + TRUE_CMD=`which true` + git=`type -P git || ${TRUE_CMD}` + if [ ! -z "${git}" ]; then + AUTHOR=`git config --get user.name` + else + AUTHOR=`whoami` + fi +} + + function detect_os() { platform='unknown' @@ -138,6 +150,9 @@ if [ ! -s $source_file ]; then echo "" > $source_file fi +#detect the author name +get_author_name; + #adding the Copyright Comments if ! grep -Fq "${COMMENT_TAG} Author :" $source_file ; then sed -i.bak '1i\'$'\n'"${COMMENT_TAG} Source : ${leetcode_url}"$'\n' $source_file @@ -160,14 +175,14 @@ fi # 2) the last two `sed` commands are used to add the comments tags case $FILE_EXT in .cpp ) xidel ${leetcode_url} -q -e "css('div.question-content')" | \ - grep -v ' ' | sed '/^$/N;/^\n$/D' | fold -w 85 -s |\ + grep -v ' ' | sed '/^$/N;/^\n$/D' | fold -w 85 -s |\ sed 's/^/ * /' | sed '1i\'$'\n'"/*$(printf '%.0s*' {0..85}) "$'\n' |\ sed '2i\'$'\n''!@#$%'$'\n' | sed 's/!@#$%/ */' | \ sed '$a\'$'\n'"*$(printf '%.0s*' {0..85})*/"$'\n'| \ sed 's/^*/ /' > /tmp/tmp.txt ;; .sh ) xidel ${leetcode_url} -q -e "css('div.question-content')" | \ - grep -v ' ' |sed '/^$/N;/^\n$/D' | fold -w 85 -s| \ + grep -v ' ' |sed '/^$/N;/^\n$/D' | fold -w 85 -s| \ sed 's/^/# /' | sed '1i\'$'\n'"#$(printf '%.0s#' {0..85}) "$'\n' | \ sed '2i\'$'\n''#'$'\n' | sed '$a\'$'\n'"#$(printf '%.0s#' {0..85})"$'\n'\ > /tmp/tmp.txt