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}|" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy