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..594d50bb1 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,70 @@ LeetCode | # | Title | Solution | Difficulty | |---| ----- | -------- | ---------- | +|477|[Total Hamming Distance](https://leetcode.com/problems/total-hamming-distance/) | [C++](./algorithms/cpp/totalHammingDistance/totalHammingDistance.cpp)|Medium| +|415|[Add Strings](https://leetcode.com/problems/add-strings/) | [C++](./algorithms/cpp/addStrings/AddStrings.cpp)|Easy| +|414|[Third Maximum Number](https://leetcode.com/problems/third-maximum-number/) | [C++](./algorithms/cpp/thirdMaximumNumber/ThirdMaximumNumber.cpp)|Easy| +|413|[Arithmetic Slices](https://leetcode.com/problems/arithmetic-slices/) | [C++](./algorithms/cpp/arithmeticSlices/ArithmeticSlices.cpp)|Medium| +|412|[Fizz Buzz](https://leetcode.com/problems/fizz-buzz/) | [C++](./algorithms/cpp/fizzBuzz/FizzBuzz.cpp)|Easy| +|410|[Split Array Largest Sum](https://leetcode.com/problems/split-array-largest-sum/) | [C++](./algorithms/cpp/splitArrayLargestSum/SplitArrayLargestSum.cpp)|Hard| +|409|[Longest Palindrome](https://leetcode.com/problems/longest-palindrome/) | [C++](./algorithms/cpp/longestPalindrome/LongestPalindrome.cpp)|Easy| +|406|[Queue Reconstruction by Height](https://leetcode.com/problems/queue-reconstruction-by-height/) | [C++](./algorithms/cpp/queueReconstructionByHeight/QueueReconstructionByHeight.cpp)|Medium| +|405|[Convert a Number to Hexadecimal](https://leetcode.com/problems/convert-a-number-to-hexadecimal/) | [C++](./algorithms/cpp/convertANumberToHexadecimal/ConvertANumberToHexadecimal.cpp)|Easy| +|404|[Sum of Left Leaves](https://leetcode.com/problems/sum-of-left-leaves/) | [C++](./algorithms/cpp/sumOfLeftLeaves/SumOfLeftLeaves.cpp)|Easy| +|403|[Frog Jump](https://leetcode.com/problems/frog-jump/) | [C++](./algorithms/cpp/frogJump/FrogJump.cpp)|Hard| +|402|[Remove K Digits](https://leetcode.com/problems/remove-k-digits/) | [C++](./algorithms/cpp/removeKDigits/RemoveKDigits.cpp)|Medium| +|401|[Binary Watch](https://leetcode.com/problems/binary-watch/) | [C++](./algorithms/cpp/binaryWatch/BinaryWatch.cpp)|Easy| +|400|[Nth Digit](https://leetcode.com/problems/nth-digit/) | [C++](./algorithms/cpp/nthDigit/NthDigit.cpp)|Easy| +|399|[Evaluate Division](https://leetcode.com/problems/evaluate-division/) | [C++](./algorithms/cpp/evaluateDivision/EvaluateDivision.cpp)|Medium| +|398|[Random Pick Index](https://leetcode.com/problems/random-pick-index/) | [C++](./algorithms/cpp/randomPickIndex/RandomPickIndex.cpp)|Medium| +|397|[Integer Replacement](https://leetcode.com/problems/integer-replacement/) | [C++](./algorithms/cpp/integerReplacement/IntegerReplacement.cpp)|Medium| +|396|[Rotate Function](https://leetcode.com/problems/rotate-function/) | [C++](./algorithms/cpp/rotateFunction/RotateFunction.cpp)|Easy| +|395|[Longest Substring with At Least K Repeating Characters](https://leetcode.com/problems/longest-substring-with-at-least-k-repeating-characters/) | [C++](./algorithms/cpp/longestSubstringWithAtLeastKRepeatingCharacters/LongestSubstringWithAtLeastKRepeatingCharacters.cpp)|Medium| +|394|[Decode String](https://leetcode.com/problems/decode-string/) | [C++](./algorithms/cpp/decodeString/DecodeString.cpp)|Medium| +|393|[UTF-8 Validation](https://leetcode.com/problems/utf-8-validation/) | [C++](./algorithms/cpp/UTF8Validation/UTF8Validation.cpp)|Medium| +|392|[Is Subsequence](https://leetcode.com/problems/is-subsequence/) | [C++](./algorithms/cpp/isSubsequence/IsSubsequence.cpp)|Medium| +|391|[Perfect Rectangle](https://leetcode.com/problems/perfect-rectangle/) | [C++](./algorithms/cpp/perfectRectangle/PerfectRectangle.cpp)|Hard| +|390|[Elimination Game](https://leetcode.com/problems/elimination-game/) | [C++](./algorithms/cpp/eliminationGame/EliminationGame.cpp)|Medium| +|389|[Find the Difference](https://leetcode.com/problems/find-the-difference/) | [C++](./algorithms/cpp/findTheDifference/FindTheDifference.cpp)|Easy| +|388|[Longest Absolute File Path](https://leetcode.com/problems/longest-absolute-file-path/) | [C++](./algorithms/cpp/longestAbsoluteFilePath/LongestAbsoluteFilePath.cpp)|Medium| +|387|[First Unique Character in a String](https://leetcode.com/problems/first-unique-character-in-a-string/) | [C++](./algorithms/cpp/firstUniqueCharacterInAString/FirstUniqueCharacterInAString.cpp)|Easy| +|386|[Lexicographical Numbers](https://leetcode.com/problems/lexicographical-numbers/) | [C++](./algorithms/cpp/lexicographicalNumbers/LexicographicalNumbers.cpp)|Medium| +|385|[Mini Parser](https://leetcode.com/problems/mini-parser/) | [C++](./algorithms/cpp/miniParser/MiniParser.cpp)|Medium| +|384|[Shuffle an Array](https://leetcode.com/problems/shuffle-an-array/) | [C++](./algorithms/cpp/shuffleAnArray/ShuffleAnArray.cpp)|Medium| +|383|[Ransom Note](https://leetcode.com/problems/ransom-note/) | [C++](./algorithms/cpp/ransomNote/RansomNote.cpp)|Easy| +|382|[Linked List Random Node](https://leetcode.com/problems/linked-list-random-node/) | [C++](./algorithms/cpp/linkedListRandomNode/LinkedListRandomNode.cpp)|Medium| +|381|[Insert Delete GetRandom O(1) - Duplicates allowed](https://leetcode.com/problems/insert-delete-getrandom-o1-duplicates-allowed/) | [C++](./algorithms/cpp/insertDeleteGetRandom/InsertDeleteGetrandomO1DuplicatesAllowed.cpp)|Hard| +|380|[Insert Delete GetRandom O(1)](https://leetcode.com/problems/insert-delete-getrandom-o1/) | [C++](./algorithms/cpp/insertDeleteGetRandom/InsertDeleteGetrandomO1.cpp)|Hard| +|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/intersectionOfTwoArrays/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| +|332|[Reconstruct Itinerary](https://leetcode.com/problems/reconstruct-itinerary/) | [C++](./algorithms/cpp/reconstructItinerary/ReconstructItinerary.cpp)|Medium| +|331|[Verify Preorder Serialization of a Binary Tree](https://leetcode.com/problems/verify-preorder-serialization-of-a-binary-tree/) | [C++](./algorithms/cpp/verifyPreorderSerializationOfABinaryTree/VerifyPreorderSerializationOfABinaryTree.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| +|324|[Wiggle Sort II](https://leetcode.com/problems/wiggle-sort-ii/) | [C++](./algorithms/cpp/wiggleSort/WiggleSort.II.cpp)|Medium| +|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| +|318|[Maximum Product of Word Lengths](https://leetcode.com/problems/maximum-product-of-word-lengths/) | [C++](./algorithms/cpp/maximumProductOfWordLengths/MaximumProductOfWordLengths.cpp)|Medium| +|316|[Remove Duplicate Letters](https://leetcode.com/problems/remove-duplicate-letters/) | [C++](./algorithms/cpp/removeDuplicateLetters/RemoveDuplicateLetters.cpp)|Hard| |315|[Count of Smaller Numbers After Self](https://leetcode.com/problems/count-of-smaller-numbers-after-self/) | [C++](./algorithms/cpp/countOfSmallerNumbersAfterSelf/countOfSmallerNumbersAfterSelf.cpp)|Hard| +|313|[Super Ugly Number](https://leetcode.com/problems/super-ugly-number/) | [C++](./algorithms/cpp/superUglyNumber/SuperUglyNumber.cpp)|Medium| +|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 +87,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 +96,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 +179,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..354584fad 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--; @@ -81,7 +81,7 @@ vector > threeSum(vector &num) { high--; } else{ //skip the duplication - while(low& data) { + int i = 0; + while ( i < data.size() ) { + if ( (data[i] & 0x80) == 0 ){ + i++; + continue; + } + + int len = 0; + if ( (data[i] & 0xE0) == 0xC0 ) { // checking 110xxxxx + len = 2; + }else if ( (data[i] & 0xF0) == 0xE0) { // checking 1110xxxx + len = 3; + }else if ( (data[i] & 0xF8) == 0xF0) { // checking 11110xxx + len = 4; + }else { + return false; + } + + + for (int j=i+1; j < i+len; j++) { //checking 10xxxxxx + if ( (data[j] & 0xC0) != 0x80 ) { + return false; + } + } + + i += len ; + + if (i > data.size()) { + return false; + } + + } + return true; + } +}; diff --git a/algorithms/cpp/addStrings/AddStrings.cpp b/algorithms/cpp/addStrings/AddStrings.cpp new file mode 100644 index 000000000..32b6734bb --- /dev/null +++ b/algorithms/cpp/addStrings/AddStrings.cpp @@ -0,0 +1,48 @@ +// Source : https://leetcode.com/problems/add-strings/ +// Author : Hao Chen +// Date : 2016-11-12 + +/*************************************************************************************** + * + * Given two non-negative numbers num1 and num2 represented as string, return the sum + * of num1 and num2. + * + * Note: + * + * The length of both num1 and num2 is + * Both num1 and num2 contains only digits 0-9. + * Both num1 and num2 does not contain any leading zero. + * You must not use any built-in BigInteger library or convert the inputs to integer + * directly. + ***************************************************************************************/ + +class Solution { +public: + string addStrings(string num1, string num2) { + string& longstr = ( num1.size() >= num2.size() ? num1 : num2 ); + string& shortstr = ( num1.size() < num2.size() ? num1 : num2 ); + + int longlen = longstr.size(); + int shortlen = shortstr.size(); + + char carry = 0; + int i, j; + + string result; + for (i = longlen-1, j=shortlen-1; i>=0; i--, j--) { + int add = 0; + if (j>=0) { + add = longstr[i] + shortstr[j] - 2 * '0' + carry; + }else{ + add = longstr[i] - '0' + carry; + } + carry = add/10; + result = char('0' + add % 10) + result; + } + + if (carry) { + result = '1' + result; + } + return result; + } +}; diff --git a/algorithms/cpp/arithmeticSlices/ArithmeticSlices.cpp b/algorithms/cpp/arithmeticSlices/ArithmeticSlices.cpp new file mode 100644 index 000000000..dc7c9fa05 --- /dev/null +++ b/algorithms/cpp/arithmeticSlices/ArithmeticSlices.cpp @@ -0,0 +1,72 @@ +// Source : https://leetcode.com/problems/arithmetic-slices/ +// Author : Hao Chen +// Date : 2016-11-13 + +/*************************************************************************************** + * + * A sequence of number is called arithmetic if it consists of at least three elements + * and if the difference between any two consecutive elements is the same. + * + * For example, these are arithmetic sequence: + * 1, 3, 5, 7, 9 + * 7, 7, 7, 7 + * 3, -1, -5, -9 + * + * The following sequence is not arithmetic. 1, 1, 2, 5, 7 + * + * A zero-indexed array A consisting of N numbers is given. A slice of that array is + * any pair of integers (P, Q) such that 0 + * + * A slice (P, Q) of array A is called arithmetic if the sequence: + * A[P], A[p + 1], ..., A[Q - 1], A[Q] is arithmetic. In particular, this means + * that P + 1 + * + * The function should return the number of arithmetic slices in the array A. + * + * Example: + * + * A = [1, 2, 3, 4] + * + * return: 3, for 3 arithmetic slices in A: [1, 2, 3], [2, 3, 4] and [1, 2, 3, 4] + * itself. + ***************************************************************************************/ + +class Solution { +public: + // + // It's easy to find out how many 3-length slices in an arithmetic array with N length. + // + // len = 3, then 1 slices, sum(1) + // len = 4, then 3 slices, sum(1,2) - TWO 3-length slices + ONE 4-length slice + // len = 5, then 6 slices, sum(1,2,3) - THREE 3-length slices + TWO 4-length slices + ONE 5-length slice + // len = 6, then 10 slices, sum(1,2,3,4) - ... + // len = 7, then 15 slices, sum(1,2,3,4,5) - .. + // + // So, with N length arithmetic array, there are Sum[1, N-3+1] 3-length slices + // + // And, we know the formula sum from 1 to n is: + // + // n * ( n + 1 ) + // sum [1, n] = --------------- + // 2 + // Then, we could have the solution - O(n) Time with O(1) Space + // + + int sum1toN(int n) { + return n * (n+1) / 2; + } + + int numberOfArithmeticSlices(vector& A) { + int result = 0; + int len = 0; // the current length of arithmetic + for (int i=2; i>& result) { + if (solution > max){ + return; + } + if (k == 0) { + char tmp[5] = ""; + if (zero) { + sprintf(tmp, "%02d", solution); + }else{ + sprintf(tmp, "%d", solution); + } + result[nLight].push_back(tmp); + return; + } + for (int i=start; i<=nLED-k; i++) { + solution += pow(2, i); + combination(nLED, nLight, max, zero, i+1, k-1, solution, result); + solution -= pow(2, i); + } + } + + void generate_combination(int nLED, int max, bool zero, vector>& result) { + for (int i=0; i>& vv) { + for(auto v : vv) { + cout << "[ "; + for (auto i : v) { + cout << i << " "; + } + cout << "]" << endl; + } + } + +private: + vector> hour; + vector> mins; + +public: + + Solution():hour(4, vector()), mins(6, vector()){ + generate_combination(4, 11, false, hour); + //print(hour); + //[ 0 ] + //[ 1 2 4 8 ] + //[ 3 5 9 6 10 ] + //[ 7 11 ] + + + generate_combination(6, 59, true, mins); + //print(mins); + //[ 00 ] + //[ 01 02 04 08 16 32 ] + //[ 03 05 09 17 33 06 10 18 34 12 20 36 24 40 48 ] + //[ 07 11 19 35 13 21 37 25 41 49 14 22 38 26 42 50 28 44 52 56 ] + //[ 15 23 39 27 43 51 29 45 53 57 30 46 54 58 ] + //[ 31 47 55 59 ] + } + + vector readBinaryWatch(int num) { + + vector result; + for (int i = 0; i <= 3 && i <= num; i++) { + if (num - i > 5) { + continue; + } + for (auto h : hour[i]) { + for (auto m : mins[num - i]) { + result.push_back( h + ":" + m ); + } + } + + } + return result; + } +}; 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/convertANumberToHexadecimal/ConvertANumberToHexadecimal.cpp b/algorithms/cpp/convertANumberToHexadecimal/ConvertANumberToHexadecimal.cpp new file mode 100644 index 000000000..654e50e40 --- /dev/null +++ b/algorithms/cpp/convertANumberToHexadecimal/ConvertANumberToHexadecimal.cpp @@ -0,0 +1,56 @@ +// Source : https://leetcode.com/problems/convert-a-number-to-hexadecimal/ +// Author : Hao Chen +// Date : 2016-11-12 + +/*************************************************************************************** + * + * Given an integer, write an algorithm to convert it to hexadecimal. For negative + * integer, two’s complement method is used. + * + * Note: + * + * All letters in hexadecimal (a-f) must be in lowercase. + * The hexadecimal string must not contain extra leading 0s. If the number is zero, it + * is represented by a single zero character '0'; otherwise, the first character in the + * hexadecimal string will not be the zero character. + * The given number is guaranteed to fit within the range of a 32-bit signed integer. + * You must not use any method provided by the library which converts/formats the + * number to hex directly. + * + * Example 1: + * + * Input: + * 26 + * + * Output: + * "1a" + * + * Example 2: + * + * Input: + * -1 + * + * Output: + * "ffffffff" + ***************************************************************************************/ + +class Solution { +public: + + string toHex(int num) { + + if (num == 0) return "0"; + + unsigned int x = num; + + string result; + for(;x > 0; x/=16) { + int n = x % 16; + char c; + if (n < 10) c = n + '0'; + else c = 'a' + n - 10 ; + result = c + result; + } + return result; + } +}; 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/decodeString/DecodeString.cpp b/algorithms/cpp/decodeString/DecodeString.cpp new file mode 100644 index 000000000..677818981 --- /dev/null +++ b/algorithms/cpp/decodeString/DecodeString.cpp @@ -0,0 +1,105 @@ +// Source : https://leetcode.com/problems/decode-string/ +// Author : Hao Chen +// Date : 2016-09-08 + +/*************************************************************************************** + * + * Given an encoded string, return it's decoded string. + * + * The encoding rule is: k[encoded_string], where the encoded_string inside the square + * brackets is being repeated exactly k times. Note that k is guaranteed to be a + * positive integer. + * + * You may assume that the input string is always valid; No extra white spaces, square + * brackets are well-formed, etc. + * + * Furthermore, you may assume that the original data does not contain any digits and + * that digits are only for those repeat numbers, k. For example, there won't be input + * like 3a or 2[4]. + * + * Examples: + * + * s = "3[a]2[bc]", return "aaabcbc". + * s = "3[a2[c]]", return "accaccacc". + * s = "2[abc]3[cd]ef", return "abcabccdcdcdef". + ***************************************************************************************/ + +class Solution { +public: + string decodeString(string s) { + if (!isValid(s)) return ""; + + stack _stack; + stack _nstack; + + string result; + string tmp; + int n=0; + for (int i=0; i0; n--) { + tmp += _stack.top(); + } + _stack.pop(); + _nstack.pop(); + if ( ! _stack.empty() ) { + _stack.top() += tmp; + }else { + result += tmp; + } + } else { + if ( ! _stack.empty() ) { + _stack.top() += s[i]; + } else { + result += s[i]; + } + + } + } + + return result; + } + +private: + + //only check the following rules: + // 1) the number must be followed by '[' + // 2) the '[' and ']' must be matched. + bool isValid(string& s) { + stack _stack; + for (int i=0; i='0' && ch<='9'); + } +}; + 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/eliminationGame/EliminationGame.cpp b/algorithms/cpp/eliminationGame/EliminationGame.cpp new file mode 100644 index 000000000..386c985fd --- /dev/null +++ b/algorithms/cpp/eliminationGame/EliminationGame.cpp @@ -0,0 +1,41 @@ +// Source : https://leetcode.com/problems/elimination-game +// Author : Hao Chen +// Date : 2016-09-07- + +/********************************************************************************** + * + * There is a list of sorted integers from 1 to n. Starting from left to right, remove the first number and every other + * number afterward until you reach the end of the list. + * + * Repeat the previous step again, but this time from right to left, remove the right most number and every other number + * from the remaining numbers. + * + * We keep repeating the steps again, alternating left to right and right to left, until a single number remains. + * + * Find the last number that remains starting with a list of length n. + * + * Example: + * + * Input: + * n = 9, + * 1 2 3 4 5 6 7 8 9 + * 2 4 6 8 + * 2 6 + * 6 + * + * Output: + * 6 +**********************************************************************************/ + +class Solution { +public: + int lastRemaining(int n) { + int start = 1, step = 1; + while (n > 1) { + start += step + (n-2)/2 * 2*step; + n /= 2; + step *= -2; + } + return start; + } +}; diff --git a/algorithms/cpp/evaluateDivision/EvaluateDivision.cpp b/algorithms/cpp/evaluateDivision/EvaluateDivision.cpp new file mode 100644 index 000000000..bd6d06ba8 --- /dev/null +++ b/algorithms/cpp/evaluateDivision/EvaluateDivision.cpp @@ -0,0 +1,93 @@ +// Source : https://leetcode.com/problems/evaluate-division/ +// Author : Hao Chen +// Date : 2016-11-05 + +/*************************************************************************************** + * + * Equations are given in the format A / B = k, where A and B are variables + * represented as strings, and k is a real number (floating point number). Given some + * queries, return the answers. If the answer does not exist, return -1.0. + * + * Example: + * Given a / b = 2.0, b / c = 3.0. queries are: a / c = ?, b / a = ?, a / e = ?, a + * / a = ?, x / x = ? . return [6.0, 0.5, -1.0, 1.0, -1.0 ]. + * + * The input is: vector> equations, vector& values, + * vector> queries , where equations.size() == values.size(), and + * the values are positive. This represents the equations. Return vector. + * + * According to the example above: + * equations = [ ["a", "b"], ["b", "c"] ], + * values = [2.0, 3.0], + * queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ]. + * + * The input is always valid. You may assume that evaluating the queries will result in + * no division by zero and there is no contradiction. + ***************************************************************************************/ + +class Solution { +private: + bool dfs( unordered_map>& m, + unordered_map& visited, + string& start, string& end, double& res ) { + + if ( m.find(start) == m.end() || m.find(end) == m.end() ) return false; + if ( start == end ) return true; + + for (auto it = m[start].begin(); it != m[start].end(); ++it) { + + auto key = it->first; + auto value = it->second; + + // already visited, skip it. + if (visited.find(key) != visited.end() ) { + continue; + } + + visited[key] = true; + double old = res; + res *= value; + + if (dfs(m, visited, key, end, res)) { + return true; + } + //didn't find the result, reset the current result, and go to next one + res = old; + visited.erase(key); + } + + return false; + } +public: + vector calcEquation(vector> equations, + vector& values, + vector> queries) { + + unordered_map> m; + for(int i=0; i result; + for(auto q : queries) { + string start = q.first; + string end = q.second; + + unordered_map visited; + visited[start] = true; + double res = 1.0; + + if(dfs(m, visited, start, end, res)) { + result.push_back(res); + } else { + result.push_back(-1.0); + } + } + + return result; + } +}; 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/findTheDifference/FindTheDifference.cpp b/algorithms/cpp/findTheDifference/FindTheDifference.cpp new file mode 100644 index 000000000..5e51e4f0e --- /dev/null +++ b/algorithms/cpp/findTheDifference/FindTheDifference.cpp @@ -0,0 +1,38 @@ +// Source : https://leetcode.com/problems/find-the-difference/ +// Author : Hao Chen +// Date : 2016-09-08 + +/*************************************************************************************** + * + * Given two strings s and t which consist of only lowercase letters. + * + * String t is generated by random shuffling string s and then add one more letter at a + * random position. + * + * Find the letter that was added in t. + * + * Example: + * + * Input: + * s = "abcd" + * t = "abcde" + * + * Output: + * e + * + * Explanation: + * 'e' is the letter that was added. + ***************************************************************************************/ + +class Solution { +public: + char findTheDifference(string s, string t) { + unordered_map m; + for(auto c : s) m[c]++; + for(auto c : t) { + m[c]--; + if (m[c] < 0) return c; + } + return '\0'; + } +}; diff --git a/algorithms/cpp/firstUniqueCharacterInAString/FirstUniqueCharacterInAString.cpp b/algorithms/cpp/firstUniqueCharacterInAString/FirstUniqueCharacterInAString.cpp new file mode 100644 index 000000000..29081bb3d --- /dev/null +++ b/algorithms/cpp/firstUniqueCharacterInAString/FirstUniqueCharacterInAString.cpp @@ -0,0 +1,55 @@ +// Source : https://leetcode.com/problems/first-unique-character-in-a-string/ +// Author : Hao Chen +// Date : 2016-08-23 + +/*************************************************************************************** + * + * Given a string, find the first non-repeating character in it and return it's index. + * If it doesn't exist, return -1. + * + * Examples: + * + * s = "leetcode" + * return 0. + * + * s = "loveleetcode", + * return 2. + * + * Note: You may assume the string contain only lowercase letters. + ***************************************************************************************/ + +class Solution { +public: + int firstUniqChar(string s) { + //As the question mentioned, there only have lower case chars, + //so the MAX_CHAR can be defined as 26, but I want this algorithm be more general for all ASCII + #define MAX_CHAR 256 + #define NOT_FOUND -1 + #define DUPLICATION -2 + + // initlize all chars status to NOT_FOUND + int pos_map[MAX_CHAR]; + memset(pos_map, NOT_FOUND,sizeof(pos_map)); + + // if it is the first time to find, set the status to its postion + // if it is the second time to find, set the status to duplication + // if it has already duplicated, do nothing + for (int i=0; i= 0 ) { + pos_map[s[i]] = DUPLICATION; + }else if ( pos_map[s[i]] == NOT_FOUND ) { + pos_map[s[i]] = i; + } + } + + // find the lowest postion + int pos = INT_MAX; + for (auto item : pos_map) { + cout << item << ","; + if (item >= 0 && item < pos) { + pos = item; + } + } + return pos == INT_MAX ? -1 : pos; + } +}; diff --git a/algorithms/cpp/fizzBuzz/FizzBuzz.cpp b/algorithms/cpp/fizzBuzz/FizzBuzz.cpp new file mode 100644 index 000000000..f4ec548e7 --- /dev/null +++ b/algorithms/cpp/fizzBuzz/FizzBuzz.cpp @@ -0,0 +1,91 @@ +// Source : https://leetcode.com/problems/fizz-buzz/ +// Author : Hao Chen +// Date : 2016-11-13 + +/*************************************************************************************** + * + * Write a program that outputs the string representation of numbers from 1 to n. + * + * But for multiples of three it should output “Fizz” instead of the number and for the + * multiples of five output “Buzz”. For numbers which are multiples of both three and + * five output “FizzBuzz”. + * + * Example: + * + * n = 15, + * + * Return: + * [ + * "1", + * "2", + * "Fizz", + * "4", + * "Buzz", + * "Fizz", + * "7", + * "8", + * "Fizz", + * "Buzz", + * "11", + * "Fizz", + * "13", + * "14", + * "FizzBuzz" + * ] + ***************************************************************************************/ + +class Solution { +public: + vector fizzBuzz_old_school_way(int n) { + vector result; + for (int i=1; i<=n; i++) { + if ( i%3 == 0 && i%5 ==0 ) { + result.push_back("FizzBuzz"); + }else if (i%3 == 0) { + result.push_back("Fizz"); + }else if (i%5 == 0) { + result.push_back("Buzz"); + }else{ + result.push_back(std::to_string(i)); + } + } + return result; + } + + + class FizzBuzz { + public: + FizzBuzz() : x(0) {} + + string operator()() { + x++; + if ( x%3 == 0 && x%5 ==0 ) { + return ("FizzBuzz"); + }else if (x%3 == 0) { + return ("Fizz"); + }else if (x%5 == 0) { + return("Buzz"); + } + return std::to_string(x); + } + + private: + int x; + }; + + vector fizzBuzz_cpp_way(int n) { + vector result(n); + generate(result.begin(), result.end(), FizzBuzz()); + return result; + } + + vector fizzBuzz(int n) { + + //both method has same performance + + if (rand() % 2 == 0) { + return fizzBuzz_cpp_way(n); + } + return fizzBuzz_old_school_way(n); + } +}; 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/frogJump/FrogJump.cpp b/algorithms/cpp/frogJump/FrogJump.cpp new file mode 100644 index 000000000..8bd302b89 --- /dev/null +++ b/algorithms/cpp/frogJump/FrogJump.cpp @@ -0,0 +1,125 @@ +// Source : https://leetcode.com/problems/frog-jump/ +// Author : Hao Chen +// Date : 2016-11-12 + +/*************************************************************************************** + * + * A frog is crossing a river. The river is divided into x 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 is able to cross the river by landing on the last stone. Initially, the + * frog is on the first stone and assume the first jump must be 1 unit. + * + * If the frog's last jump was k units, then its next jump must be either k - 1, k, or + * k + 1 units. Note that the frog can only jump in the forward direction. + * + * Note: + * + * The number of stones is ≥ 2 and is + * Each stone's position will be a non-negative integer 31. + * The first stone's position is always 0. + * + * Example 1: + * + * [0,1,3,5,6,8,12,17] + * + * There are a total of 8 stones. + * The first stone at the 0th unit, second stone at the 1st unit, + * third stone at the 3rd unit, and so on... + * The last stone at the 17th unit. + * + * Return true. The frog can jump to the last stone by jumping + * 1 unit to the 2nd stone, then 2 units to the 3rd stone, then + * 2 units to the 4th stone, then 3 units to the 6th stone, + * 4 units to the 7th stone, and 5 units to the 8th stone. + * + * Example 2: + * + * [0,1,2,3,4,8,9,11] + * + * Return false. There is no way to jump to the last stone as + * the gap between the 5th and 6th stone is too large. + ***************************************************************************************/ + +class Solution { +public: + bool canCross_recursion(vector& stones, int curr, int last_jump) { + for(int i=curr+1; i last_jump + 1) return false; + + if (i == stones.size() - 1 || canCross_recursion(stones, i, next_jump)) return true; + } + return false; + } + + bool canCross_recursion_with_cache(vector& stones, int curr, int last_jump, + unordered_map>& cache) + { + //check the cache is hitted ? + if (cache.find(curr) != cache.end() && cache[curr].find(last_jump)!=cache[curr].end()) { + return cache[curr][last_jump]; + } + + for(int i=curr+1; i last_jump + 1) break; + if (i == stones.size() - 1 || canCross_recursion_with_cache(stones, i, next_jump, cache)) { + cache[curr][last_jump] = true; + return true; + } + } + cache[curr][last_jump] = false; + return false; + } + + bool canCross_non_recursion(vector& stones) { + + // the `jumps` map store the all possible `last jumps` + unordered_map> jumps = {{0, {0}}}; + + for(int i=0; i& stones) { + + //Burst Force solution -- accepted ~500ms + return canCross_non_recursion(stones); + + //DFS with cache solution - accepted ~160ms + unordered_map> cache; + return canCross_recursion_with_cache(stones, 0, 0, cache); + + // Time Limit Error + return canCross_recursion(stones, 0, 0); + + } +}; 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/insertDeleteGetRandom/InsertDeleteGetrandomO1.cpp b/algorithms/cpp/insertDeleteGetRandom/InsertDeleteGetrandomO1.cpp new file mode 100644 index 000000000..07a0bde1d --- /dev/null +++ b/algorithms/cpp/insertDeleteGetRandom/InsertDeleteGetrandomO1.cpp @@ -0,0 +1,98 @@ +// Source : https://leetcode.com/problems/insert-delete-getrandom-o1/ +// Author : Hao Chen +// Date : 2016-08-25 + +/*************************************************************************************** + * + * Design a data structure that supports all following operations in average O(1) time. + * + * insert(val): Inserts an item val to the set if not already present. + * remove(val): Removes an item val from the set if present. + * getRandom: Returns a random element from current set of elements. Each element must + * have the same probability of being returned. + * + * Example: + * + * // Init an empty set. + * RandomizedSet randomSet = new RandomizedSet(); + * + * // Inserts 1 to the set. Returns true as 1 was inserted successfully. + * randomSet.insert(1); + * + * // Returns false as 2 does not exist in the set. + * randomSet.remove(2); + * + * // Inserts 2 to the set, returns true. Set now contains [1,2]. + * randomSet.insert(2); + * + * // getRandom should return either 1 or 2 randomly. + * randomSet.getRandom(); + * + * // Removes 1 from the set, returns true. Set now contains [2]. + * randomSet.remove(1); + * + * // 2 was already in the set, so return false. + * randomSet.insert(2); + * + * // Since 1 is the only number in the set, getRandom always return 1. + * randomSet.getRandom(); + ***************************************************************************************/ + + +class RandomizedSet { +public: + /** Initialize your data structure here. */ + RandomizedSet() { + srand(time(NULL)); + } + + /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */ + bool insert(int val) { + if ( find(val) ) return false; + data.push_back(val); + valpos[val] = data.size() - 1; + return true; + } + + /** Removes a value from the set. Returns true if the set contained the specified element. */ + bool remove(int val) { + if ( !find(val) ) return false; + + /* + * Tricky + * ------ + * 1) Copy the data from the last one to the place need be removed. + * 2) Remove the last one. + */ + int _idx = valpos[val]; + int _val = data.back(); + + data[_idx] = _val; + valpos[_val] = _idx; + + valpos.erase(val); + data.pop_back(); + return true; + } + + /** Get a random element from the set. */ + int getRandom() { + return data[ rand() % data.size() ]; + } + +private: + unordered_map valpos; //value position map + vector data; + bool find(int val) { + return (valpos.find(val) != valpos.end()); + } + +}; + +/** + * Your RandomizedSet object will be instantiated and called as such: + * RandomizedSet obj = new RandomizedSet(); + * bool param_1 = obj.insert(val); + * bool param_2 = obj.remove(val); + * int param_3 = obj.getRandom(); + */ diff --git a/algorithms/cpp/insertDeleteGetRandom/InsertDeleteGetrandomO1DuplicatesAllowed.cpp b/algorithms/cpp/insertDeleteGetRandom/InsertDeleteGetrandomO1DuplicatesAllowed.cpp new file mode 100644 index 000000000..3ae8de9b2 --- /dev/null +++ b/algorithms/cpp/insertDeleteGetRandom/InsertDeleteGetrandomO1DuplicatesAllowed.cpp @@ -0,0 +1,102 @@ +// Source : https://leetcode.com/problems/insert-delete-getrandom-o1-duplicates-allowed/ +// Author : Hao Chen +// Date : 2016-08-25 + +/*************************************************************************************** + * + * Design a data structure that supports all following operations in average O(1) time. + * Note: Duplicate elements are allowed. + * + * insert(val): Inserts an item val to the collection. + * remove(val): Removes an item val from the collection if present. + * getRandom: Returns a random element from current collection of elements. The + * probability of each element being returned is linearly related to the number of same + * value the collection contains. + * + * Example: + * + * // Init an empty collection. + * RandomizedCollection collection = new RandomizedCollection(); + * + * // Inserts 1 to the collection. Returns true as the collection did not contain 1. + * collection.insert(1); + * + * // Inserts another 1 to the collection. Returns false as the collection contained 1. + * Collection now contains [1,1]. + * collection.insert(1); + * + * // Inserts 2 to the collection, returns true. Collection now contains [1,1,2]. + * collection.insert(2); + * + * // getRandom should return 1 with the probability 2/3, and returns 2 with the + * probability 1/3. + * collection.getRandom(); + * + * // Removes 1 from the collection, returns true. Collection now contains [1,2]. + * collection.remove(1); + * + * // getRandom should return 1 and 2 both equally likely. + * collection.getRandom(); + ***************************************************************************************/ + +class RandomizedCollection { +public: + /** Initialize your data structure here. */ + RandomizedCollection() { + srand(time(NULL)); + } + + /** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */ + bool insert(int val) { + data.push_back(val); + valpos[val].insert( data.size() - 1 ); + return (valpos[val].size() == 1); + } + + /** Removes a value from the collection. Returns true if the collection contained the specified element. */ + bool remove(int val) { + // not found + if (!find(val)) return false; + + + //same idea with non-duplication version, but need be careful with some edge case + int _idx = *(valpos[val].begin()); + int _val = data.back(); + + valpos[_val].insert(_idx); + data[_idx] = _val; + + valpos[val].erase(_idx); + if (valpos[val].size()==0){ + valpos.erase(val); + } + + data.pop_back(); + if ( _idx < data.size() ){ + valpos[_val].erase(data.size()); + valpos[_val].insert(_idx); + } + + return true; + } + + /** Get a random element from the collection. */ + int getRandom() { + return data[ rand() % data.size() ]; + } +private: + unordered_map> valpos; //value position map + vector data; + bool find(int val) { + return (valpos.find(val) != valpos.end()); + } + +}; + +/** + * Your RandomizedCollection object will be instantiated and called as such: + * RandomizedCollection obj = new RandomizedCollection(); + * bool param_1 = obj.insert(val); + * bool param_2 = obj.remove(val); + * int param_3 = obj.getRandom(); + */ 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/integerReplacement/IntegerReplacement.cpp b/algorithms/cpp/integerReplacement/IntegerReplacement.cpp new file mode 100644 index 000000000..8583482d7 --- /dev/null +++ b/algorithms/cpp/integerReplacement/IntegerReplacement.cpp @@ -0,0 +1,69 @@ +// Source : https://leetcode.com/problems/integer-replacement/ +// Author : Hao Chen +// Date : 2016-11-04 + +/*************************************************************************************** + * + * Given a positive integer n and you can do operations as follow: + * + * If n is even, replace n with n/2. + * If n is odd, you can replace n with either n + 1 or n - 1. + * + * What is the minimum number of replacements needed for n to become 1? + * + * Example 1: + * + * Input: + * 8 + * + * Output: + * 3 + * + * Explanation: + * 8 -> 4 -> 2 -> 1 + * + * Example 2: + * + * Input: + * 7 + * + * Output: + * 4 + * + * Explanation: + * 7 -> 8 -> 4 -> 2 -> 1 + * or + * 7 -> 6 -> 3 -> 2 -> 1 + ***************************************************************************************/ + +class Solution { +public: + + + int integerReplacement_recursion(int n) { + if ( n <= 1) return 0; // recursive exited point + if ( n == INT_MAX ) return 32; // special case to avoid integer overflow. + if ( n % 2 == 0 ) return integerReplacement(n/2) + 1; + return min( integerReplacement(n+1), integerReplacement(n-1) ) + 1; + } + + int integerReplacement_recursionWithCache(int n) { + static unordered_map cache; + //if hitted the cache, just return the result + if (cache.find(n) != cache.end()) return cache[n]; + + int result; + if ( n <= 1) return 0; // recursive exited point + if ( n == INT_MAX ) return 32; // special case to avoid integer overflow. + if ( n % 2 == 0 ) result = integerReplacement(n/2) + 1; + else result = min( integerReplacement(n+1), integerReplacement(n-1) ) + 1; + + //add into cache + cache[n] = result; + return result; + } + + int integerReplacement(int n) { + return integerReplacement_recursionWithCache(n); + } +}; diff --git a/algorithms/cpp/intersectionOfTwoArrays/intersectionOfTwoArrays.cpp b/algorithms/cpp/intersectionOfTwoArrays/intersectionOfTwoArrays.cpp new file mode 100644 index 000000000..88eaccba6 --- /dev/null +++ b/algorithms/cpp/intersectionOfTwoArrays/intersectionOfTwoArrays.cpp @@ -0,0 +1,60 @@ +// 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; + } +}; + +/* + * This Solution use one unordered_set + */ +class Solution2 { +public: + vector intersection(vector& nums1, vector& nums2) { + unordered_set hash_set(nums1.begin(), nums1.end()); + vector res ; + for (auto it& : nums2) { + if (hash_set.count(it)) { + res.push_back(it); + hash_set.erase(it); + } + } + return res; + } +}; + + + + + + + + + + + diff --git a/algorithms/cpp/intersectionOfTwoArrays/intersectionOfTwoArraysII.cpp b/algorithms/cpp/intersectionOfTwoArrays/intersectionOfTwoArraysII.cpp new file mode 100644 index 000000000..3b20ef791 --- /dev/null +++ b/algorithms/cpp/intersectionOfTwoArrays/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/isSubsequence/IsSubsequence.cpp b/algorithms/cpp/isSubsequence/IsSubsequence.cpp new file mode 100644 index 000000000..e2cd88371 --- /dev/null +++ b/algorithms/cpp/isSubsequence/IsSubsequence.cpp @@ -0,0 +1,50 @@ +// Source : https://leetcode.com/problems/is-subsequence/ +// Author : Hao Chen +// Date : 2016-09-08 + +/*************************************************************************************** + * + * Given a string s and a string t, check if s is subsequence of t. + * + * You may assume that there is only lower case English letters in both s and t. t is + * potentially a very long (length ~= 500,000) string, and s is a short string ( + * + * A subsequence of a string is a new string which 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 subsequence of "abcde" while + * "aec" is not). + * + * Example 1: + * s = "abc", t = "ahbgdc" + * + * Return true. + * + * Example 2: + * s = "axc", t = "ahbgdc" + * + * Return false. + * + * Follow up: + * If there are lots of incoming S, say S1, S2, ... , Sk where k >= 1B, and you want to + * check one by one to see if T has its subsequence. In this scenario, how would you + * change your code? + ***************************************************************************************/ + +class Solution { +public: + bool isSubsequence(string s, string t) { + if (s.size() <= 0) return true; + + int ps=0, pt=0; + while (pt < t.size()) { + if (s[ps] == t[pt]) { + ps++; pt++; + if (ps >= s.size()) return true; + }else { + pt++; + } + } + + return false; + } +}; diff --git a/algorithms/cpp/lexicographicalNumbers/LexicographicalNumbers.cpp b/algorithms/cpp/lexicographicalNumbers/LexicographicalNumbers.cpp new file mode 100644 index 000000000..779e61077 --- /dev/null +++ b/algorithms/cpp/lexicographicalNumbers/LexicographicalNumbers.cpp @@ -0,0 +1,109 @@ +// Source : https://leetcode.com/problems/lexicographical-numbers/ +// Author : Hao Chen +// Date : 2016-08-23 + +/*************************************************************************************** + * + * Given an integer n, return 1 - n in lexicographical order. + * + * For example, given 13, return: [1,10,11,12,13,2,3,4,5,6,7,8,9]. + * + * Please optimize your algorithm to use less time and space. The input size may be as + * large as 5,000,000. + ***************************************************************************************/ +class Solution { + +//Solution 1: convert the int to string for sort, Time complexity is high (Time Limited Error) +public: + vector lexicalOrder01(int n) { + vector result; + for (int i=1; i<=n; i++) { + result.push_back(i); + } + sort(result.begin(), result.end(), this->myComp); + return result; + } +private: + static bool myComp(int i,int j) { + static char si[32]={0}, sj[32]={0}; + sprintf(si, "%d\0", i); + sprintf(sj, "%d\0", j); + return (strcmp(si, sj)<0); + } + + +//Solution 2 : using recursive way to solution the problem, 540ms +public: + vector lexicalOrder02(int n) { + vector result; + for (int i=1; i<=n && i<=9; i++) { + result.push_back(i); + lexicalOrder_helper(i, n, result); + } + return result; + } + +private: + void lexicalOrder_helper(int num, int& n, vector& result) { + for (int i=0; i<=9; i++) { + int tmp = num * 10 + i; + if (tmp > n) { + break; + } + result.push_back(tmp); + lexicalOrder_helper(tmp, n, result); + } + } + +//Solution 3: no recursive way, but the code is not easy to read +public : + vector lexicalOrder03(int n) { + vector result; + int curr = 1; + while (result.size() lexicalOrder(int n) { + srand(time(NULL)); + if (rand()%2) + return lexicalOrder02(n); // recursive way 560ms + else + return lexicalOrder03(n); // non-recursive way, 460ms + } + +}; diff --git a/algorithms/cpp/linkedListRandomNode/LinkedListRandomNode.cpp b/algorithms/cpp/linkedListRandomNode/LinkedListRandomNode.cpp new file mode 100644 index 000000000..8cc97117c --- /dev/null +++ b/algorithms/cpp/linkedListRandomNode/LinkedListRandomNode.cpp @@ -0,0 +1,61 @@ +// Source : https://leetcode.com/problems/linked-list-random-node/ +// Author : Hao Chen +// Date : 2016-08-24 + +/*************************************************************************************** + * + * Given a singly linked list, return a random node's value from the linked list. Each + * node must have the same probability of being chosen. + * + * Follow up: + * What if the linked list is extremely large and its length is unknown to you? Could + * you solve this efficiently without using extra space? + * + * Example: + * + * // Init a singly linked list [1,2,3]. + * ListNode head = new ListNode(1); + * head.next = new ListNode(2); + * head.next.next = new ListNode(3); + * Solution solution = new Solution(head); + * + * // getRandom() should return either 1, 2, or 3 randomly. Each element should have + * equal probability of returning. + * solution.getRandom(); + ***************************************************************************************/ + +/** + * Definition for singly-linked list. + * struct ListNode { + * int val; + * ListNode *next; + * ListNode(int x) : val(x), next(NULL) {} + * }; + */ +class Solution { +public: + /** @param head The linked list's head. + Note that the head is guaranteed to be not null, so it contains at least one node. */ + Solution(ListNode* head) { + this->head = head; + this->len = 0; + for(ListNode*p = head; p!=NULL; p=p->next, len++); + srand(time(NULL)); + } + + /** Returns a random node's value. */ + int getRandom() { + int pos = rand() % len; + ListNode *p = head; + for (; pos > 0; pos--, p=p->next); + return p->val; + } + ListNode* head; + int len; +}; + +/** + * Your Solution object will be instantiated and called as such: + * Solution obj = new Solution(head); + * int param_1 = obj.getRandom(); + */ diff --git a/algorithms/cpp/longestAbsoluteFilePath/LongestAbsoluteFilePath.cpp b/algorithms/cpp/longestAbsoluteFilePath/LongestAbsoluteFilePath.cpp new file mode 100644 index 000000000..bf7f6ce33 --- /dev/null +++ b/algorithms/cpp/longestAbsoluteFilePath/LongestAbsoluteFilePath.cpp @@ -0,0 +1,107 @@ +// Source : https://leetcode.com/problems/longest-absolute-file-path/ +// Author : Hao Chen +// Date : 2016-08-23 + +/*************************************************************************************** + * + * Suppose we abstract our file system by a string in the following manner: + * + * The string "dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext" represents: + * + * dir + * subdir1 + * subdir2 + * file.ext + * + * The directory dir contains an empty sub-directory subdir1 and a sub-directory + * subdir2 containing a file file.ext. + * + * The string + * "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile + * 2.ext" represents: + * + * dir + * subdir1 + * file1.ext + * subsubdir1 + * subdir2 + * subsubdir2 + * file2.ext + * + * The directory dir contains two sub-directories subdir1 and subdir2. subdir1 contains + * a file file1.ext and an empty second-level sub-directory subsubdir1. subdir2 + * contains a second-level sub-directory subsubdir2 containing a file file2.ext. + * + * We are interested in finding the longest (number of characters) absolute path to a + * file within our file system. For example, in the second example above, the longest + * absolute path is "dir/subdir2/subsubdir2/file2.ext", and its length is 32 (not + * including the double quotes). + * + * Given a string representing the file system in the above format, return the length + * of the longest absolute path to file in the abstracted file system. If there is no + * file in the system, return 0. + * + * Note: + * + * The name of a file contains at least a . and an extension. + * The name of a directory or sub-directory will not contain a .. + * + * Time complexity required: O(n) where n is the size of the input string. + * + * Notice that a/aa/aaa/file1.txt is not the longest file path, if there is another + * path aaaaaaaaaaaaaaaaaaaaa/sth.png. + ***************************************************************************************/ + +class Solution { +public: + // Solution + // -------- + // We can see the input formation has the order + // so, we can maintain an array which states the current level's path length + // + // For example: + // dir + // subdir1 <- length[ level1 = len("dir")+len("/"), + // level2 = len("dir")+len("/")+len("subdir1")+len("/") ] + // file.ext + // subdir2 + // file.ext + // subsubdir1 <- length[ level1 = len("dir")+len("/"), + // level2 = len("dir")+len("/")+len("subdir2")+len("/"), + // level3 = len("dir")+len("/")+len("subdir2")+len("/")+len("subsubdir1")+len("/") ] + // file.ext + // + int lengthLongestPath(string input) { + + stringstream ss(input); + string line; + int result = 0; + + vector length; + length.push_back(0); //initialize top dummy level's length is zero + + while (getline(ss, line, '\n')) { + //get current level, start from 1 + int level = 0; + while ( line[level++] == '\t'); // get the level + int len = line.size() - level + 1; + + //if is a file, then cacualte the total length. + if (line.find('.') != string::npos) { + if ( length[level-1] + len > result ) { + result = length[level-1] + len; + } + } else { + + if (length.size() <= level) { + length.push_back(0); + } + + // if it a folder, then update the current level's length + length[level] = length[level-1] + len + 1; // 1 for "/" path delimiter + } + + } + return result; + } +}; 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= NO_OF_CHARS ) return s.size(); + + // find the most infrequent char + char least = 0; + for (int c = 0; c < NO_OF_CHARS; c++) { + if (count[c] == 0) continue; + if (least == 0) { + least = c; + } else if ( count[c] < count[least]) { + least = c; + } + } + + //split the string and run them recursively + vector subs; + split(s, least, subs); + + int res = 0; + for (string str: subs) { + res = max(res, longestSubstring(str, k)); + } + return res; + return 0; + } + +private: + + inline int max(int x, int y) { return x>y? x:y; } + + inline void split(const string &s, char delim, vector &elems) { + stringstream ss; + ss.str(s); + string item; + while (getline(ss, item, delim)) { + cout << item << endl; + elems.push_back(item); + } + } + + + inline vector split(const string &s, char delim) { + vector elems; + split(s, delim, elems); + return elems; + } +}; diff --git a/algorithms/cpp/majorityElement/majorityElement.II.cpp b/algorithms/cpp/majorityElement/majorityElement.II.cpp index 827e97a57..08b675d69 100644 --- a/algorithms/cpp/majorityElement/majorityElement.II.cpp +++ b/algorithms/cpp/majorityElement/majorityElement.II.cpp @@ -36,7 +36,7 @@ class Solution { //the same algorithm as Majority Element I problem int majority1=0, majority2=0, cnt1=0, cnt2=0; for(auto item: nums) { - if (cnt1 == 0) { + if (cnt1 == 0 && majority2 != item ) { majority1 = item; cnt1 = 1; } else if (majority1 == item) { diff --git a/algorithms/cpp/maximalRectangle/maximalRectangle.cpp b/algorithms/cpp/maximalRectangle/maximalRectangle.cpp index 5e0a8fd81..4f732ed73 100644 --- a/algorithms/cpp/maximalRectangle/maximalRectangle.cpp +++ b/algorithms/cpp/maximalRectangle/maximalRectangle.cpp @@ -56,7 +56,7 @@ int maximalRectangle(vector > &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; ileft), maxDepth(root->right)) + 1; + } +}; diff --git a/algorithms/cpp/maximumProductOfWordLengths/MaximumProductOfWordLengths.cpp b/algorithms/cpp/maximumProductOfWordLengths/MaximumProductOfWordLengths.cpp new file mode 100644 index 000000000..8e9ecf4e0 --- /dev/null +++ b/algorithms/cpp/maximumProductOfWordLengths/MaximumProductOfWordLengths.cpp @@ -0,0 +1,72 @@ +// Source : https://leetcode.com/problems/maximum-product-of-word-lengths/ +// Author : Hao Chen +// Date : 2017-01-02 + +/*************************************************************************************** + * + * Given a string array words, find the maximum value of length(word[i]) * + * length(word[j]) where the two words do not share common letters. + * You may assume that each word will contain only lower case letters. + * If no such two words exist, return 0. + * + * Example 1: + * + * Given ["abcw", "baz", "foo", "bar", "xtfn", "abcdef"] + * Return 16 + * The two words can be "abcw", "xtfn". + * + * Example 2: + * + * Given ["a", "ab", "abc", "d", "cd", "bcd", "abcd"] + * Return 4 + * The two words can be "ab", "cd". + * + * Example 3: + * + * Given ["a", "aa", "aaa", "aaaa"] + * Return 0 + * No such pair of words. + * + * Credits:Special thanks to @dietpepsi for adding this problem and creating all test + * cases. + ***************************************************************************************/ + +class Solution { +public: + // + // there are two algorithms: + // + // 1) compare two words is same or not + // - we can use bit-mask to solve that. + // - we need be careful about one word is subset of another one, such as: "abc" is subset of "abcabc" + // + // 2) find out the max product - that needs O(N^2) time complexity algorithm. + // + + int maxProduct(vector& words) { + //Key is the word's bitmask, and the value the max length of that bit mask + unordered_map maxLens; + //constructing the bitmask. + for(auto& w: words) { + int mask = 0; + for (auto& c: w) { + mask = mask | ( 1 << (c-'a') ); + } + if ( maxLens.find(mask) == maxLens.end() || maxLens[mask] < w.size() ) { + maxLens[mask] = w.size(); + } + } + + //find out the max product + int result = 0; + for (auto a : maxLens) { + for (auto b: maxLens) { + // if `a` and `b` is same, then just simply continue + if (a.first & b.first) continue; // there are common letters + result = max( result, a.second * b.second ); + } + } + + return result; + } +}; diff --git a/algorithms/cpp/miniParser/MiniParser.cpp b/algorithms/cpp/miniParser/MiniParser.cpp new file mode 100644 index 000000000..8c126e958 --- /dev/null +++ b/algorithms/cpp/miniParser/MiniParser.cpp @@ -0,0 +1,116 @@ +// Source : https://leetcode.com/problems/mini-parser/ +// Author : Hao Chen +// Date : 2016-08-24 + +/*************************************************************************************** + * + * Given a nested list of integers represented as a string, implement a parser to + * deserialize it. + * + * Each element is either an integer, or a list -- whose elements may also be integers + * or other lists. + * + * Note: + * You may assume that the string is well-formed: + * + * String is non-empty. + * String does not contain white spaces. + * String contains only digits 0-9, [, - ,, ]. + * + * Example 1: + * + * Given s = "324", + * + * You should return a NestedInteger object which contains a single integer 324. + * + * Example 2: + * + * Given s = "[123,[456,[789]]]", + * + * Return a NestedInteger object containing a nested list with 2 elements: + * + * 1. An integer containing value 123. + * 2. A nested list containing two elements: + * i. An integer containing value 456. + * ii. A nested list with one element: + * a. An integer containing value 789. + ***************************************************************************************/ + + +/** + * // This is the interface that allows for creating nested lists. + * // You should not implement it, or speculate about its implementation + * class NestedInteger { + * public: + * // Constructor initializes an empty nested list. + * NestedInteger(); + * + * // Constructor initializes a single integer. + * NestedInteger(int value); + * + * // 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; + * + * // Set this NestedInteger to hold a single integer. + * void setInteger(int value); + * + * // Set this NestedInteger to hold a nested list and adds a nested integer to it. + * void add(const NestedInteger &ni); + * + * // 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 Solution { +public: + NestedInteger deserialize(string s) { + if (s.size()==0) return NestedInteger(); + int pos = 0; + if (s[pos]!='[') return atoni(s, pos); + + return helper(s, ++pos); + } +private: + NestedInteger helper(string& s, int& pos) { + + NestedInteger ni; + + while ( s[pos] != ']' && pos < s.size() ) { + + if (s[pos]=='-' || isnum(s[pos])){ + ni.add(atoni(s, pos)); + }else if (s[pos] == '[') { + pos++; + ni.add(helper(s, pos)); + }else { + pos++; + } + } + pos++; + return ni; + } + NestedInteger atoni(string& s, int& pos) { + int sign = 1; + int num = 0; + if (s[pos]=='-') { + sign = -1; + pos++; + } + for (; pos < s.size(); pos++) { + if (isnum(s[pos])) { + num = num * 10 + s[pos] - '0'; + }else{ + break; + } + } + return NestedInteger(sign * num); + } + bool isnum(char& c) { + return (c >='0' && c <='9'); + } +}; diff --git a/algorithms/cpp/minimumHeightTrees/MinimumHeightTrees.cpp b/algorithms/cpp/minimumHeightTrees/MinimumHeightTrees.cpp new file mode 100644 index 000000000..9f3a125f2 --- /dev/null +++ b/algorithms/cpp/minimumHeightTrees/MinimumHeightTrees.cpp @@ -0,0 +1,98 @@ +// Source : https://leetcode.com/problems/minimum-height-trees/ +// Author : Hao Chen +// Date : 2016-01-24 + +/*************************************************************************************** + * + * For a undirected graph with tree characteristics, we can choose any node as the + * root. The result graph is then a rooted tree. Among all possible rooted trees, those + * with minimum height are called minimum height trees (MHTs). + * + * Given such a graph, write a function to find all the MHTs and return a list of + * their root labels. + * + * *Format* + * The graph contains n nodes which are labeled from 0 to n - 1. + * You will be given the number n and a list of undirected edges (each edge is a + * pair of labels). + * + * + * You can assume that no duplicate edges will appear in edges. Since all edges are + * undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges. + * + * Example 1: + * + * Given n = 4, edges = [[1, 0], [1, 2], [1, 3]] + * + * 0 + * | + * 1 + * / \ + * 2 3 + * + * return [1] + * + * Example 2: + * + * Given n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]] + * + * 0 1 2 + * \ | / + * 3 + * | + * 4 + * | + * 5 + * + * return [3, 4] + * + * How many MHTs can a graph have at most? + * + * Note: + * + * (1) According to the definition of tree on Wikipedia: https://en.wikipedia.org/wiki/Tree_(graph_theory) + * “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 tree.” + * + * (2) The height of a rooted tree is the number of edges on the longest downward path between + * the root and a leaf. + * + * Credits:Special thanks to @dietpepsi for adding this problem and creating all test + * cases. + ***************************************************************************************/ + +class Solution { +public: + vector 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/nthDigit/NthDigit.cpp b/algorithms/cpp/nthDigit/NthDigit.cpp new file mode 100644 index 000000000..1351f2a84 --- /dev/null +++ b/algorithms/cpp/nthDigit/NthDigit.cpp @@ -0,0 +1,99 @@ +// Source : https://leetcode.com/problems/nth-digit/ +// Author : Hao Chen +// Date : 2016-11-05 + +/*************************************************************************************** + * + * Find the nth digit of the infinite integer sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + * 11, ... + * + * Note: + * n is positive and will fit within the range of a 32-bit signed integer (n 31). + * + * Example 1: + * + * Input: + * 3 + * + * Output: + * 3 + * + * Example 2: + * + * Input: + * 11 + * + * Output: + * 0 + * + * Explanation: + * The 11th digit of the sequence 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, ... is a 0, which + * is part of the number 10. + ***************************************************************************************/ + + +#include +using namespace std; + +class Solution { +public: + int findNthDigit(int n) { + + // We can see the following pattern: + // + // 1, 2, .... 9 : there are 9 * 1 digits. + // 10, 11, ..., 99: there are 90 * 2 digits. + // 101, 102, 103, ..., 999: there are 900 * 3. + // ... + + + //we can count the digits with the above pattern + long digits_cnt = 0; + long digits_cnt_prev = 0; + int base = 0; + for ( ; digits_cnt < n; base++) { + digits_cnt_prev = digits_cnt; + digits_cnt = digits_cnt + 9 * pow(10 , base) * ( base + 1 ); + } + + + // Now, we got `digits_cnt_prev`, `digits_cnt` and `base` + // + // For examples: + // n = 20; digits_cnt_prev = 9, digits_cnt = 9+90*2 = 189, base = 2; + // n = 500; digits_cnt_prev = 9+90*2 = 189, digits_cnt = 9+90*2+900*3 = 2889, base = 3; + // n = 2000; digits_cnt_prev = 9+90*2 = 189, digits_cnt = 9+90*2+900*3 = 2889, base = 3; + // + // It means, we found the range where the number it is + // n = 20, the number located in the range 10 -- 99 + // n = 500, the number located in the range 100 - 999 + // + // and we can use `digits_cnt_prev` to know the previous rangs produce how many digits. + // n = 20, the previous ranges produce 9 digits, so there needs 20-9 = 11 digits in [10 - 99] + // n = 500, the previous ranges produce 189 digits, so there needs 500-189 = 311 digits in [100-999] + // + // the `base` told us in current ranges, each number can have how many digits. + // then we can locate the target number. + // n = 20, + // (n - digits_cnt_prev) / base = (20 - 9 ) / 2 = 5, so, [10 - 14] produces 10 digits (ZERO-based), + // now, we have 1 digits left, it is the first digit of the target number 15. + // + // n = 500, + // (n - digits_cnt_prev) / base = (500 - 189) / 3 = 103, so, [100 - 202] produces 309 digits(ZERO-based). + // now, we have (500 - 189 - 309) = 2 digits left, it is the second digit of the target number 203. + // + // We can write the code now... + // + int target = pow(10, base-1) + (n - digits_cnt_prev) / base - 1; + int left = n - digits_cnt_prev - (n - digits_cnt_prev) / base * base; + + //cout << "target = " << target << ", left = " << left << endl; + + //no digits left + if ( left == 0 ) return (target) % 10; + + //still have some digits left, it should be in next number. + target++; + return int( target / pow(10, base - left) ) % 10; + } +}; 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 (i 0, determine if they all together form an + * exact cover of a rectangular region. + * + * Each rectangle is represented as a bottom-left point and a top-right point. For + * example, a unit square is represented as [1,1,2,2]. (coordinate of bottom-left point + * is (1, 1) and top-right point is (2, 2)). + * + * Example 1: + * + * rectangles = [ + * [1,1,3,3], + * [3,1,4,2], + * [3,2,4,4], + * [1,3,2,4], + * [2,3,3,4] + * ] + * + * Return true. All 5 rectangles together form an exact cover of a rectangular region. + * + * Example 2: + * + * rectangles = [ + * [1,1,2,3], + * [1,3,2,4], + * [3,1,4,2], + * [3,2,4,4] + * ] + * + * Return false. Because there is a gap between the two rectangular regions. + * + * Example 3: + * + * rectangles = [ + * [1,1,3,3], + * [3,1,4,2], + * [1,3,2,4], + * [3,2,4,4] + * ] + * + * Return false. Because there is a gap in the top center. + * + * Example 4: + * + * rectangles = [ + * [1,1,3,3], + * [3,1,4,2], + * [1,3,2,4], + * [2,2,4,4] + * ] + * + * Return false. Because two of the rectangles overlap with each other. + ***************************************************************************************/ + + +class Solution { +public: + bool isRectangleCover(vector>& rectangles) { + unordered_map mp; + string corners[4]; + for(auto v: rectangles) + for(int i = 0; i<4; ++i){ + corners[i] = to_string(v[i/2*2]) + "," + to_string(v[(i%2)*2+1]); + if(mp[corners[i]] & int(pow(2,i))) return false; + else mp[corners[i]] |= int(pow(2,i)); + } + int corner = 0; + for(auto i=mp.begin(); i!=mp.end(); ++i){ + int val = i->second; + if(!(val & (val-1)) && (++corner >4)) return false; + if((val & (val-1)) && !(val == 3 || val==12 || val==10 || val==5 || val==15)) return false; + } + return true; + } +}; diff --git a/algorithms/cpp/powerOfFour/PowerOfFour.cpp b/algorithms/cpp/powerOfFour/PowerOfFour.cpp new file mode 100644 index 000000000..f66e6d9e2 --- /dev/null +++ b/algorithms/cpp/powerOfFour/PowerOfFour.cpp @@ -0,0 +1,37 @@ +// Source : https://leetcode.com/problems/power-of-four/ +// Author : Hao Chen +// Date : 2016-05-29 + +/*************************************************************************************** + * + * Given an integer (signed 32 bits), write a function to check whether it is a power + * of 4. + * + * Example: + * Given num = 16, return true. + * Given num = 5, return false. + * + * Follow up: Could you solve it without loops/recursion? + * + * Credits:Special thanks to @yukuairoy for adding this problem and creating all test + * cases. + ***************************************************************************************/ + + +class Solution { +public: + bool isPowerOfFour(int num) { + static int mask = 0b01010101010101010101010101010101; + + //edge case + if (num<=0) return false; + + // there are multiple bits are 1 + if ((num & num-1) != 0) return false; + + // check which one bit is zero, if the place is 1 or 3 or 5 or 7 or 9..., + // then it is the power of 4 + if ((num & mask) != 0) return true; + return false; + } +}; diff --git a/algorithms/cpp/powerOfThree/PowerOfThree.cpp b/algorithms/cpp/powerOfThree/PowerOfThree.cpp new file mode 100644 index 000000000..a75143b91 --- /dev/null +++ b/algorithms/cpp/powerOfThree/PowerOfThree.cpp @@ -0,0 +1,66 @@ +// Source : https://leetcode.com/problems/power-of-three/ +// Author : Hao Chen +// Date : 2016-01-14 + +/*************************************************************************************** + * + * Given an integer, write a function to determine if it is a power of three. + * + * Follow up: + * Could you do it without using any loop / recursion? + * + * Credits:Special thanks to @dietpepsi for adding this problem and creating all test + * cases. + * + ***************************************************************************************/ + +class Solution { + +public: + + bool isPowerOfThree(int n) { + return isPowerOfThree03(n); //140ms + return isPowerOfThree02(n);//130ms + return isPowerOfThree01(n); //140ms + return isPowerOfThree_loop(n); //136ms + return isPowerOfThree_recursive(n); //168ms + } + + bool isPowerOfThree03(int n) { + double logRes = log10(n)/log10(3); + return (logRes - int(logRes) == 0); + } + bool isPowerOfThree02(int n) { + return n>0 ? (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/queueReconstructionByHeight/QueueReconstructionByHeight.cpp b/algorithms/cpp/queueReconstructionByHeight/QueueReconstructionByHeight.cpp new file mode 100644 index 000000000..e648683a1 --- /dev/null +++ b/algorithms/cpp/queueReconstructionByHeight/QueueReconstructionByHeight.cpp @@ -0,0 +1,73 @@ +// Source : https://leetcode.com/problems/queue-reconstruction-by-height/ +// Author : Hao Chen +// Date : 2016-11-12 + +/*************************************************************************************** + * + * Suppose you have a random list of people standing in a queue. Each person is + * described by a pair of integers (h, k), where h is the height of the person and k is + * the number of people in front of this person who have a height greater than or equal + * to h. Write an algorithm to reconstruct the queue. + * + * Note: + * The number of people is less than 1,100. + * + * Example + * + * Input: + * [[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]] + * + * Output: + * [[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]] + ***************************************************************************************/ + +class Solution { + +public: + vector> reconstructQueue(vector>& people) { + //sort function + auto comp = [](const pair& p1, const pair& p2) + { return p1.first == p2.first ? p1.second < p2.second : p1.first > p2.first; }; + //sort the people with their height with descending order + // and if the height is same then sort by K with ascending order + sort(people.begin(), people.end(), comp); + + // For example: + // Original Queue: [7,0], [4,4], [7,1], [5,0], [6,1], [5,2] + // Sorted Queue: [7,0], [7,1], [6,1], [5,0], [5,2], [4,4] + + + // Why do we need to sort like this? + // + // ** The position of shorter people is ZERO impacted with higher people. ** + // + // and, the shortest people has no impacts to all of people. we can simpley insert it to the Kth position + // + // So, we sorted the people from highest to the shortest, then when we insert the people to another array, + // + // we always can guarantee the people is going to be inserted has nothing to do with the people has been inserted. + // + // Let's continue the about example above + // + // [7,0] => [] then [7,0] + // [7,1] => [7,0] then [7,0], [7,1] + // [6,1] => [7,0], [7,1] then [7,0], [6,1], [7,1] + // [5,0] => [7,0], [6,1], [7,1] then [5,0], [7,0], [6,1], [7,1] + // [5,2] => [5,0], [7,0], [6,1], [7,1] then [5,0], [7,0], [5,2], [6,1], [7,1] + // [4,4] => [5,0], [7,0], [5,2], [6,1], [7,1] then [5,0], [7,0], [5,2], [6,1], [4,4], [7,1] + // + // We alway can see, the people is going to be inserted has NO IMPACT with the current people. + // + // [6,1] => [7,0], [7,1] + // + // Whatever the people[6,1] placed, it has nothing to do with the people [7,0] [7,1], + // So, we can just insert the people to the place he like - the `Kth` place. + // + // + vector> res; + for (auto& p : people) { + res.insert(res.begin() + p.second, p); + } + return res; + } +}; diff --git a/algorithms/cpp/randomPickIndex/RandomPickIndex.cpp b/algorithms/cpp/randomPickIndex/RandomPickIndex.cpp new file mode 100644 index 000000000..f06f43ab3 --- /dev/null +++ b/algorithms/cpp/randomPickIndex/RandomPickIndex.cpp @@ -0,0 +1,54 @@ +// Source : https://leetcode.com/problems/random-pick-index/ +// Author : Hao Chen +// Date : 2016-11-04 + +/*************************************************************************************** + * + * Given an array of integers with possible duplicates, randomly output the index of a + * given target number. You can assume that the given target number must exist in the + * array. + * + * Note: + * The array size can be very large. Solution that uses too much extra space will not + * pass the judge. + * + * Example: + * + * int[] nums = new int[] {1,2,3,3,3}; + * Solution solution = new Solution(nums); + * + * // pick(3) should return either index 2, 3, or 4 randomly. Each index should have + * equal probability of returning. + * solution.pick(3); + * + * // pick(1) should return 0. Since in the array only nums[0] is equal to 1. + * solution.pick(1); + ***************************************************************************************/ + +class Solution { +private: + vector nums; +public: + Solution(vector nums) { + srand(time(0)); + this->nums = nums; + } + + int pick(int target) { + // we just randomly pick a number from the array, + // if the number is target just return the index. + // otherwise, keep picking the number randomly. + while(true) { + int idx = rand() % nums.size(); + if ( target == nums[idx] ) { + return idx; + } + } + } +}; + +/** + * Your Solution object will be instantiated and called as such: + * Solution obj = new Solution(nums); + * int param_1 = obj.pick(target); + */ diff --git a/algorithms/cpp/ransomNote/RansomNote.cpp b/algorithms/cpp/ransomNote/RansomNote.cpp new file mode 100644 index 000000000..c13922ea1 --- /dev/null +++ b/algorithms/cpp/ransomNote/RansomNote.cpp @@ -0,0 +1,38 @@ +// Source : https://leetcode.com/problems/ransom-note/ +// Author : Hao Chen +// Date : 2016-08-24 + +/*************************************************************************************** + * + * 
Given
 an 
arbitrary
 ransom
 note
 string 
and 
another 
string 
containing + * 
letters from
 all 
the 
magazines,
 write 
a 
function 
that 
will 
return 
true + * 
if 
the 
ransom 
 + * note 
can 
be 
constructed 
from 
the 
magazines ; 
otherwise, 
it 
will 
return + * 
false. 

 + * + * Each 
letter
 in
 the
 magazine 
string 
can
 only 
be
 used 
once
 in
 your + * 
ransom
 note. + * + * Note: + * You may assume that both strings contain only lowercase letters. + * + * canConstruct("a", "b") -> false + * canConstruct("aa", "ab") -> false + * canConstruct("aa", "aab") -> true + ***************************************************************************************/ + +class Solution { +public: + bool canConstruct(string ransomNote, string magazine) { + unordered_map m; + for(int i=0; i PEK, + b) JFK -> SHA -> JFK -> PEK + The a) is smaller than b), because PEK < SHA, however the b) is correct answer. + So, it means we need use all of tickets. + + 2) [["JFK", "PEK"], ["JFK", "SHA"]], which also has two itineraries: + a) JFK -> PEK + b) JFK -> SHA + for my understanding, the JFK -> SHA is the correct one, + however, the correct answer is JFK -> SHA -> PEK. + I don't understand, why the correct answer is not JFK -> PEK -> SHA + That really does not make sense to me. + + All right, we need assume all of the tickets can be connected in one itinerary. + Then, it's easy to have a DFS algorithm. +*/ + + +class Solution { +public: + //DFS + void travel(string& start, unordered_map>& map, vector& result) { + while (map[start].size() > 0 ) { + string next = *(map[start].begin()); + map[start].erase(map[start].begin()); + travel(next, map, result); + } + result.insert(result.begin(), start); + } + + vector findItinerary(vector> tickets) { + unordered_map> map; + for(auto t : tickets) { + map[t.first].insert(t.second); + } + vector result; + string start = "JFK"; + travel(start, map, result); + return result; + } +}; diff --git a/algorithms/cpp/removeDuplicateLetters/RemoveDuplicateLetters.cpp b/algorithms/cpp/removeDuplicateLetters/RemoveDuplicateLetters.cpp new file mode 100644 index 000000000..e3ae9f3f4 --- /dev/null +++ b/algorithms/cpp/removeDuplicateLetters/RemoveDuplicateLetters.cpp @@ -0,0 +1,52 @@ +// Source : https://leetcode.com/problems/remove-duplicate-letters/ +// Author : Hao Chen +// Date : 2017-01-02 + +/*************************************************************************************** + * + * Given a string which contains only lowercase letters, remove duplicate letters so + * that every letter appear once and only once. You must make sure your result is the + * smallest in lexicographical order among all possible results. + * + * Example: + * + * Given "bcabc" + * Return "abc" + * + * Given "cbacdcbc" + * Return "acdb" + * + * Credits:Special thanks to @dietpepsi for adding this problem and creating all test + * cases. + ***************************************************************************************/ + + +class Solution { +public: + string removeDuplicateLetters(string s) { + const int ASCII_LEN = 256; + int counter[ASCII_LEN] = {0}; + bool visited[ASCII_LEN] = {false}; + + for (char ch : s) { + counter[ch]++; + } + + string result; + for (char ch : s) { + counter[ch]--; + // if the current `ch` has already put into the result. + if (visited[ch]) continue; + + // if the current `ch` is smaller than the last one char in result. + // and we still have duplicated last-one char behind, so we can remove the current one. + while ( !result.empty() && ch < result.back() && counter[result.back()] ) { + visited[result.back()] = false; + result.pop_back(); + } + result.push_back(ch); + visited[ch] = true; + } + return result; + } +}; diff --git a/algorithms/cpp/removeKDigits/RemoveKDigits.cpp b/algorithms/cpp/removeKDigits/RemoveKDigits.cpp new file mode 100644 index 000000000..9b33cf5c4 --- /dev/null +++ b/algorithms/cpp/removeKDigits/RemoveKDigits.cpp @@ -0,0 +1,107 @@ +// Source : https://leetcode.com/problems/remove-k-digits/ +// Author : Hao Chen +// Date : 2016-11-11 + +/*************************************************************************************** + * + * Given a non-negative integer num represented as a string, remove k digits from the + * number so that the new number is the smallest possible. + * + * Note: + * + * The length of num is less than 10002 and will be ≥ k. + * The given num does not contain any leading zero. + * + * Example 1: + * + * Input: num = "1432219", k = 3 + * Output: "1219" + * Explanation: Remove the three digits 4, 3, and 2 to form the new number 1219 which + * is the smallest. + * + * Example 2: + * + * Input: num = "10200", k = 1 + * Output: "200" + * Explanation: Remove the leading 1 and the number is 200. Note that the output must + * not contain leading zeroes. + * + * Example 3: + * + * Input: num = "10", k = 2 + * Output: "0" + * Explanation: Remove all the digits from the number and it is left with nothing which + * is 0. + ***************************************************************************************/ + +class Solution { +public: + string removeKdigits_pick(string& num, int k) { + + int len = num.size(); + string result; + + int idx = 0; + for (int i=0; i < len - k; i++) { + int min_idx = idx; + for (int j=min_idx; j<=i+k; j++) { + if (num[min_idx] > num[j]) min_idx = j; + } + + //don't put zero at the beginning + if ( !(result.empty() && num[min_idx]=='0') ){ + result.push_back(num[min_idx]); + } + + //select the number started from next one, to make the order correctness. + idx = min_idx + 1; + } + + if (result.empty()) result = "0"; + return result; + } + + string removeKdigits_remove(string& num, int k) { + if ( num.size() <= k ) return "0"; + int left_len = num.size() - k; + int idx = 0; + for (int i=0; i num[j+1] ) { + num.erase(j, 1); + idx = j; + break; + } + } + } + + //remove all of ZEROs at the beginning. + for (int i=0; i<= num.size(); i++) { + if (num[i] != '0' || i == num.size()) { + num.erase(0, i); + break; + } + } + + // if the digits in the array are sorted, + // then, we need remove the digits at the ends. + if (num.size() > left_len ) { + num.erase(num.begin() + left_len, num.end()); + } + + if (num.empty()) num = "0"; + return num; + } + + string removeKdigits(string num, int k) { + srand(time(0)); + if (rand() % 2 ) { + return removeKdigits_pick(num, k); + } else { + return removeKdigits_remove(num, k); + } + } +}; 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/rotateFunction/RotateFunction.cpp b/algorithms/cpp/rotateFunction/RotateFunction.cpp new file mode 100644 index 000000000..c8897dd27 --- /dev/null +++ b/algorithms/cpp/rotateFunction/RotateFunction.cpp @@ -0,0 +1,75 @@ +// Source : https://leetcode.com/problems/rotate-function/ +// Author : Hao Chen +// Date : 2016-11-03 + +/*************************************************************************************** + * + * Given an array of integers A and let n to be its length. + * + * Assume Bk to be an array obtained by rotating the array A k positions clock-wise, we + * define a "rotation function" F on A as follow: + * + * F(k) = 0 * Bk[0] + 1 * Bk[1] + ... + (n-1) * Bk[n-1]. + * + * Calculate the maximum value of F(0), F(1), ..., F(n-1). + * + * Note: + * n is guaranteed to be less than 105. + * + * Example: + * + * A = [4, 3, 2, 6] + * + * F(0) = (0 * 4) + (1 * 3) + (2 * 2) + (3 * 6) = 0 + 3 + 4 + 18 = 25 + * F(1) = (0 * 6) + (1 * 4) + (2 * 3) + (3 * 2) = 0 + 4 + 6 + 6 = 16 + * F(2) = (0 * 2) + (1 * 6) + (2 * 4) + (3 * 3) = 0 + 6 + 8 + 9 = 23 + * F(3) = (0 * 3) + (1 * 2) + (2 * 6) + (3 * 4) = 0 + 2 + 12 + 12 = 26 + * + * So the maximum value of F(0), F(1), F(2), F(3) is F(3) = 26. + ***************************************************************************************/ + + +// +// Asumming we have 4 numbers: a, b, c, d, then +// F(0) = 0a + 1b + 2c + 3d +// F(1) = 3a + 0b + 1c + 2d +// F(2) = 2a + 3b + 0c + 1d +// F(3) = 1a + 2b + 3c + 0d +// +// We can see how F(n) transfrom to F(n+1) +// F(0) - F(1) = -3a + b + c + d +// F(1) - F(2) = a + -3b + c + d +// F(2) - F(3) = a + b + -3c + d +// F(3) - F(0) = a + b + c + -3d +// +// So, we can tansfrom to the following experssion: +// +// F(1) = F(0) - (a+b+c+d) + 4a +// F(2) = F[1] - (a+b+c+d) + 4b +// F(3) = F[2] - (a+b+c+d) + 4c +// +// Then, we can see this fomular: +// +// F(n) = F(n-1) - sum(array) + len(array) * array[n-1] +// +class Solution { +public: + int maxRotateFunction(vector& A) { + int sum = 0; + int F = 0; + for (int i=0; i < A.size(); i++) { + sum += A[i]; + F += (i * A[i]); + } + int maxF = F; + int len = A.size(); + //cout << "F(0) = " << maxF < list; + split(preorder, ',', list); + //we initailize the counter as 1, + //because we expect at lease 1 node in the tree. + int node_expected = 1; + for (auto node : list) { + if (node_expected == 0) return false; + node == "#" ? node_expected-- : node_expected++; + } + return node_expected == 0; + } + + void split(const string &s, char delim, vector &elems) { + stringstream ss(s); + string item; + while (getline(ss, item, delim)) { + elems.push_back(item); + } + } +}; diff --git a/algorithms/cpp/wiggleSort/WiggleSort.II.cpp b/algorithms/cpp/wiggleSort/WiggleSort.II.cpp new file mode 100644 index 000000000..a225c19b7 --- /dev/null +++ b/algorithms/cpp/wiggleSort/WiggleSort.II.cpp @@ -0,0 +1,93 @@ +// Source : https://leetcode.com/problems/wiggle-sort-ii/ +// Author : Hao Chen +// Date : 2017-01-02 + +/*************************************************************************************** + * + * Given an unsorted array nums, reorder it such that + * nums[0] nums[2] . + * + * Example: + * (1) Given nums = [1, 5, 1, 1, 6, 4], one possible answer is [1, 4, 1, 5, 1, 6]. + * (2) Given nums = [1, 3, 2, 2, 3, 1], one possible answer is [2, 3, 1, 3, 1, 2]. + * + * Note: + * You may assume all input has valid answer. + * + * Follow Up: + * Can you do it in O(n) time and/or in-place with O(1) extra space? + * + * Credits:Special thanks to @dietpepsi for adding this problem and creating all test + * cases. + ***************************************************************************************/ + +class Solution { + +public: + // + // Solution - O(N*logN) + // -------------------- + // 1) Sorting the array with descending order + // + // 2) Split the sorted array into two parts, + // and insert the 2nd half array into the 1st half array + // + // For example: [ 9 8 7 6 5 4 3 2 1 0 ] + // + // + // 1st Large half: . 9 . 8 . 7 . 6 . 5 + // 2nd Small half: 4 . 3 . 2 . 1 . 0 . + // --------------------------------------- + // Result: 4 9 3 8 2 7 1 6 0 5 + // + // Be careful if the length of array is odd number, + // Such as: [5 4 3 2 1], + // The 2nd half is [3 2 1] instead of [2 1] + // + + void wiggleSort01(vector& nums) { + sort(nums.begin(), nums.end(), [](int x, int y) { return x > y; }); + int half = (nums.size() / 2); + + for (int i=0; i& nums) { + int n = nums.size(); + + // Find a median. + auto midptr = nums.begin() + n / 2; + nth_element(nums.begin(), midptr, nums.end()); + int mid = *midptr; + + // Index-rewiring. + #define A(i) nums[(1+2*(i)) % (n|1)] + + // 3-way-partition-to-wiggly in O(n) time with O(1) space. + int i = 0, j = 0, k = n - 1; + while (j <= k) { + if (A(j) > mid) + swap(A(i++), A(j++)); + else if (A(j) < mid) + swap(A(j), A(k--)); + else + j++; + } + } + void wiggleSort(vector& nums) { + return wiggleSort02(nums); //~140ms + return wiggleSort01(nums); //~230ms + } +}; 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/cpp/wordPattern/WordPattern.cpp b/algorithms/cpp/wordPattern/WordPattern.cpp index 8d67a0edb..0d319f110 100644 --- a/algorithms/cpp/wordPattern/WordPattern.cpp +++ b/algorithms/cpp/wordPattern/WordPattern.cpp @@ -34,7 +34,7 @@ private:: string tok; while(getline(ss, tok, delimiter)) { - internal.push_back(tok); + internal.push_back(tok); } return internal; 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/algorithms/js/twoSum/twoSum.js b/algorithms/js/twoSum/twoSum.js new file mode 100644 index 000000000..3a33d13e2 --- /dev/null +++ b/algorithms/js/twoSum/twoSum.js @@ -0,0 +1,36 @@ +// Source : https://oj.leetcode.com/problems/two-sum/ +// Author : Albin Zeng. +// Date : 2017-02-26 + +/********************************************************************************** +* +* Given an array of integers, find two numbers such that they add up to a specific target number. +* +* The function twoSum should return indices of the two numbers such that they add up to the target, +* where index1 must be less than index2. Please note that your returned answers (both index1 and index2) +* are not zero-based. +* +* You may assume that each input would have exactly one solution. +* +* Input: numbers={2, 7, 11, 15}, target=9 +* Output: index1=1, index2=2 +* +* +**********************************************************************************/ + +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ +var twoSum = function(nums, target) { + const map = {}; + let i = 0; + for (; i < nums.length; i++) { + if (undefined === map[target - nums[i]]) { + map[nums[i]] = i; + } else { + return [map[target - nums[i]], i]; + } + } +}; diff --git a/scripts/README.md b/scripts/README.md index 6972133fa..6349e5f00 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -44,3 +44,16 @@ The comments would be generated by above examples as below: ``` + +### readme.sh + +`readme.sh` - it's used to generate the table item in README.md + +For example: + +``` +$ ./readme.sh ../algorithms/cpp/nextPermutation/nextPermutation.cpp +|31|[Next Permutation](https://oj.leetcode.com/problems/next-permutation/) | [C++](./algorithms/cpp/nextPermutation/nextPermutation.cpp)|Medium| +``` + + 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 diff --git a/scripts/readme.sh b/scripts/readme.sh new file mode 100755 index 000000000..356c9613c --- /dev/null +++ b/scripts/readme.sh @@ -0,0 +1,33 @@ +#!/bin/bash + + +function usage() +{ + + echo -e "Usage: ${0} [file]" + echo -e "" + echo -e "Example:" + echo -e "" + echo -e " ${0} ./LargestNumber.cpp" + echo -e "" +} + + + +if [ $# -lt 1 ] || [[ ! -f ${1} ]]; then + usage + exit 255 +fi + +DIR=`cd $(dirname ${1}) && pwd -P` +FILE=${DIR}/$(basename ${1}) + +URL=`grep Source ${FILE} | awk '{print $4}'` +title_str=`xidel ${URL} -q -e "css('div.question-title h3')"` +NUM=`echo ${title_str} | awk -F '.' '{print $1}'` +TITLE=`echo ${title_str} | awk -F '.' '{print $2}' | sed -e 's/^[[:space:]]*//'` +DIFFCULT=`xidel ${URL} -q -e "css('.question-info')" | grep Difficulty | awk '{print $2}'` + +FILE=`echo ${FILE} | sed "s/.*\/algorithms/\.\/algorithms/"` + +echo "|${NUM}|[${TITLE}](${URL}) | [C++](${FILE})|${DIFFCULT}|"