diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 000000000..e5adb6835 --- /dev/null +++ b/.gitconfig @@ -0,0 +1,4 @@ +[alias] + lg1 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all + lg2 = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --all + lg = !"git lg1" diff --git a/.gitignore b/.gitignore index 1f1c65c40..465b96430 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ .idea algorithms-java/out +*.class +*.out +*.vscode diff --git a/CppContainersNotes.txt b/CppContainersNotes.txt new file mode 100644 index 000000000..8f5048330 --- /dev/null +++ b/CppContainersNotes.txt @@ -0,0 +1,277 @@ +#include +using std::string; + +// Declaration & Initialization +string s1; // empty +string s2 = "hello"; // from literal +string s3(5, 'x'); // "xxxxx" +string s4 = s2 + " world"; // concatenation + +// Key Operations +s2 += "!"; // append (concatenate) +char c = s2[1]; // index access + +string sub = s2.substr(2, 3); // substring from pos=2 len=3 +size_t pos = s2.find("lo"); // find substring, returns index or npos +bool empty = s2.empty(); // is empty? +s2.clear(); // clear contents + +// Comparison +if (s2 == s4) +{ /* ... */ +} + +std::string s = "hi"; +s.push_back('!'); // hi! +// Note: Can only push one char at a time +s.pop_back() + +// if (result.ends_with(string(2, ch1))) // C++20 feature to check if the last two characters are same as ch1 + +/*TUPLE +๐Ÿ”น std::tuple +A tuple can hold heterogeneous types (different types). + +You access elements using std::get(). + +You can use it to group logically related but differently typed items (like a string, an int, and a float). +*/ +#include +#include +using namespace std; + +tuple person = {"Alice", 30, 55.5f}; +string name = get<0>(person); // "Alice" +int age = get<1>(person); // 30 +float weight = get<2>(person); // 55.5 + +maxHeap +By default a max heap is created. +And by default the first element will be used to compare. + +priority_queue> maxpq; + +auto cmp = [](const tuple& a, const tuple& b) { + return get<0>(a) < get<0>(b); // min-heap on the first element +}; +priority_queue, vector>, decltype(cmp)> pq(cmp); + + + + + + + +//Vector +#include +using std::vector; + +// 1D vector +vector v; // empty +vector v2(10); // size=10, default-initialized (0) +vector v3 = {1,2,3,4}; // initializer-list + +// 2D vector (matrix/graph adj list) +int rows = 5, cols = 4; +vector> mat(rows, vector(cols, 0)); +// or for adjacency list +vector> adj(n); + +// Common Ops +v.push_back(42); // append +v.pop_back(); // remove last +int x = v.back(); // access last +v.front(); // first element + +v.insert(v.begin()+i, 99);// insert at pos i +v.erase(v.begin()+i); // erase at pos i +v.clear(); // remove all + +// Searching & Sorting Helpers +#include +// assumes v sorted +auto it = std::lower_bound(v.begin(), v.end(), target); +auto it2 = std::upper_bound(v.begin(), v.end(), target); +// distance from begin gives index of first โ‰ฅ (lower) or > (upper) + +//Finding max element in the Vector +int maxVal = *max_element(a.begin(), a.end()); +Make sure the vector isn't empty before calling thisโ€”otherwise, max_element returns a.end(), and dereferencing that is ๐Ÿ‘ป undefined behavior. +if (!nums.empty()) { + int maxVal = *max_element(nums.begin(), nums.end()); +} + +vector nums = {4, 2, 9, 1, 6}; + +int maxVal = *max_element(nums.begin(), nums.end()); // 9 +int minVal = *min_element(nums.begin(), nums.end()); // 1 + +//Get index of the max element +int maxIdx = max_element(nums.begin(), nums.end()) - nums.begin(); +int minIdx = min_element(nums.begin(), nums.end()) - nums.begin(); + +//Say you have vector and want the longest string: +vector strs = {"cat", "tiger", "lion"}; + +auto it = max_element(strs.begin(), strs.end(), + [](const string &a, const string &b) { + return a.size() < b.size(); + }); + +string longest = *it; // "tiger" + +// With pair: Compare on second or custom rule +vector> arr = {{1, 10}, {2, 5}, {3, 15}}; + +// Max by second element +auto maxBySecond = max_element(arr.begin(), arr.end(), + [](auto &a, auto &b) { + return a.second < b.second; + }); +// *maxBySecond = {3, 15} + +//You can use std::max_element and std::min_element with any +//container that supports iterators, because they operate over +//iterator ranges โ€” not the container itself. + +std::list nums = {5, 3, 8, 1}; +int maxVal = *std::max_element(nums.begin(), nums.end()); // 8 + +std::set s = {1, 2, 3, 4}; +// max = *s.rbegin(); OR use max_element +int maxVal = *std::max_element(s.begin(), s.end()); // 4 + +struct Car { + string model; + int speed; +}; + +vector cars = {{"A", 100}, {"B", 150}, {"C", 120}}; + +auto fastest = max_element(cars.begin(), cars.end(), [](const Car& a, const Car& b) { + return a.speed < b.speed; +}); + +int val = 120; +int clamped = std::clamp(val, 0, 100); // clamped = 100 +/* +This means: + +"If val is too big, just return the max (100); +If it's too small, return the min (0); +Otherwise, return the value itself." + +| Function | Use For | +| ------------------------- | ---------------------------- | +| `std::max(a, b)` | Max of two values | +| `std::min(a, b)` | Min of two values | +| `std::max_element` | Max in a range | +| `std::min_element` | Min in a range | +| `std::clamp(val, lo, hi)` | Bound a value between limits | +*/ + + +#include +using std::list; + +list lst; // empty +list lst2(5, 0); // five zeros + +// Ops +lst.push_back(1); +lst.push_front(2); +lst.pop_back(); +lst.pop_front(); + +// Splicing, inserting at iterator +auto it = lst.begin(); +std::advance(it, 2); +lst.insert(it, 99); // O(1) +lst.erase(it); // O(1) + +// Deque +#include +using std::deque; + +deque dq; +dq.push_back(3); +dq.push_front(4); +dq.pop_back(); +dq.pop_front(); + +int a = dq[0]; // random access (slightly slower than vector) + +//Sets + +#include +using std::set; + +set st; +st.insert(5); +st.insert(1); +st.erase(5); +auto sit = st.find(1); // iterator or end() +bool exists = (sit != st.end()); + +//Unordered Sets +#include +using std::unordered_set; + +unordered_set us; +us.insert("abc"); +us.count("def"); // 0 or 1 + + +//Map + +#include +using std::map; + +map mp; +mp[1] = "one"; // insert or overwrite +mp.insert({2, "two"}); +mp.erase(1); +auto mit = mp.find(2); // iterator to pair or end() +if (mit != mp.end()) { + int key = mit->first; + string val = mit->second; +} + + + +// Unordered map +#include +using std::unordered_map; + +unordered_map ump; +ump["a"] = 10; +ump.count("b"); // 0 or 1 + + +//Queue Stacks + +#include +#include + +std::queue q; +q.push(1); +q.pop(); +int front = q.front(); + +std::stack stck; +stck.push(2); +stck.pop(); +int top = stck.top(); + + +//Searching Iteration +// Iterating +for (auto &x : v) { /* ... */ } +for (auto it = mp.begin(); it != mp.end(); ++it) { + // it->first, it->second +} + +// Generic find +#include +auto pos = std::find(v.begin(), v.end(), target); +if (pos != v.end()) { /* found */ } diff --git a/README.md b/README.md index 3f71fe9be..b214c7d3f 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,90 @@ LeetCode ======== -###LeetCode Algorithm +### LeetCode Algorithm (Notes: "♥" means you need to buy a book from Leetcode) | # | Title | Solution | Difficulty | |---| ----- | -------- | ---------- | +|859|[Buddy Strings](https://leetcode.com/problems/buddy-strings/description/) | [C++](./algorithms/cpp/buddyStrings/BuddyStrings.cpp)|Easy| +|858|[Mirror Reflection](https://leetcode.com/problems/mirror-reflection/description/) | [C++](./algorithms/cpp/mirrorReflection/MirrorReflection.cpp)|Medium| +|852|[Peak Index in a Mountain Array](https://leetcode.com/problems/peak-index-in-a-mountain-array/description/) | [C++](./algorithms/cpp/peakIndexInAMountainArray/PeakIndexInAMountainArray.cpp)|Easy| +844|[Backspace String Compare](https://leetcode.com/problems/backspace-string-compare/description/) | [C++](./algorithms/cpp/backspaceStringCompare/BackspaceStringCompare.cpp)|Easy| +|837|[Most Common Word](https://leetcode.com/problems/most-common-word/) | [C++](./algorithms/cpp/mostCommonWord/MostCommonWord.cpp)|Easy| +|804|[Unique Morse Code Words](https://leetcode.com/problems/unique-morse-code-words/description/) | [C++](./algorithms/cpp/uniqueMorseCodeWords/UniqueMorseCodeWords.cpp)|Easy| +|771|[Jewels and Stones](https://leetcode.com/problems/jewels-and-stones/description) | [C++](./algorithms/cpp/jewelsAndStones/JewelsAndStones.cpp)|Easy| +|643|[Maximum Average Subarray I](https://leetcode.com/problems/maximum-average-subarray-i/description/) | [C++](./algorithms/cpp/maximumAverageSubarray/MaximumAverageSubarray.I.cpp)|Easy| +|477|[Total Hamming Distance](https://leetcode.com/problems/total-hamming-distance/) | [C++](./algorithms/cpp/totalHammingDistance/totalHammingDistance.cpp)|Medium| +|418|[SentenceScreenFitting](https://leetcode.com/problems/sentence-screen-fitting/) ♥ | [C++](./algorithms/cpp/sentenceScreenFitting/sentenceScreenFitting.cpp)|Easy| +|416|[Partition Equal Subset Sum](https://leetcode.com/problems/partition-equal-subset-sum/description/) | [C++](./algorithms/cpp/partitionEqualSubsetSum/PartitionEqualSubsetSum.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| +|371|[Sum of Two Integers](https://leetcode.com/problems/sum-of-two-integers/description/) | [C++](./algorithms/cpp/sumOfTwoIntegers/SumOfTwoIntegers.cpp)|Easy| +|367|[Valid Perfect Square](https://leetcode.com/problems/valid-perfect-square/description/) | [C++](./algorithms/cpp/validPerfectSquare/ValidPerfectSquare.cpp)|Easy| +|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| +|336|[Palindrome Pairs](https://leetcode.com/problems/palindrome-pairs/) | [C++](./algorithms/cpp/palindromePairs/PalindromePairs.cpp)|Hard| +|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 +100,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,11 +109,12 @@ 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| +|242|[Valid Anagram](https://leetcode.com/problems/valid-anagram/)| [C++](./algorithms/cpp/anagrams/ValidAnagram.cpp), [Java](./algorithms/java/src/validAnagram/ValidAnagram.java)|Easy| |241|[Different Ways to Add Parentheses](https://leetcode.com/problems/different-ways-to-add-parentheses/)|[C++](./algorithms/cpp/differentWaysToAddParentheses/DifferentWaysToAddParentheses.cpp)|Medium| -|240|[Search a 2D Matrix II](https://leetcode.com/problems/search-a-2d-matrix-ii/)|[C++](./algorithms/cpp/search2DMatrix/search2DMatrix.II.cpp)|Medium| +|240|[Search a 2D Matrix II](https://leetcode.com/problems/search-a-2d-matrix-ii/)|[C++](./algorithms/cpp/search2DMatrix/search2DMatrix.II.cpp), [Java](./algorithms/java/src/searchA2DMatrixII/SearchA2DMatrixII.java)|Medium| |239|[Sliding Window Maximum](https://leetcode.com/problems/sliding-window-maximum/)| [C++](./algorithms/cpp/slidingWindowMaximum/SlidingWindowMaximum.cpp)|Hard| |238|[Product of Array Except Self](https://leetcode.com/problems/product-of-array-except-self/)| [C++](./algorithms/cpp/productOfArrayExceptSelf/ProductOfArrayExceptSelf.cpp)|Medium| |237|[Delete Node in a Linked List](https://leetcode.com/problems/delete-node-in-a-linked-list/)| [C++](./algorithms/cpp/deleteNodeInALinkedList/DeleteNodeInALinkedList.cpp)|Easy| @@ -44,14 +122,14 @@ LeetCode |235|[Lowest Common Ancestor of a Binary Search Tree](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/)| [C++](./algorithms/cpp/lowestCommonAncestorOfABinarySearchTree/LowestCommonAncestorOfABinarySearchTree.cpp)|Easy| |234|[Palindrome Linked List](https://leetcode.com/problems/palindrome-linked-list/)| [C++](./algorithms/cpp/palindromeLinkedList/PalindromeLinkedList.cpp)|Easy| |233|[Number of Digit One](https://leetcode.com/problems/number-of-digit-one/)| [C++](./algorithms/cpp/numberOfDigitOne/NumberOfDigitOne.cpp)|Medium| -|232|[Implement Queue using Stacks](https://leetcode.com/problems/implement-queue-using-stacks/)| [C++](./algorithms/cpp/implementQueueUsingStacks/ImplementQueueUsingStacks.cpp)|Easy| +|232|[Implement Queue using Stacks](https://leetcode.com/problems/implement-queue-using-stacks/)| [C++](./algorithms/cpp/implementQueueUsingStacks/ImplementQueueUsingStacks.cpp), [Java](./algorithms/java/src/myQueue/MyQueue.java)|Easy| |231|[Power of Two](https://leetcode.com/problems/power-of-two/)| [C++](./algorithms/cpp/powerOfTwo/PowerOfTwo.cpp)|Easy| |230|[Kth Smallest Element in a BST](https://leetcode.com/problems/kth-smallest-element-in-a-bst/)| [C++](./algorithms/cpp/kthSmallestElementInaBST/KthSmallestElementInABst.cpp)|Medium| |229|[Majority Element II](https://oj.leetcode.com/problems/majority-element-ii/) | [C++](./algorithms/cpp/majorityElement/majorityElement.II.cpp)|Medium| |228|[Summary Ranges](https://leetcode.com/problems/summary-ranges/)| [C++](./algorithms/cpp/summaryRanges/SummaryRanges.cpp)|Easy| |227|[Basic Calculator II](https://leetcode.com/problems/basic-calculator-ii/)| [C++](./algorithms/cpp/basicCalculator/BasicCalculator.II.cpp)|Medium| |226|[Invert Binary Tree](https://leetcode.com/problems/invert-binary-tree/)| [C++](./algorithms/cpp/invertBinaryTree/InvertBinaryTree.cpp)|Easy| -|225|[Implement Stack using Queues](https://leetcode.com/problems/implement-stack-using-queues/)| [C++](./algorithms/cpp/implementStackUsingQueues/ImplementStackUsingQueues.cpp)|Medium| +|225|[Implement Stack using Queues](https://leetcode.com/problems/implement-stack-using-queues/)| [C++](./algorithms/cpp/implementStackUsingQueues/ImplementStackUsingQueues.cpp), [Java](./algorithms/java/src/myStack/MyStack.java)|Medium| |224|[Basic Calculator](https://leetcode.com/problems/basic-calculator/)| [C++](./algorithms/cpp/basicCalculator/BasicCalculator.cpp)|Medium| |223|[Rectangle Area](https://leetcode.com/problems/rectangle-area/)| [C++](./algorithms/cpp/rectangleArea/RectangleArea.cpp)|Easy| |222|[Count Complete Tree Nodes](https://leetcode.com/problems/count-complete-tree-nodes/)| [C++](./algorithms/cpp/countCompleteTreeNodes/CountCompleteTreeNodes.cpp)|Medium| @@ -70,7 +148,7 @@ LeetCode |209|[Minimum Size Subarray Sum](https://leetcode.com/problems/minimum-size-subarray-sum/)| [C++](./algorithms/cpp/minimumSizeSubarraySum/MinimumSizeSubarraySum.cpp)|Medium| |208|[Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree/)| [C++](./algorithms/cpp/implementTriePrefixTree/ImplementTriePrefixTree.cpp)|Medium| |207|[Course Schedule](https://leetcode.com/problems/course-schedule/)| [C++](./algorithms/cpp/courseSchedule/CourseSchedule.cpp)|Medium| -|206|[Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/)| [C++](./algorithms/cpp/reverseLinkedList/reverseLinkedList.cpp)|Easy| +|206|[Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/)| [C++](./algorithms/cpp/reverseLinkedList/reverseLinkedList.cpp), [Java](./algorithms/java/src/reverseLinkedList/ReverseLinkedList.java)|Easy| |205|[Isomorphic Strings](https://leetcode.com/problems/isomorphic-strings/)| [C++](./algorithms/cpp/isomorphicStrings/IsomorphicStrings.cpp)|Easy| |204|[Count Primes](https://leetcode.com/problems/count-primes/)| [C++](./algorithms/cpp/countPrimes/CountPrimes.cpp)|Easy| |203|[Remove Linked List Elements](https://leetcode.com/problems/remove-linked-list-elements/)| [C++](./algorithms/cpp/removeLinkedListElements/RemoveLinkedListElements.cpp)|Easy| @@ -81,7 +159,7 @@ LeetCode |198|[House Robber](https://leetcode.com/problems/house-robber/)| [C++](./algorithms/cpp/houseRobber/houseRobber.cpp)|Easy| |191|[Number of 1 Bits](https://oj.leetcode.com/problems/number-of-1-bits/)| [C++](./algorithms/cpp/numberOf1Bits/numberOf1Bits.cpp)|Easy| |190|[Reverse Bits](https://oj.leetcode.com/problems/reverse-bits/)| [C++](./algorithms/cpp/reverseBits/reverseBits.cpp)|Easy| -|189|[Rotate Array](https://oj.leetcode.com/problems/rotate-array/)| [C++](./algorithms/cpp/rotateArray/rotateArray.cpp)|Easy| +|189|[Rotate Array](https://oj.leetcode.com/problems/rotate-array/)| [C++](./algorithms/cpp/rotateArray/rotateArray.cpp), [Java](./algorithms/java/src/rotateArray/RotateArray.java)|Easy| |188|[Best Time to Buy and Sell Stock IV](https://oj.leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/)| [C++](./algorithms/cpp/bestTimeToBuyAndSellStock/bestTimeToBuyAndSellStock.IV.cpp)|Hard| |187|[Repeated DNA Sequences](https://oj.leetcode.com/problems/repeated-dna-sequences/)| [C++](./algorithms/cpp/repeatedDNASequences/repeatedDNASequences.cpp)|Medium| |186|[Reverse Words in a String II](https://oj.leetcode.com/problems/reverse-words-in-a-string-ii/) ♥ | [C++](./algorithms/cpp/reverseWordsInAString/reverseWordsInAString.II.cpp)|Medium| @@ -105,16 +183,16 @@ LeetCode |158|[Read N Characters Given Read4 II - Call multiple times](https://oj.leetcode.com/problems/read-n-characters-given-read4-ii-call-multiple-times/) ♥ | [C++](./algorithms/cpp/readNCharactersGivenRead4/readNCharactersGivenRead4.II.cpp)|Hard| |157|[Read N Characters Given Read4](https://oj.leetcode.com/problems/read-n-characters-given-read4/) ♥ | [C++](./algorithms/cpp/readNCharactersGivenRead4/readNCharactersGivenRead4.cpp)|Easy| |156|[Binary Tree Upside Down](https://oj.leetcode.com/problems/binary-tree-upside-down/) ♥ | [C++](./algorithms/cpp/binaryTreeUpsideDown/binaryTreeUpsideDown.cpp)|Medium| -|155|[Min Stack](https://oj.leetcode.com/problems/min-stack/)| [C++](./algorithms/cpp/minStack/minStack.cpp)|Easy| +|155|[Min Stack](https://oj.leetcode.com/problems/min-stack/)| [C++](./algorithms/cpp/minStack/minStack.cpp), [Java](./algorithms/java/src/minStack/MinStack.java)|Easy| |154|[Find Minimum in Rotated Sorted Array II](https://oj.leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/)| [C++](./algorithms/cpp/findMinimumInRotatedSortedArray/findMinimumInRotatedSortedArray.II.cpp)|Hard| |153|[Find Minimum in Rotated Sorted Array](https://oj.leetcode.com/problems/find-minimum-in-rotated-sorted-array/)| [C++](./algorithms/cpp/findMinimumInRotatedSortedArray/findMinimumInRotatedSortedArray.cpp), [Java](./algorithms/java/src/findMinimumInRotatedSortedArray/findMinimumInRotatedSortedArray.java)|Medium| |152|[Maximum Product Subarray](https://oj.leetcode.com/problems/maximum-product-subarray/)| [C++](./algorithms/cpp/maximumProductSubarray/maximumProductSubarray.cpp)|Medium| -|151|[Reverse Words in a String](https://oj.leetcode.com/problems/reverse-words-in-a-string/)| [C++](./algorithms/cpp/reverseWordsInAString/reverseWordsInAString.cpp)|Medium| +|151|[Reverse Words in a String](https://oj.leetcode.com/problems/reverse-words-in-a-string/)| [C++](./algorithms/cpp/reverseWordsInAString/reverseWordsInAString.cpp), [Java](./algorithms/java/src/reverseWordsInAString/ReverseWordsInAString.java)|Medium| |150|[Evaluate Reverse Polish Notation](https://oj.leetcode.com/problems/evaluate-reverse-polish-notation/)| [C++](./algorithms/cpp/evaluateReversePolishNotation/evaluateReversePolishNotation.cpp)|Medium| |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| @@ -135,7 +213,7 @@ LeetCode |128|[Longest Consecutive Sequence](https://oj.leetcode.com/problems/longest-consecutive-sequence/)| [C++](./algorithms/cpp/longestConsecutiveSequence/longestConsecutiveSequence.cpp)|Hard| |127|[Word Ladder](https://oj.leetcode.com/problems/word-ladder/)| [C++](./algorithms/cpp/wordLadder/wordLadder.cpp)|Medium| |126|[Word Ladder II](https://oj.leetcode.com/problems/word-ladder-ii/)| [C++](./algorithms/cpp/wordLadder/wordLadder.II.cpp)|Hard| -|125|[Valid Palindrome](https://oj.leetcode.com/problems/valid-palindrome/)| [C++](./algorithms/cpp/validPalindrome/validPalindrome.cpp)|Easy| +|125|[Valid Palindrome](https://oj.leetcode.com/problems/valid-palindrome/)| [C++](./algorithms/cpp/validPalindrome/validPalindrome.cpp), [Java](./algorithms/java/src/validPalindrome/ValidPalindrome.java)|Easy| |124|[Binary Tree Maximum Path Sum](https://oj.leetcode.com/problems/binary-tree-maximum-path-sum/)| [C++](./algorithms/cpp/binaryTreeMaximumPathSum/binaryTreeMaximumPathSum.cpp), [Java](./algorithms/java/src/binaryTreeMaximumPathSum/binaryTreeMaximumPathSum.java)|Hard| |123|[Best Time to Buy and Sell Stock III](https://oj.leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/)| [C++](./algorithms/cpp/bestTimeToBuyAndSellStock/bestTimeToBuyAndSellStock.III.cpp)|Hard| |122|[Best Time to Buy and Sell Stock II](https://oj.leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/)| [C++](./algorithms/cpp/bestTimeToBuyAndSellStock/bestTimeToBuyAndSellStock.II.cpp)|Medium| @@ -168,7 +246,7 @@ LeetCode |95|[Unique Binary Search Trees II](https://oj.leetcode.com/problems/unique-binary-search-trees-ii/)| [C++](./algorithms/cpp/uniqueBinarySearchTrees/uniqueBinarySearchTrees.II.cpp)|Medium| |94|[Binary Tree Inorder Traversal](https://oj.leetcode.com/problems/binary-tree-inorder-traversal/)| [C++](./algorithms/cpp/binaryTreeInorderTraversal/binaryTreeInorderTraversal.cpp)|Medium| |93|[Restore IP Addresses](https://oj.leetcode.com/problems/restore-ip-addresses/)| [C++](./algorithms/cpp/restoreIPAddresses/restoreIPAddresses.cpp)|Medium| -|92|[Reverse Linked List II](https://oj.leetcode.com/problems/reverse-linked-list-ii/)| [C++](./algorithms/cpp/reverseLinkedList/reverseLinkedList.II.cpp)|Medium| +|92|[Reverse Linked List II](https://oj.leetcode.com/problems/reverse-linked-list-ii/)| [C++](./algorithms/cpp/reverseLinkedList/reverseLinkedList.II.cpp), [Java](./algorithms/java/src/reverseLinkedListII/ReverseLinkedListII.java)|Medium| |91|[Decode Ways](https://oj.leetcode.com/problems/decode-ways/)| [C++](./algorithms/cpp/decodeWays/decodeWays.cpp)|Medium| |90|[Subsets II](https://oj.leetcode.com/problems/subsets-ii/)| [C++](./algorithms/cpp/subsets/subsets.II.cpp), [Java](./algorithms/java/src/subsets/subsetsII.java)|Medium| |89|[Gray Code](https://oj.leetcode.com/problems/gray-code/)| [C++](./algorithms/cpp/grayCode/grayCode.cpp)|Medium| @@ -202,7 +280,7 @@ LeetCode |61|[Rotate List](https://oj.leetcode.com/problems/rotate-list/)| [C++](./algorithms/cpp/rotateList/rotateList.cpp)|Medium| |60|[Permutation Sequence](https://oj.leetcode.com/problems/permutation-sequence/)| [C++](./algorithms/cpp/permutationSequence/permutationSequence.cpp)|Medium| |59|[Spiral Matrix II](https://oj.leetcode.com/problems/spiral-matrix-ii/)| [C++](./algorithms/cpp/spiralMatrix/spiralMatrix.II.cpp)|Medium| -|58|[Length of Last Word](https://oj.leetcode.com/problems/length-of-last-word/)| [C++](./algorithms/cpp/lengthOfLastWord/lengthOfLastWord.cpp)|Easy| +|58|[Length of Last Word](https://oj.leetcode.com/problems/length-of-last-word/)| [C++](./algorithms/cpp/lengthOfLastWord/lengthOfLastWord.cpp), [Java](./algorithms/java/src/lengthOfLastWord/LengthOfLastWord.java)|Easy| |57|[Insert Interval](https://oj.leetcode.com/problems/insert-interval/)| [C++](./algorithms/cpp/insertInterval/insertInterval.cpp)|Hard| |56|[Merge Intervals](https://oj.leetcode.com/problems/merge-intervals/)| [C++](./algorithms/cpp/mergeIntervals/mergeIntervals.cpp)|Hard| |55|[Jump Game](https://oj.leetcode.com/problems/jump-game/)| [C++](./algorithms/cpp/jumpGame/jumpGame.cpp)|Medium| @@ -210,7 +288,7 @@ LeetCode |53|[Maximum Subarray](https://oj.leetcode.com/problems/maximum-subarray/)| [C++](./algorithms/cpp/maximumSubArray/maximumSubArray.cpp)|Medium| |52|[N-Queens II](https://oj.leetcode.com/problems/n-queens-ii/)| [C++](./algorithms/cpp/nQueens/nQueuens.II.cpp)|Hard| |51|[N-Queens](https://oj.leetcode.com/problems/n-queens/)| [C++](./algorithms/cpp/nQueens/nQueuens.cpp)|Hard| -|50|["Pow(x, n)"](https://oj.leetcode.com/problems/powx-n/)| [C++](./algorithms/cpp/pow/pow.cpp)|Medium| +|50|["Pow(x, n)"](https://oj.leetcode.com/problems/powx-n/)| [C++](./algorithms/cpp/pow/pow.cpp), [Java](./algorithms/java/src/powXn/PowXn.java)|Medium| |49|[Group Anagrams](https://oj.leetcode.com/problems/anagrams/)| [C++](./algorithms/cpp/anagrams/GroupAnagrams.cpp)|Medium| |48|[Rotate Image](https://oj.leetcode.com/problems/rotate-image/)| [C++](./algorithms/cpp/rotateImage/rotateImage.cpp)|Medium| |47|[Permutations II](https://oj.leetcode.com/problems/permutations-ii/)| [C++](./algorithms/cpp/permutations/permutations.II.cpp)|Hard| @@ -222,7 +300,7 @@ LeetCode |41|[First Missing Positive](https://oj.leetcode.com/problems/first-missing-positive/)| [C++](./algorithms/cpp/firstMissingPositive/firstMissingPositive.cpp)|Hard| |40|[Combination Sum II](https://oj.leetcode.com/problems/combination-sum-ii/)| [C++](./algorithms/cpp/combinationSum/combinationSum.II.cpp)|Medium| |39|[Combination Sum](https://oj.leetcode.com/problems/combination-sum/)| [C++](./algorithms/cpp/combinationSum/combinationSum.cpp)|Medium| -|38|[Count and Say](https://oj.leetcode.com/problems/count-and-say/)| [C++](./algorithms/cpp/countAndSay/countAndSay.cpp)|Easy| +|38|[Count and Say](https://oj.leetcode.com/problems/count-and-say/)| [C++](./algorithms/cpp/countAndSay/countAndSay.cpp), [Java](./algorithms/java/src/countAndSay/CountAndSay.java)|Easy| |37|[Sudoku Solver](https://oj.leetcode.com/problems/sudoku-solver/)| [C++](./algorithms/cpp/sudokuSolver/sudokuSolver.cpp)|Hard| |36|[Valid Sudoku](https://oj.leetcode.com/problems/valid-sudoku/)| [C++](./algorithms/cpp/validSudoku/validSudoku.cpp)|Easy| |35|[Search Insert Position](https://oj.leetcode.com/problems/search-insert-position/)| [C++](./algorithms/cpp/searchInsertPosition/searchInsertPosition.cpp), [Java](./algorithms/java/src/searchInsertPosition/searchInsertPosition.java)|Medium| @@ -234,7 +312,7 @@ LeetCode |29|[Divide Two Integers](https://oj.leetcode.com/problems/divide-two-integers/)| [C++](./algorithms/cpp/divideTwoInt/divideTwoInt.cpp)|Medium| |28|[Implement strStr()](https://oj.leetcode.com/problems/implement-strstr/)| [C++](./algorithms/cpp/strStr/strStr.cpp), [Java](./algorithms/java/src/strStr/strStr.java)|Easy| |27|[Remove Element](https://oj.leetcode.com/problems/remove-element/)| [C++](./algorithms/cpp/removeElement/removeElement.cpp)|Easy| -|26|[Remove Duplicates from Sorted Array](https://oj.leetcode.com/problems/remove-duplicates-from-sorted-array/)| [C++](./algorithms/cpp/removeDuplicatesFromSortedArray/removeDuplicatesFromSortedArray.cpp)|Easy| +|26|[Remove Duplicates from Sorted Array](https://oj.leetcode.com/problems/remove-duplicates-from-sorted-array/)| [C++](./algorithms/cpp/removeDuplicatesFromSortedArray/removeDuplicatesFromSortedArray.cpp), [Java](./algorithms/java/src/removeDuplicatesFromSortedArray/RemoveDuplicatesFromSortedArray.java)|Easy| |25|[Reverse Nodes in k-Group](https://oj.leetcode.com/problems/reverse-nodes-in-k-group/)| [C++](./algorithms/cpp/reverseNodesInKGroup/reverseNodesInKGroup.cpp)|Hard| |24|[Swap Nodes in Pairs](https://oj.leetcode.com/problems/swap-nodes-in-pairs/)| [C++](./algorithms/cpp/swapNodesInPairs/swapNodesInPairs.cpp)|Medium| |23|[Merge k Sorted Lists](https://oj.leetcode.com/problems/merge-k-sorted-lists/)| [C++](./algorithms/cpp/mergeKSortedLists/mergeKSortedLists.cpp)|Hard| @@ -251,7 +329,7 @@ LeetCode |12|[Integer to Roman](https://oj.leetcode.com/problems/integer-to-roman/)| [C++](./algorithms/cpp/integerToRoman/integerToRoman.cpp)|Medium| |11|[Container With Most Water](https://oj.leetcode.com/problems/container-with-most-water/)| [C++](./algorithms/cpp/containerWithMostWater/containerWithMostWater.cpp)|Medium| |10|[Regular Expression Matching](https://oj.leetcode.com/problems/regular-expression-matching/)| [C++](./algorithms/cpp/regularExpressionMatching/regularExpressionMatching.cpp)|Hard| -|9|[Palindrome Number](https://oj.leetcode.com/problems/palindrome-number/)| [C++](./algorithms/cpp/palindromeNumber/palindromeNumber.cpp)|Easy| +|9|[Palindrome Number](https://oj.leetcode.com/problems/palindrome-number/)| [C++](./algorithms/cpp/palindromeNumber/palindromeNumber.cpp), [Java](./algorithms/java/src/palindromeNumber/PalindromeNumber.java)|Easy| |8|[String to Integer (atoi)](https://oj.leetcode.com/problems/string-to-integer-atoi/)| [C++](./algorithms/cpp/stringToIntegerAtoi/stringToIntegerAtoi.cpp)|Easy| |7|[Reverse Integer](https://oj.leetcode.com/problems/reverse-integer/)| [C++](./algorithms/cpp/reverseInteger/reverseInteger.cpp)|Easy| |6|[ZigZag Conversion](https://oj.leetcode.com/problems/zigzag-conversion/)| [C++](./algorithms/cpp/zigZagConversion/zigZagConversion.cpp)|Easy| @@ -262,7 +340,7 @@ LeetCode |1|[Two Sum](https://oj.leetcode.com/problems/two-sum/)| [C++](./algorithms/cpp/twoSum/twoSum.cpp)|Medium| -###LeetCode Shell +### LeetCode Shell | # | Title | Solution | Difficulty | @@ -272,7 +350,8 @@ LeetCode |2|[Valid Phone Numbers](https://leetcode.com/problems/valid-phone-numbers/)| [Bash](./shell/ValidPhoneNumbers.sh)|Easy| |1|[Word Frequency](https://leetcode.com/problems/word-frequency/)| [Bash](./shell/WordFrequency.sh)|Medium| -###LintCode +### LintCode + | # | Title | Solution | Difficulty | |---| ----- | -------- | ---------- | |1|[Search in a big sorted array](http://www.lintcode.com/en/problem/search-in-a-big-sorted-array/)|[Java](./algorithms/java/src/searchInABigSortedArray/searchInABigSortedArray.java)|Medium| diff --git a/algorithms/cpp/3Sum/3Sum.cpp b/algorithms/cpp/3Sum/3Sum.cpp index 0b38716e4..ada7dba86 100644 --- a/algorithms/cpp/3Sum/3Sum.cpp +++ b/algorithms/cpp/3Sum/3Sum.cpp @@ -30,7 +30,7 @@ using namespace std; /* - * Simlar like "Two Number" problem, we can have the simlar solution. + * Similar like "Two Number" problem, we can have the simlar solution. * * Suppose the input array is S[0..n-1], 3SUM can be solved in O(n^2) time on average by * inserting each number S[i] into a hash table, and then for each index i and j, @@ -47,6 +47,7 @@ using namespace std; vector > threeSum(vector &num) { vector< vector > result; + if(num.size()==0 || num.size()==1 || num.size() == 2) return result; //sort the array, this is the key sort(num.begin(), num.end()); @@ -71,7 +72,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 +82,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; i0 ? 2 : 1; + s.erase(i-backSteps + 1, backSteps); + i -= backSteps; + } + } + } + +public: + bool backspaceCompare(string S, string T) { + removeBackspaces(S); + removeBackspaces(T); + return S == T; + } +}; diff --git a/algorithms/cpp/binaryWatch/BinaryWatch.cpp b/algorithms/cpp/binaryWatch/BinaryWatch.cpp new file mode 100644 index 000000000..26c59425c --- /dev/null +++ b/algorithms/cpp/binaryWatch/BinaryWatch.cpp @@ -0,0 +1,111 @@ +// Source : https://leetcode.com/problems/binary-watch/ +// Author : Hao Chen +// Date : 2016-11-05 + +/*************************************************************************************** + * + * A binary watch has 4 LEDs on the top which represent the hours (0-11), and the 6 + * LEDs on the bottom represent the minutes (0-59). + * Each LED represents a zero or one, with the least significant bit on the right. + * + * For example, the above binary watch reads "3:25". + * + * Given a non-negative integer n which represents the number of LEDs that are + * currently on, return all possible times the watch could represent. + * + * Example: + * Input: n = 1Return: ["1:00", "2:00", "4:00", "8:00", "0:01", "0:02", "0:04", "0:08", + * "0:16", "0:32"] + * + * Note: + * + * The order of output does not matter. + * The hour must not contain a leading zero, for example "01:00" is not valid, it + * should be "1:00". + * The minute must be consist of two digits and may contain a leading zero, for example + * "10:2" is not valid, it should be "10:02". + ***************************************************************************************/ + +class Solution { +private: + void combination(int nLED, int nLight, int max, bool zero, + int start, int k, int solution, + vector>& 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/buddyStrings/BuddyStrings.cpp b/algorithms/cpp/buddyStrings/BuddyStrings.cpp new file mode 100644 index 000000000..41b0b5ea9 --- /dev/null +++ b/algorithms/cpp/buddyStrings/BuddyStrings.cpp @@ -0,0 +1,94 @@ +// Source : https://leetcode.com/problems/buddy-strings/description/ +// Author : Hao Chen +// Date : 2018-06-27 + +/*************************************************************************************** + * + * Given two strings A and B of lowercase letters, return true if and only if we can + * swap two letters in A so that the result equals B. + * + * + * + * Example 1: + * + * + * + * Input: A = "ab", B = "ba" + * Output: true + * + * + * + * Example 2: + * + * + * Input: A = "ab", B = "ab" + * Output: false + * + * + * + * Example 3: + * + * + * Input: A = "aa", B = "aa" + * Output: true + * + * + * + * Example 4: + * + * + * Input: A = "aaaaaaabc", B = "aaaaaaacb" + * Output: true + * + * + * + * Example 5: + * + * + * Input: A = "", B = "aa" + * Output: false + * + * + * + * + * Note: + * + * + * 0 <= A.length <= 20000 + * 0 <= B.length <= 20000 + * A and B consist only of lowercase letters. + * + * + * + * + * + ***************************************************************************************/ + + + +class Solution { +public: + bool buddyStrings(string A, string B) { + if (A.size() != B.size()) return false; + if (A.size()<2) return false; + + bool bRepeat = false; + bool map[26] = {false}; + int idx[2], diffCnt=0; + + for (int i=0; i=2) return false; + idx[diffCnt++] = i; + + } + } + //if A == B and there has repeated chars , then return true + if (diffCnt==0 && bRepeat) return true; + + return (A[idx[0]] == B[idx[1]] && A[idx[1]] == B[idx[0]]); + + } +}; 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/courseSchedule/non-recursive/course_schedule.cpp b/algorithms/cpp/courseSchedule/non-recursive/course_schedule.cpp new file mode 100644 index 000000000..b7decde33 --- /dev/null +++ b/algorithms/cpp/courseSchedule/non-recursive/course_schedule.cpp @@ -0,0 +1,149 @@ +// +// course_schedule.cpp +// LeeteCodeOJ#207 +// +// Created by Wang Yi on 28/11/16. +// Copyright (c) 2016 Wang Yi. All rights reserved. +// + +#include + +#include +#include +#include +#include + +using std::stack; +using std::queue; +using std::vector; +using std::unordered_set; +using std::pair; + +typedef pair Val; +typedef vector> Graph; + +#define FOR(s, e) \ +for (s = 0; s < e; s++) { +#define END ;} + + typedef struct _node { + int val; + // int depth; + struct _node * parent; + } node; + + class Solution { + public: + bool canFinish(int numCourses, vector>& prerequisites) { + vector outdepth(numCourses, 0); + unordered_set vex; + if ((int) prerequisites.size() == 0) + return true; + vector> graph = to_neighbor_repr(numCourses, prerequisites, outdepth); + + return dsf(numCourses, graph, outdepth); + } + + vector> to_neighbor_repr(int numOfvex, vector& edges, + vector& outdepth) { + // std::cout << "building ... " << std::endl; + vector> graph(numOfvex); + for (auto edge : edges) { + graph[edge.second].insert(edge.first); // second -> first + outdepth[edge.second]++; + // std::cout << edge.first << " <- " << edge.second << std::endl; + } + + return graph; + + } + + + bool dsf(int numOfvex, vector>& graph, vector& outdepth) + { + // preparation + stack s; + vector visited(numOfvex, false); + vector onpath(numOfvex, false); + vector starts; + + int i; + + unordered_set children; + + + FOR(i, numOfvex) + if (outdepth[i] !=0 ) { + starts.push_back(i); + } + END + + if ((int)starts.size() == 0) + return false; // no vertex with indepth of 0 found, a circle found + + for (auto j: starts) { + // std::cout << "start from " << j << std::endl; + // do dsf search, if not visited + // when a circle in a path found, return false. + // else return true + if (visited[j]) + continue; + + node head; + head.val = j; + head.parent = NULL; + // head.depth = 1; + s.push(head); + + // non-recursive search + while (!s.empty()) { + node* curr = &(s.top()); + + if (visited[curr->val]) { + // all children have been read + s.pop(); + onpath[curr->val] = false; + continue; // ignore ... + } + + onpath[curr->val] = visited[curr->val]= true; + children = graph[curr->val]; + + if ((int)children.size() == 0) { + s.pop(); + onpath[curr->val] = false; + // std::cout << "==== reach the end ===="<val << "'s children is: "; + for (auto child: children) { + // std::cout << child << " "; + //if (onpath.find(child) == onpath.end()) + if (onpath[child]) { + + // std::cout << std::endl << "a circle found:" << std::endl; + // std::cout << child << " <- "; + // while (curr->parent != NULL) { + // std::cout << curr->val << " <- "; + // curr = curr->parent; + // } + // std::cout << curr->val << std::endl; + + return false; // a circle found, might print debug here + } + + node nd; + nd.val = child; + // nd.depth = curr->depth+1; + nd.parent = curr; // for debug purpose ... + s.push(nd); + } + // std::cout << std::endl; + } + + } // end of for + return true; + } + + }; \ No newline at end of file diff --git a/algorithms/cpp/courseSchedule/non-recursive/main.cpp b/algorithms/cpp/courseSchedule/non-recursive/main.cpp new file mode 100644 index 000000000..f667c8796 --- /dev/null +++ b/algorithms/cpp/courseSchedule/non-recursive/main.cpp @@ -0,0 +1,30 @@ +// +// main.cpp +// LeeteCodeOJ#207 +// +// Created by Wang Yi on 28/11/16. +// Copyright (c) 2016 Wang Yi. All rights reserved. +// + +#include +#include +#include + +#include "course_schedule.cpp" + +using std::make_pair; + +int main(int argc, const char * argv[]) { + // insert code here... + Solution sl; + int numCourses = 4; + vector prerequisites; + prerequisites.push_back(make_pair(0,1)); + prerequisites.push_back(make_pair(3,1)); + prerequisites.push_back(make_pair(1,3)); + prerequisites.push_back(make_pair(3,2)); + + + std::cout << sl.canFinish(numCourses, prerequisites); + return 0; +} 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..79e32cbd8 --- /dev/null +++ b/algorithms/cpp/intersectionOfTwoArrays/intersectionOfTwoArrays.cpp @@ -0,0 +1,72 @@ +// Source : https://leetcode.com/problems/intersection-of-two-arrays/ +// Author : Calinescu Valentin, Hao Chen +// 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; + } +}; + +/* + * This Solution use unordered_map, insert the data into a map is more efficent than set + */ + +class Solution { +public: + vector intersection(vector& nums1, vector& nums2) { + unordered_map m; + for (auto n : nums1) { + m[n] = true; + } + vector result; + for (auto n : nums2){ + if (m.find(n) != m.end() && m[n] ){ + result.push_back(n); + m[n]=false; + } + } + return result; + } +}; + diff --git a/algorithms/cpp/intersectionOfTwoArrays/intersectionOfTwoArraysII.cpp b/algorithms/cpp/intersectionOfTwoArrays/intersectionOfTwoArraysII.cpp new file mode 100644 index 000000000..9384d96da --- /dev/null +++ b/algorithms/cpp/intersectionOfTwoArrays/intersectionOfTwoArraysII.cpp @@ -0,0 +1,87 @@ +// Source : https://leetcode.com/problems/intersection-of-two-arrays-ii/ +// Author : Calinescu Valentin, Hao Chen +// 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; + } +}; + + + +/* + * Just simply use the map can have O(M+N) time complexity. + * + */ + + +class Solution { +public: + vector intersect(vector& nums1, vector& nums2) { + unordered_map m; + for (auto n: nums1) { + m[n]++; + } + vector result; + for (auto n:nums2){ + if (m.find(n) != m.end() && m[n]>0 ){ + result.push_back(n); + m[n]--; + } + } + return result; + } +}; 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/jewelsAndStones/JewelsAndStones.cpp b/algorithms/cpp/jewelsAndStones/JewelsAndStones.cpp new file mode 100644 index 000000000..1b807b115 --- /dev/null +++ b/algorithms/cpp/jewelsAndStones/JewelsAndStones.cpp @@ -0,0 +1,49 @@ +// Source : https://leetcode.com/problems/jewels-and-stones/description +// Author : Hao Chen +// Date : 2018-06-23 + +/*************************************************************************************** + * + * You're given strings J representing the types of stones that are jewels, and S + * representing the stones you have. Each character in S is a type of stone you have. + * You want to know how many of the stones you have are also jewels. + * + * The letters in J are guaranteed distinct, and all characters in J and S are letters. + * Letters are case sensitive, so "a" is considered a different type of stone from "A". + * + * Example 1: + * + * + * Input: J = "aA", S = "aAAbbbb" + * Output: 3 + * + * + * Example 2: + * + * + * Input: J = "z", S = "ZZ" + * Output: 0 + * + * + * Note: + * + * + * S and J will consist of letters and have length at most 50. + * The characters in J are distinct. + ***************************************************************************************/ + + +class Solution { +public: + int numJewelsInStones(string J, string S) { + bool map[256] = {false}; + for (auto c : J) { + map[c]=true; + } + int cnt=0; + for (auto c : S) { + if (map[c]) cnt++; + } + return cnt; + } +}; 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=0 && right<=n-1 && s[left] == s[right]) { + left--; + right++; + } + if (right-left-1 > len){ + len = right-left-1; + start = left+1; + } +} + +//The following solution is better than previous solution. +//Because it remove the sub-string return in findPalindrome(). +string longestPalindrome_recursive_way2(string s) { + int n = s.size(); + if (n<=1) return s; + + int start=0, len=0; + string longest; + + string str; + 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/majorityElement/majorityElement.cpp b/algorithms/cpp/majorityElement/majorityElement.cpp index 2df47d1ef..802ef6283 100644 --- a/algorithms/cpp/majorityElement/majorityElement.cpp +++ b/algorithms/cpp/majorityElement/majorityElement.cpp @@ -32,7 +32,7 @@ int majorityElement(vector &num) { cnt++; }else{ majority == num[i] ? cnt++ : cnt --; - if (cnt >= num.size()/2) return majority; + if (cnt > num.size()/2) return majority; } } return majority; @@ -59,7 +59,8 @@ vector split(const string &s, char delim) { int main(int argc, char** argv) { - string array = "1,2,1,2,1,2,1,2,1,2,1"; + //string array = "1,2,1,2,1,2,1,2,1,2,1"; + string array = "2,2,1,1,1"; if (argc > 1){ array = argv[1]; } 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; i& nums, int k) { + int sum=0; + for(int i=0; i sum) { + sum = s; + } + } + return (double)sum/k; + } +}; + diff --git a/algorithms/cpp/maximumDepthOfBinaryTree/maximumDepthOfBinaryTree.cpp b/algorithms/cpp/maximumDepthOfBinaryTree/maximumDepthOfBinaryTree.cpp index e33d6020d..c80336281 100644 --- a/algorithms/cpp/maximumDepthOfBinaryTree/maximumDepthOfBinaryTree.cpp +++ b/algorithms/cpp/maximumDepthOfBinaryTree/maximumDepthOfBinaryTree.cpp @@ -40,3 +40,11 @@ class Solution { } }; + +class Solution2 { +public: + int maxDepth(TreeNode *root) { + if (root==NULL) return 0; + return max(maxDepth(root->left), 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/mirrorReflection/MirrorReflection.cpp b/algorithms/cpp/mirrorReflection/MirrorReflection.cpp new file mode 100644 index 000000000..c2d0d8201 --- /dev/null +++ b/algorithms/cpp/mirrorReflection/MirrorReflection.cpp @@ -0,0 +1,80 @@ +// Source : https://leetcode.com/problems/mirror-reflection/description/ +// Author : Hao Chen +// Date : 2018-06-27 + +/*************************************************************************************** + * + * There is a special square room with mirrors on each of the four walls. Except for + * the southwest corner, there are receptors on each of the remaining corners, numbered + * 0, 1, and 2. + * + * The square room has walls of length p, and a laser ray from the southwest corner + * first meets the east wall at a distance q from the 0th receptor. + * + * Return the number of the receptor that the ray meets first. (It is guaranteed that + * the ray will meet a receptor eventually.) + * + * + * + * + * Example 1: + * + * + * Input: p = 2, q = 1 + * Output: 2 + * Explanation: The ray meets receptor 2 the first time it gets reflected back to the + * left wall. + * + * + * + * + * Note: + * + * + * 1 <= p <= 1000 + * 0 <= q <= p + * + ***************************************************************************************/ + +/* + * Solution + * -------- + * + * We know the following things: + * 1๏ผ‰every reflection will increase the step of `q`. + * 2) when reach the top, the reflection would go down, when reach the bottom the reflection would go up. + * + * So, we can image if there have two walls, left one and right one, then the reflection can go up instanstly, + * + * - the reflection points on left wall would be even times of `q`. + * - the reflection points on right wall would be odd times of `q`. + * + * And in the right wall, the receptors `#0` would be the times of `2p`. + * + * So, we need find the least common multiple of `p` and `q`, then we can have the answer. + */ + + +class Solution { +private: + //GCD - greatest common divisor ๆœ€ๅคงๅ…ฌๅ› ๆ•ฐ + int greatestCommonDivisor (int a, int b) { + if(b) while((a %= b) && (b %= a)); + return a + b; + } + //LCM - least common multiple ๆœ€ๅฐๅ…ฌๅ€ๆ•ฐ + int leastCommonMultiple(int a, int b) { + return a * b / greatestCommonDivisor(a, b); + } +public: + int mirrorReflection(int p, int q) { + int lcm = leastCommonMultiple(p, q); + if (lcm % (2*p) == 0 ) return 0; + + int nq = lcm / q; + + if (nq % 2 == 0 ) return 2; + return 1; + } +}; + diff --git a/algorithms/cpp/mostCommonWord/MostCommonWord.cpp b/algorithms/cpp/mostCommonWord/MostCommonWord.cpp new file mode 100644 index 000000000..12ffe2712 --- /dev/null +++ b/algorithms/cpp/mostCommonWord/MostCommonWord.cpp @@ -0,0 +1,100 @@ +// Source : https://leetcode.com/problems/most-common-word/ +// Author : Hao Chen +// Date : 2018-04-19 + +/*************************************************************************************** + * + * Given a paragraph and a list of banned words, return the most frequent word that is + * not in the list of banned words. It is guaranteed there is at least one word that + * isn't banned, and that the answer is unique. + * + * Words in the list of banned words are given in lowercase, and free of punctuation. + * Words in the paragraph are not case sensitive. The answer is in lowercase. + * + * + * Example: + * Input: + * paragraph = "Bob hit a ball, the hit BALL flew far after it was hit." + * banned = ["hit"] + * Output: "ball" + * Explanation: + * "hit" occurs 3 times, but it is a banned word. + * "ball" occurs twice (and no other word does), so it is the most frequent non-banned + * word in the paragraph. + * Note that words in the paragraph are not case sensitive, + * that punctuation is ignored (even if adjacent to words, such as "ball,"), + * and that "hit" isn't the answer even though it occurs more because it is banned. + * + * + * + * + * Note: + * + * + * 1 <= paragraph.length <= 1000. + * 1 <= banned.length <= 100. + * 1 <= banned[i].length <= 10. + * The answer is unique, and written in lowercase (even if its occurrences in + * paragraph may have uppercase symbols, and even if it is a proper noun.) + * paragraph only consists of letters, spaces, or the punctuation symbols !?',;. + * Different words in paragraph are always separated by a space. + * There are no hyphens or hyphenated words. + * Words only consist of letters, never apostrophes or other punctuation + * symbols. + * + * + * + ***************************************************************************************/ + + +class Solution { +private: + bool isLetter(char c) { + return c >= 'a' && c <= 'z'; + } +public: + string mostCommonWord(string paragraph, vector& banned) { + unordered_map banned_map, words_map; + for (auto w:banned) { + banned_map[w]++; + } + + //conert the string to lower case. + transform(paragraph.begin(), paragraph.end(), paragraph.begin(), ::tolower); + + //transfer the symbols to space. + for (int i=0; i0 ) { + words_map[word]++; + } + word=""; + } + } + if ( word.size()>0 ) words_map[word]++; + + string result; + int max_cnt=0; + // go through the words_map + for (auto const& w : words_map) { + + if ( banned_map.find(w.first) != banned_map.end() ) { + continue; + } + if (max_cnt < w.second) { + result = w.first; + max_cnt = w.second; + } + } + + return result; + } +}; diff --git a/algorithms/cpp/moveZeroes/moveZeroes.cpp b/algorithms/cpp/moveZeroes/moveZeroes.cpp index f6fcb9dab..1b86cb691 100644 --- a/algorithms/cpp/moveZeroes/moveZeroes.cpp +++ b/algorithms/cpp/moveZeroes/moveZeroes.cpp @@ -41,7 +41,7 @@ class Solution { int i = 0, poz = 0; for(i = 0; i < nums.size() && poz < nums.size(); i++) { - while(nums[poz] == 0) + while(poz < nums.size() && nums[poz] == 0) poz++; if(poz < nums.size()) nums[i] = nums[poz]; @@ -72,7 +72,7 @@ class Solution { // Find the first ZERO, where is the tail of the array. // (Notes: we can simply remove this!) - for (; nums[p1]!=0 && p1= 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/palindromePairs/PalindromePairs.cpp b/algorithms/cpp/palindromePairs/PalindromePairs.cpp new file mode 100644 index 000000000..c7c6fada2 --- /dev/null +++ b/algorithms/cpp/palindromePairs/PalindromePairs.cpp @@ -0,0 +1,78 @@ +// Source : https://leetcode.com/problems/palindrome-pairs/ +// Author : Hao Chen +// Date : 2017-03-22 + +/*************************************************************************************** + * + * Given a list of unique words, find all pairs of distinct indices (i, j) in the given + * list, so that the concatenation of the two words, i.e. words[i] + words[j] is a + * palindrome. + * + * Example 1: + * Given words = ["bat", "tab", "cat"] + * Return [[0, 1], [1, 0]] + * The palindromes are ["battab", "tabbat"] + * + * Example 2: + * Given words = ["abcd", "dcba", "lls", "s", "sssll"] + * Return [[0, 1], [1, 0], [3, 2], [2, 4]] + * The palindromes are ["dcbaabcd", "abcddcba", "slls", "llssssll"] + * + * Credits:Special thanks to @dietpepsi for adding this problem and creating all test + * cases. + * + ***************************************************************************************/ + +class Solution { +public: + bool isPalindrome(string& str) { + int left = 0, right = str.size() - 1; + while( left < right) { + if (str[left++] != str[right--]) return false; + } + return true; + } + vector> palindromePairs(vector& words) { + unordered_map dict; + for(int i=0; i> result; + + //egde case: deal with empty string + if ( dict.find("") != dict.end() ) { + for(int i=0; i& nums, int half, int index) { + for (int i=index; i& nums) { + int sum = 0; + for(auto n : nums) sum +=n; + if ( sum & 1 ) return false; // sum % 2 != 1 + int half = sum / 2; + + //sort the array in descending order + //so, the DFS could be very fast to find the answer because it's greedy. + std::sort(nums.begin(), nums.end(), std::greater()); + + //go to find a path which sum is half + return canPartitionRecrusion(nums, half, 0); + } +}; 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= 3 + * There exists some 0 < i < A.length - 1 such that A[0] < A[1] < ... A[i-1] < + * A[i] > A[i+1] > ... > A[A.length - 1] + * + * + * Given an array that is definitely a mountain, return any i such that A[0] < A[1] < + * ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]. + * + * Example 1: + * + * + * Input: [0,1,0] + * Output: 1 + * + * + * + * Example 2: + * + * + * Input: [0,2,1,0] + * Output: 1 + * + * + * Note: + * + * + * 3 <= A.length <= 10000 + * 0 <= A[i] <= 10^6 + * A is a mountain, as defined above. + * + ***************************************************************************************/ + +class Solution { +public: + int peakIndexInMountainArray(vector& A) { + + // Put two dummy items at head and tail to avoid Out-of-Bound Error. + #define INT_MAX 2147483647 + #define INT_MIN (-INT_MAX - 1) + A.insert ( A.begin() , INT_MIN ); + A.push_back(INT_MIN); + + //binary search + int len = A.size(); + int left = 1, right = len - 2; + while(left <= right) { + int mid = left + (right - left)/2; //avoid integer overflow + if ( A[mid-1] < A[mid] && A[mid] > A[mid+1]) return mid-1; + if ( A[mid-1] < A[mid] && A[mid] < A[mid+1]) left = mid + 1; + if ( A[mid-1] > A[mid] && A[mid] > A[mid+1]) right = mid - 1; + + } + return -1; + } +}; + diff --git a/algorithms/cpp/perfectRectangle/PerfectRectangle.cpp b/algorithms/cpp/perfectRectangle/PerfectRectangle.cpp new file mode 100644 index 000000000..453020c6e --- /dev/null +++ b/algorithms/cpp/perfectRectangle/PerfectRectangle.cpp @@ -0,0 +1,80 @@ +// Source : https://leetcode.com/problems/perfect-rectangle/ +// Author : Hao Chen +// Date : 2016-09-08 + +/*************************************************************************************** + * + * Given N axis-aligned rectangles where N > 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; + } +}; + + +// Author: Hao Chen +// 1) preset a dictionary table to look up vowels +// 2) we have two pointer, the `left` one search vowels from the beginning to then end, the `right` one search from the end to the beginning. +// 3) swap the left one and the right one until left >= right. +class Solution { +private: + bool vowelsTable[256]; +public: + Solution(){ + memset(vowelsTable, 0, sizeof(vowelsTable)); + vowelsTable['a']=true; + vowelsTable['e']=true; + vowelsTable['i']=true; + vowelsTable['o']=true; + vowelsTable['u']=true; + + vowelsTable['A']=true; + vowelsTable['E']=true; + vowelsTable['I']=true; + vowelsTable['O']=true; + vowelsTable['U']=true; + } + bool isVowels(char ch) { + return vowelsTable[ch]; + } + string reverseVowels(string s) { + int left=0, right=s.size()-1; + while ( left < right ) { + while( !isVowels( s[left]) ) left++; + while( !isVowels( s[right] ) ) right--; + if (left >= right) break; + swap(s[left], s[right]); + left++; right--; + } + return s; + } +}; 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 < sentence; + std::string word; + std::string line; + std::stringstream numbers, split; + + std::getline(std::cin, line); + numbers << line; + numbers >> rows >> cols; + std::getline(std::cin, line); + split << line; + + while (split >> word){ + sentence.push_back(word); +// strcpy(stc[i++], word.c_str()); + } + + Solution solution; + ret = solution.wordsTyping(sentence, rows, cols); +// ret = SentenceScreenFitting(stc, rows, cols, i); + std::cout << ret << std::endl; + return 0; +} diff --git a/algorithms/cpp/sentenceScreenFitting/sentenceScreenFitting.cpp b/algorithms/cpp/sentenceScreenFitting/sentenceScreenFitting.cpp new file mode 100644 index 000000000..b6d7542b8 --- /dev/null +++ b/algorithms/cpp/sentenceScreenFitting/sentenceScreenFitting.cpp @@ -0,0 +1,197 @@ +// +// OJ#418.cpp +// LeeteCodeOJ#418 +// +// Created by Wang Yi on 25/10/16. +// Copyright (c) 2016 Wang Yi. All rights reserved. +// + + +/********************************************************************************** + * + * Given a rows x cols screen and a sentence represented by a list of words, find + * how many times the given sentence can be fitted on the screen. + * + * Note: + * + * A word cannot be split into two lines. + * The order of words in the sentence must remain unchanged. + * Two consecutive words in a line must be separated by a single space. + * Total words in the sentence won't exceed 100. + * Length of each word won't exceed 10. + * 1 โ‰ค rows, cols โ‰ค 20,000. + * + * + * + * Example 1: + * + * Input: + * rows = 2, cols = 8, sentence = ["hello", "world"] + * + * Output: + * 1 + * + * Explanation: + * hello--- + * world--- + * + * The character '-' signifies an empty space on the screen. + * + * + * + * Example 2: + * + * Input: + * rows = 3, cols = 6, sentence = ["a", "bcd", "e"] + * + * Output: + * 2 + * + * Explanation: + * a-bcd- + * e-a--- + * bcd-e- + * + * The character '-' signifies an empty space on the screen. + * + * + * + * Example 3: + * + * Input: + * rows = 4, cols = 5, sentence = ["I", "had", "apple", "pie"] + * + * Output: + * 1 + * + * Explanation: + * I-had + * apple + * pie-I + * had-- + * + * The character '-' signifies an empty space on the screen. + * + * *********************************************************************************/ + + +#include "sentenceScreenFitting.h" +#include +#include +#include +#define FOR(START, END) for((START)=0;(START)<(END);(START)+=1) { +#define END ;} +#define N 100 + +// first brute force solution +int SentenceScreenFitting(char stc[][M], int row, int col, size_t l) +{ + int i, j, t, s, k=0, ret=0; + int len[N] = {0}; + FOR(i, l) len[i] = (int)strlen(stc[i]) END + + FOR(i, row) + j = col; + t = k; + while (j - len[k] >= 0) { + j -= len[k] + 1; + if (k+1 > l-1){ + FOR(s, k-t) std::cout << stc[t+s] << ' ' END; + std::cout << stc[t+s]; + if (j - len[0] >= 0) + std::cout << ' '; + k = 0; + t = 0; + ret++; + } else{ + k++; + } + } + FOR(s, k-t-1) std::cout << stc[t+s] << ' ' END; + if (k-t > 0) + std::cout << stc[t+s]; + + std::cout << std::setfill ('-') << std::setw(j == col ? col:j+1) << "" << std::endl; + END + + return ret; +} + +/* +int Solution::wordsTyping(vector& sentence, int rows, int cols) +{ + int i, j, t, s, k=0, ret=0, l=(int)sentence.size(); + int len[N] = {0}; + FOR(i, l) len[i] = (int)sentence[i].size() END + + FOR(i, rows) + j = cols; + t = k; + while (j - len[k] >= 0) { + j -= len[k] + 1; + if (k+1 > l-1){ +// FOR(s, k-t) std::cout << sentence[t+s] << ' ' END; +// std::cout << sentence[t+s]; +// if (j - len[0] >= 0) +// std::cout << ' '; + k = 0; + t = 0; + ret++; + } else{ + k++; + } + } +// FOR(s, k-t-1) std::cout << sentence[t+s] << ' ' END; +// if (k-t > 0) +// std::cout << sentence[t+s]; +// +// std::cout << std::setfill ('-') << std::setw(j == cols ? cols:j+1) << "" << std::endl; + END + + return ret; +} +*/ + +// second boosting +int Solution::wordsTyping(vector& sentence, int rows, int cols) +{ + int i, j, k=0, ret=0, l=(int)sentence.size(); +// int t, s; + int jump = 0; + int len[N] = {0}; + FOR(i, l) len[i] = (int)sentence[i].size();jump += len[i] END + jump += l; + + FOR(i, rows) + j = cols; +// t = k; + + if (k == 0){ + ret += j / jump; + j = j % jump; + } + + while (j - len[k] >= 0) { + j -= len[k] + 1; + if (k+1 > l-1){ + // FOR(s, k-t) std::cout << sentence[t+s] << ' ' END; + // std::cout << sentence[t+s]; + // if (j - len[0] >= 0) + // std::cout << ' '; + k = 0; +// t = 0; + ret += j / jump + 1; + j = j % jump; + } else { + k++; + } + } + // FOR(s, k-t-1) std::cout << sentence[t+s] << ' ' END; + // if (k-t > 0) + // std::cout << sentence[t+s]; + // + // std::cout << std::setfill ('-') << std::setw(j == cols ? cols:j+1) << "" << std::endl; + END + + return ret; +} diff --git a/algorithms/cpp/sentenceScreenFitting/sentenceScreenFitting.h b/algorithms/cpp/sentenceScreenFitting/sentenceScreenFitting.h new file mode 100644 index 000000000..e3a3523cb --- /dev/null +++ b/algorithms/cpp/sentenceScreenFitting/sentenceScreenFitting.h @@ -0,0 +1,28 @@ +// +// OJ#418.h +// LeeteCodeOJ#418 +// +// Created by Wang Yi on 25/10/16. +// Copyright (c) 2016 Wang Yi. All rights reserved. +// + +#ifndef __LeeteCodeOJ_418__OJ_418__ +#define __LeeteCodeOJ_418__OJ_418__ + +#define M 10 + +#include +#include +#include + +using std::vector; +using std::string; + +int SentenceScreenFitting(char stc[][M], int row, int col, size_t l); + +class Solution { +public: + int wordsTyping(vector& sentence, int rows, int cols); +}; + +#endif /* defined(__LeeteCodeOJ_418__OJ_418__) */ diff --git a/algorithms/cpp/shuffleAnArray/ShuffleAnArray.cpp b/algorithms/cpp/shuffleAnArray/ShuffleAnArray.cpp new file mode 100644 index 000000000..681a77519 --- /dev/null +++ b/algorithms/cpp/shuffleAnArray/ShuffleAnArray.cpp @@ -0,0 +1,59 @@ +// Source : https://leetcode.com/problems/shuffle-an-array/ +// Author : Hao Chen +// Date : 2016-08-24 + +/*************************************************************************************** + * + * Shuffle a set of numbers without duplicates. + * + * Example: + * + * // Init an array with set 1, 2, and 3. + * int[] nums = {1,2,3}; + * Solution solution = new Solution(nums); + * + * // Shuffle the array [1,2,3] and return its result. Any permutation of [1,2,3] must + * equally likely to be returned. + * solution.shuffle(); + * + * // Resets the array back to its original configuration [1,2,3]. + * solution.reset(); + * + * // Returns the random shuffling of array [1,2,3]. + * solution.shuffle(); + ***************************************************************************************/ + +class Solution { +public: + Solution(vector nums) : _nums(nums), _solution(nums) { + srand(time(NULL)); + } + + /** Resets the array to its original configuration and return it. */ + vector reset() { + return _solution = _nums; + } + + /** Returns a random shuffling of the array. */ + vector shuffle() { + //Fisher Yates + //https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle + + int i = _solution.size(); + + while ( --i > 0 ) { + int j = rand() % (i+1); + swap(_solution[i], _solution[j]); + } + return _solution; + } +private: + vector _nums, _solution; +}; + +/** + * Your Solution object will be instantiated and called as such: + * Solution obj = new Solution(nums); + * vector param_1 = obj.reset(); + * vector param_2 = obj.shuffle(); + */ diff --git a/algorithms/cpp/singleNumber/singleNumber.III.cpp b/algorithms/cpp/singleNumber/singleNumber.III.cpp new file mode 100644 index 000000000..d2f86bd52 --- /dev/null +++ b/algorithms/cpp/singleNumber/singleNumber.III.cpp @@ -0,0 +1,94 @@ +// Source : https://leetcode.com/problems/single-number-iii/ +// Author : Hao Chen +// Date : 2016-01-16 + +/*************************************************************************************** + * + * Given an array of numbers nums, in which exactly two elements appear only once and + * all the other elements appear exactly twice. Find the two elements that appear only + * once. + * + * For example: + * + * Given nums = [1, 2, 1, 3, 2, 5], return [3, 5]. + * + * Note: + * + * The order of the result is not important. So in the above example, [5, 3] is also + * correct. + * Your algorithm should run in linear runtime complexity. Could you implement it using + * only constant space complexity? + * + * Credits:Special thanks to @jianchao.li.fighter for adding this problem and creating + * all test cases. + ***************************************************************************************/ + + +/* + * For the problem - only one number appears once when all other numbers appears exactly twice. + * + * We know, we can XOR all of the array elements. Since X^X is zero, and X^0 is X, + * so all of the duplicated number will zero themselves out, and the only number would be the result. + * + * However, this solution cannot be applied directly to finding two numbers that appear once each. + * + * Suppose that these numbers that appear once are X and Y, and all other numbers appear twice. + * If we decide to XOR all the array's elements, the overall result would actually be `X^Y`. + * + * Unfortunately, there is no way to extract J and K out of their XOR. + * + * But since X and Y are different, we are sure that X^Y is different than zero. + * + * This information is valuable in sense that we know pieces of information that differ. + * If we pick up any bit that is 1 in X XOR Y, we can use it as a mask to test each element of the array. + * + * Obviously, that mask will be the discriminator between X and Y - + * + * Only one of them will have value 1 at that particular position. + * + * + * Now that we have the mask with exactly one bit set to 1, we can walk through the array once again. + * + * But this time we are going to maintain two XORed results. + * + * - One for numbers that have bit 1 at the mask's position + * - Another for numbers that have bit 0 at that position + * + * In this way, we are sure that all duplicates will go into the same pile. + * + * But likewise, we are sure that X and Y will go into separate piles. + * + * So, the overall result is that + * - the first XORed result will be equal to X + * - and the second XORed result will be equal to Y + * +*/ + +class Solution { +public: + vector singleNumber(vector& nums) { + int allxor = 0; + for (int n : nums) { + allxor ^= n; + } + int mask = 1; + while ( (mask & allxor) == 0 ) { + mask <<= 1; + } + + int zero = 0; + int one = 0; + for (int n : nums) { + if (n & mask ){ + one ^= n; + }else { + zero ^= n; + } + } + + vector result; + result.push_back(zero); + result.push_back(one); + return result; + } +}; diff --git a/algorithms/cpp/splitArrayLargestSum/SplitArrayLargestSum.cpp b/algorithms/cpp/splitArrayLargestSum/SplitArrayLargestSum.cpp new file mode 100644 index 000000000..450dda91d --- /dev/null +++ b/algorithms/cpp/splitArrayLargestSum/SplitArrayLargestSum.cpp @@ -0,0 +1,69 @@ +// Source : https://leetcode.com/problems/split-array-largest-sum/ +// Author : Hao Chen +// Date : 2016-11-13 + +/*************************************************************************************** + * + * Given an array which consists of non-negative integers and an integer m, you can + * split the array into m non-empty continuous subarrays. Write an algorithm to + * minimize the largest sum among these m subarrays. + * + * Note: + * Given m satisfies the following constraint: 1 โ‰ค m โ‰ค length(nums) โ‰ค 14,000. + * + * Examples: + * + * Input: + * nums = [7,2,5,10,8] + * m = 2 + * + * Output: + * 18 + * + * Explanation: + * There are four ways to split nums into two subarrays. + * The best way is to split it into [7,2,5] and [10,8], + * where the largest sum among the two subarrays is only 18. + ***************************************************************************************/ + +class Solution { +public: + // Idea + // 1) The max of the result is the sum of the whole array. + // 2) The min of the result is the max num among the array. + // 3) Then, we use Binary Search to find the resullt between the `min` and the `max` + + int splitArray(vector& nums, int m) { + int min = 0, max = 0; + for (int n : nums) { + min = std::max(min, n); + max += n; + } + while (min < max) { + int mid = min + (max - min) / 2; + if (hasSmallerSum(nums, m, mid)) max = mid; + else min = mid + 1; + } + return min; + } + + + // Using a specific `sum` to check wheter we can get `smaller sum` + // The idea here as below: + // find all of possible `sub array` whose sum greater than `sum` + // 1) if the number of `sub array` > m, whcih means the actual result is greater than `sum` + // 2) if the number of `sub array` <= m, whcih means we can have `smaller sum` + // + bool hasSmallerSum(vector& nums, int m, int sum) { + int cnt = 1, curSum = 0; + for (int n : nums) { + curSum += n; + if (curSum > sum) { + curSum = n; + cnt++; + if (cnt > m) return false; + } + } + return true; + } +}; diff --git a/algorithms/cpp/sumOfLeftLeaves/SumOfLeftLeaves.cpp b/algorithms/cpp/sumOfLeftLeaves/SumOfLeftLeaves.cpp new file mode 100644 index 000000000..3db0ad26c --- /dev/null +++ b/algorithms/cpp/sumOfLeftLeaves/SumOfLeftLeaves.cpp @@ -0,0 +1,71 @@ +// Source : https://leetcode.com/problems/sum-of-left-leaves/ +// Author : Hao Chen +// Date : 2016-11-12 + +/*************************************************************************************** + * + * Find the sum of all left leaves in a given binary tree. + * + * Example: + * + * 3 + * / \ + * 9 20 + * / \ + * 15 7 + * + * There are two left leaves in the binary tree, with values 9 and 15 respectively. + * Return 24. + ***************************************************************************************/ + +/** + * Definition for a binary tree node. + * struct TreeNode { + * int val; + * TreeNode *left; + * TreeNode *right; + * TreeNode(int x) : val(x), left(NULL), right(NULL) {} + * }; + */ +class Solution { +public: + + + void sumOfLeftLeaves_recursion_v1(TreeNode* root, int& result) { + if (root == NULL ) { + return; + } + + if (root->left && root->left->left == NULL && root->left->right == NULL) { + result += root->left->val; + } + sumOfLeftLeaves_recursion_v1(root->left, result); + sumOfLeftLeaves_recursion_v1(root->right, result); + + } + + int sumOfLeftLeaves_recursion_v2(TreeNode* root) { + if (root == NULL ) { + return 0; + } + int result = 0; + if (root->left && root->left->left == NULL && root->left->right == NULL) { + result = root->left->val; + } + result += sumOfLeftLeaves_recursion_v2(root->left) + sumOfLeftLeaves_recursion_v2(root->right); + return result; + } + + + int sumOfLeftLeaves(TreeNode* root) { + srand(time(NULL)); + if (rand()%2) { + int result = 0; + sumOfLeftLeaves_recursion_v1(root, result); + return result; + } else { + return sumOfLeftLeaves_recursion_v2(root); + } + + } +}; diff --git a/algorithms/cpp/sumOfTwoIntegers/SumOfTwoIntegers.cpp b/algorithms/cpp/sumOfTwoIntegers/SumOfTwoIntegers.cpp new file mode 100644 index 000000000..d636e94c3 --- /dev/null +++ b/algorithms/cpp/sumOfTwoIntegers/SumOfTwoIntegers.cpp @@ -0,0 +1,38 @@ +// Source : https://leetcode.com/problems/sum-of-two-integers/description/ +// Author : Hao Chen +// Date : 2018-06-25 + +/*************************************************************************************** + * + * Calculate the sum of two integers a and b, but you are not allowed to use the + * operator + and -. + * + * Example: + * Given a = 1 and b = 2, return 3. + * + * + * Credits:Special thanks to @fujiaozhu for adding this problem and creating all test + * cases. + ***************************************************************************************/ + +class Solution { +public: + int getSum(int x, int y) { + // Iterate till there is no carry + while (y != 0) { + // carry now contains common + //set bits of x and y + int carry = x & y; + + // Sum of bits of x and y where at + //least one of the bits is not set + x = x ^ y; + + // Carry is shifted by one so that adding + // it to x gives the required sum + y = carry << 1; + } + return x; + } +}; + diff --git a/algorithms/cpp/superUglyNumber/SuperUglyNumber.cpp b/algorithms/cpp/superUglyNumber/SuperUglyNumber.cpp new file mode 100644 index 000000000..66438fd46 --- /dev/null +++ b/algorithms/cpp/superUglyNumber/SuperUglyNumber.cpp @@ -0,0 +1,69 @@ +// Source : https://leetcode.com/problems/super-ugly-number/ +// Author : Hao Chen +// Date : 2017-01-02 + +/*************************************************************************************** + * + * Write a program to find the nth super ugly number. + * + * Super ugly numbers are positive numbers whose all prime factors are in the given + * prime list + * primes of size k. For example, [1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] + * is the sequence of the first 12 super ugly numbers given primes + * = [2, 7, 13, 19] of size 4. + * + * Note: + * (1) 1 is a super ugly number for any given primes. + * (2) The given numbers in primes are in ascending order. + * (3) 0 k โ‰ค 100, 0 n โ‰ค 106, 0 primes[i] + * + * Credits:Special thanks to @dietpepsi for adding this problem and creating all test + * cases. + ***************************************************************************************/ + +// As the solution we have for the ugly number II problem +// +// int nthUglyNumber(int n) { +// +// int i=0, j=0, k=0; +// vector ugly(1,1); +// +// while(ugly.size() < n){ +// int next = min(ugly[i]*2, ugly[j]*3, ugly[k]*5); +// if (next == ugly[i]*2) i++; +// if (next == ugly[j]*3) j++; +// if (next == ugly[k]*5) k++; +// ugly.push_back(next); +// } +// return ugly.back(); +// } +// +// The logic of solution is exacly same for both., except that instead of 3 numbers you have k numbers to consider. +// +// +// +class Solution { + +public: + int nthSuperUglyNumber(int n, vector& primes) { + vector ugly(1, 1); + int len = primes.size(); + vector pos(len, 0); + + while( ugly.size() < n ) { + int next = INT_MAX; + for(int i=0; i > &board) { } } + +// refers to 4th edition. +class UnionFind { + int count_; // number of components + int* rank_; // to limits tree hights + int* id_; // id[i] parent of i +public: + UnionFind(int n) { + count_ = n; + rank_ = new int[n]; + id_ = new int[n]; + for (int i = 0; i < n; i++) { + id_[i] = i; + rank_[i] = 0; + } + } + + ~UnionFind() { + delete [] rank_; + delete [] id_; + } + + int count() { return count_; } + + int find(int p) { + while (p != id_[p]) { + id_[p] = id_[id_[p]]; // path compression + p = id_[p]; + } + return p; + } + + bool connected(int p, int q) { + return find(p) == find(q); + } + + void connect(int p, int q) { + int i = find(p); + int j = find(q); + if (i == j) return; + if (rank_[i] < rank_[j]) id_[i] = j; + else if (rank_[i] > rank_[j]) id_[j] = i; + else { // == + id_[j] = i; + rank_[i]++; + } + count_--; + } +}; + +class Solution { +public: + void solve(vector >& board) { + int n = board.size(); + if (n == 0) return; + int m = board[0].size(); + + UnionFind uf(n*m+1); + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (i == 0 || i == n-1 || j == 0 || j == m-1) { // side case, connect to dummy node + uf.connect(i*m + j, n*m); + continue; + } + char c = board[i][j]; // inner case, connect to same neighbor + if (board[i+1][j] == c) uf.connect((i+1)*m + j, i*m + j); + if (board[i-1][j] == c) uf.connect((i-1)*m + j, i*m + j); + if (board[i][j+1] == c) uf.connect(i*m + (j+1), i*m + j); + if (board[i][j-1] == c) uf.connect(i*m + (j-1), i*m + j); + } + } + + for (int i = 0; i < n; i++) { + for (int j = 0; j < m; j++) { + if (board[i][j] == 'O' && !uf.connected(i*m + j, n*m)) { + board[i][j] = 'X'; + } + } + } + } +}; + + void solve(vector< vector > &board) { + if (rand() % 2) { + Solution().solve(board); + return; + } //Runtime Error for 250 x 250 matrix /* solve_recursively(board); */ solve_non_recursively(board); diff --git a/algorithms/cpp/thirdMaximumNumber/ThirdMaximumNumber.cpp b/algorithms/cpp/thirdMaximumNumber/ThirdMaximumNumber.cpp new file mode 100644 index 000000000..897dcdfd0 --- /dev/null +++ b/algorithms/cpp/thirdMaximumNumber/ThirdMaximumNumber.cpp @@ -0,0 +1,51 @@ +// Source : https://leetcode.com/problems/third-maximum-number/ +// Author : Hao Chen +// Date : 2016-11-12 + +/*************************************************************************************** + * + * Given a non-empty array of integers, return the third maximum number in this array. + * If it does not exist, return the maximum number. The time complexity must be in O(n). + * + * Example 1: + * + * Input: [3, 2, 1] + * + * Output: 1 + * + * Explanation: The third maximum is 1. + * + * Example 2: + * + * Input: [1, 2] + * + * Output: 2 + * + * Explanation: The third maximum does not exist, so the maximum (2) is returned + * instead. + * + * Example 3: + * + * Input: [2, 2, 3, 1] + * + * Output: 1 + * + * Explanation: Note that the third maximum here means the third maximum distinct + * number. + * Both numbers with value 2 are both considered as second maximum. + ***************************************************************************************/ + +class Solution { +public: + int nMax(vector& nums, int n) { + set topN; + for(auto num : nums) { + topN.insert(num); + if (topN.size() > n) topN.erase(topN.begin()); + } + return (topN.size() >= n) ? *(topN.begin()) : *(topN.rbegin()); + } + int thirdMax(vector& nums) { + return nMax(nums, 3); + } +}; diff --git a/algorithms/cpp/topKFrequentElements/topKFrequentElements.cpp b/algorithms/cpp/topKFrequentElements/topKFrequentElements.cpp new file mode 100644 index 000000000..245c3ba0b --- /dev/null +++ b/algorithms/cpp/topKFrequentElements/topKFrequentElements.cpp @@ -0,0 +1,65 @@ +// Source : https://leetcode.com/problems/top-k-frequent-elements/ +// Author : Calinescu Valentin +// Date : 2016-05-02 + +/*************************************************************************************** + * + * Given a non-empty array of integers, return the k most frequent elements. + * + * For example, + * Given [1,1,1,2,2,3] and k = 2, return [1,2]. + * + * Note: + * You may assume k is always valid, 1 โ‰ค k โ‰ค number of unique elements. + * Your algorithm's time complexity must be better than O(n log n), where n is the + * array's size. + * + ***************************************************************************************/ + +class Solution { +public: + struct element//structure consisting of every distinct number in the vector, + //along with its frequency + { + int number, frequency; + bool operator < (const element arg) const + { + return frequency < arg.frequency; + } + }; + priority_queue sol;//we use a heap so we have all of the elements sorted + //by their frequency + vector solution; + + vector topKFrequent(vector& nums, int k) { + sort(nums.begin(), nums.end()); + int i = 1; + for(; i < nums.size(); i++) + { + int freq = 1; + while(i < nums.size() && nums[i] == nums[i - 1]) + { + i++; + freq++; + } + element el; + el.number = nums[i - 1]; + el.frequency = freq; + sol.push(el); + } + if(i == nums.size())//if we have 1 distinct element as the last + { + element el; + el.number = nums[nums.size() - 1]; + el.frequency = 1; + sol.push(el); + } + while(k)//we extract the first k elements from the heap + { + solution.push_back(sol.top().number); + sol.pop(); + k--; + } + return solution; + } +}; diff --git a/algorithms/cpp/totalHammingDistance/totalHammingDistance.cpp b/algorithms/cpp/totalHammingDistance/totalHammingDistance.cpp new file mode 100644 index 000000000..27971e2b0 --- /dev/null +++ b/algorithms/cpp/totalHammingDistance/totalHammingDistance.cpp @@ -0,0 +1,56 @@ +// Source : https://leetcode.com/problems/total-hamming-distance/ +// Author : Calinescu Valentin +// Date : 2017-01-09 + +/*************************************************************************************** + * + * The Hamming distance between two integers is the number of positions at which the + * corresponding bits are different. + * + * Now your job is to find the total Hamming distance between all pairs of the given + * numbers. + * + * Example: + * Input: 4, 14, 2 + * + * Output: 6 + * + * Explanation: In binary representation, the 4 is 0100, 14 is 1110, and 2 is 0010 (just + * showing the four bits relevant in this case). So the answer will be: + * HammingDistance(4, 14) + HammingDistance(4, 2) + HammingDistance(14, 2) = 2 + 2 + 2 = 6. + * + * Note: + * Elements of the given array are in the range of 0 to 10^9 + * Length of the array will not exceed 10^4. + ***************************************************************************************/ + +/* +* Solution 1 - O(N) +* +* The total Hamming Distance is equal to the sum of all individual Hamming Distances +* between every 2 numbers. However, given that this depends on the individual bits of +* each number, we can see that we only need to compute the number of 1s and 0s for each +* bit position. For example, we look at the least significant bit. Given that we need to +* calculate the Hamming Distance for each pair of 2 numbers, we see that the answer is +* equal to the number of 1s at this position * the number of 0s(which is the total number +* of numbers - the number of 1s), because for each 1 we need to have a 0 to form a pair. +* Thus, the solution is the sum of all these distances at every position. +*/ +class Solution { +public: + int totalHammingDistance(vector& nums) { + long long solution = 0; + int ones[31]; + for(int i = 0; i < 31; i++) + ones[i] = 0; + for(vector::iterator it = nums.begin(); it != nums.end(); ++it) + { + for(int i = 0; (1 << i) <= *it; i++) //i is the position of the bit + if((1 << i) & *it)//to see if the bit at i-position is a 1 + ones[i]++; + } + for(int i = 0; i < 31; i++) + solution += ones[i] * (nums.size() - ones[i]); + return solution; + } +}; diff --git a/algorithms/cpp/uniqueMorseCodeWords/UniqueMorseCodeWords.cpp b/algorithms/cpp/uniqueMorseCodeWords/UniqueMorseCodeWords.cpp new file mode 100644 index 000000000..0b24dd09b --- /dev/null +++ b/algorithms/cpp/uniqueMorseCodeWords/UniqueMorseCodeWords.cpp @@ -0,0 +1,67 @@ +// Source : https://leetcode.com/problems/unique-morse-code-words/description/ +// Author : Hao Chen +// Date : 2018-06-29 + +/*************************************************************************************** + * + * International orse Code defines a standard encoding where each letter is mapped to + * a series of dots and dashes, as follows: "a" maps to ".-", "b" maps to "-...", "c" + * maps to "-.-.", and so on. + * + * For convenience, the full table for the 26 letters of the English alphabet is given + * below: + * + * + * [".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.", + * "---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."] + * + * Now, given a list of words, each word can be written as a concatenation of the orse + * code of each letter. For example, "cab" can be written as "-.-.-....-", (which is + * the concatenation "-.-." + "-..." + ".-"). We'll call such a concatenation, the + * transformation of a word. + * + * Return the number of different transformations among all words we have. + * + * + * Example: + * Input: words = ["gin", "zen", "gig", "msg"] + * Output: 2 + * Explanation: + * The transformation of each word is: + * "gin" -> "--...-." + * "zen" -> "--...-." + * "gig" -> "--...--." + * "msg" -> "--...--." + * + * There are 2 different transformations, "--...-." and "--...--.". + * + * + * + * + * Note: + * + * + * The length of words will be at most 100. + * Each words[i] will have length in range [1, 12]. + * words[i] will only consist of lowercase letters. + ***************************************************************************************/ + +class Solution { +public: + int uniqueMorseRepresentations(vector& words) { + + string MorseTable[26] = {".-","-...","-.-.","-..",".","..-.","--.", + "....","..",".---","-.-",".-..","--","-.", + "---",".--.","--.-",".-.","...","-","..-", + "...-",".--","-..-","-.--","--.."}; + unordered_map transformations; + for (auto word : words) { + string morse; + for (auto ch : word) { + morse += MorseTable[ ch - 'a' ]; + } + transformations[morse]=true; + } + return transformations.size(); + } +}; diff --git a/algorithms/cpp/verifyPreorderSerializationOfABinaryTree/VerifyPreorderSerializationOfABinaryTree.cpp b/algorithms/cpp/verifyPreorderSerializationOfABinaryTree/VerifyPreorderSerializationOfABinaryTree.cpp new file mode 100644 index 000000000..04e6c6c1d --- /dev/null +++ b/algorithms/cpp/verifyPreorderSerializationOfABinaryTree/VerifyPreorderSerializationOfABinaryTree.cpp @@ -0,0 +1,85 @@ +// Source : https://leetcode.com/problems/verify-preorder-serialization-of-a-binary-tree/ +// Author : Hao Chen +// Date : 2017-01-06 + +/*************************************************************************************** + * + * One way to serialize a binary tree is to use pre-order traversal. When we encounter + * a non-null node, we record the node's value. If it is a null node, we record using a + * sentinel value such as #. + * + * _9_ + * / \ + * 3 2 + * / \ / \ + * 4 1 # 6 + * / \ / \ / \ + * # # # # # # + * + * For example, the above binary tree can be serialized to the string + * "9,3,4,#,#,1,#,#,2,#,6,#,#", where # represents a null node. + * + * Given a string of comma separated values, verify whether it is a correct preorder + * traversal serialization of a binary tree. Find an algorithm without reconstructing + * the tree. + * + * Each comma separated value in the string must be either an integer or a character + * '#' representing null pointer. + * + * You may assume that the input format is always valid, for example it could never + * contain two consecutive commas such as "1,,3". + * + * Example 1: + * "9,3,4,#,#,1,#,#,2,#,6,#,#" + * Return true + * Example 2: + * "1,#" + * Return false + * Example 3: + * "9,#,#,1" + * Return false + * + * Credits:Special thanks to @dietpepsi for adding this problem and creating all test + * cases. + ***************************************************************************************/ + +class Solution { +public: + + // we know the following facts: + // 1) if we met a non-null node, then this node will generate two child node. + // 2) if we met a null node, then this node will generate zero child node. + // + // so the idea is, + // 1) we can have a counter to calculate how many node we are going to expect + // 2) once we have the expected node, then we can decrease the counter. + // 3) finally, we will check the counter is zero or not. + // + // the algorithm as below: + // 1) when we meet a non-null node, just simply do `counter++`. because: + // 1.1) we will expect 2 more node after, then we do `counter += 2`. + // 1.2) but the current node also meet the expection of parent node , so, it need remove 1 in counter. + // finally, the `counter = counbter + 2 -1` + // 2) when we meet a null node, just simply do `counter--`. + + bool isValidSerialization(string preorder) { + vector 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/countAndSay/CountAndSay.java b/algorithms/java/src/countAndSay/CountAndSay.java new file mode 100644 index 000000000..28a5151ad --- /dev/null +++ b/algorithms/java/src/countAndSay/CountAndSay.java @@ -0,0 +1,66 @@ +// Source : https://leetcode.com/problems/count-and-say/description/ +// Author : Tianming Cao +// Date : 2018-02-11 + +/********************************************************************************** + * + * The count-and-say sequence is the sequence of integers with the first five terms as following: + * + * 1. 1 + * 2. 11 + * 3. 21 + * 4. 1211 + * 5. 111221 + * 1 is read off as "one 1" or 11. + * 11 is read off as "two 1s" or 21. + * 21 is read off as "one 2, then one 1" or 1211. + * Given an integer n, generate the nth term of the count-and-say sequence. + * + * Note: Each term of the sequence of integers will be represented as a string. + * + * Example 1: + * + * Input: 1 + * Output: "1" + * + * Example 2: + * + * Input: 4 + * Output: "1211" + * + **********************************************************************************/ +package countAndSay; + +public class CountAndSay { + + public String nextString(String str) { + StringBuilder next = new StringBuilder(); + int len = str.length(); + int i = 0; + while (i < len) { + int j = i; + int count = 0; + char currentNumber = str.charAt(i); + while (j < len && str.charAt(j) == currentNumber) { + j++; + count++; + } + next.append(count).append(currentNumber); + i = j; + } + return next.toString(); + } + public String countAndSay(int n) { + if (n <= 1) { + return "1"; + } else { + String p = "1"; + for (int i = 2; i <= n; i++) { + String next = nextString(p); + p = next; + } + return p; + } + } + +} diff --git a/algorithms/java/src/countAndSay/TestCountAndSay.java b/algorithms/java/src/countAndSay/TestCountAndSay.java new file mode 100644 index 000000000..50e4b5be1 --- /dev/null +++ b/algorithms/java/src/countAndSay/TestCountAndSay.java @@ -0,0 +1,17 @@ +package countAndSay; + +import org.junit.Assert; +import org.junit.Test; +/** + * Test for 38. Count and Say + */ +public class TestCountAndSay { + @Test + public void test() { + CountAndSay solution = new CountAndSay(); + String next5 = solution.countAndSay(5); + Assert.assertTrue(next5.equals("111221")); + String next6 = solution.countAndSay(6); + Assert.assertTrue(next6.equals("312211")); + } +} diff --git a/algorithms/java/src/lengthOfLastWord/LengthOfLastWord.java b/algorithms/java/src/lengthOfLastWord/LengthOfLastWord.java new file mode 100644 index 000000000..2e661629a --- /dev/null +++ b/algorithms/java/src/lengthOfLastWord/LengthOfLastWord.java @@ -0,0 +1,44 @@ +// Source : https://leetcode.com/problems/length-of-last-word/description/ +// Author : Tianming Cao +// Date : 2018-02-11 + +/********************************************************************************** + * + * Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word in the string. + * + * If the last word does not exist, return 0. + * + * Note: A word is defined as a character sequence consists of non-space characters only. + * + * Example: + * + * Input: "Hello World" + * Output: 5 + * + **********************************************************************************/ +package lengthOfLastWord; + +public class LengthOfLastWord { + + public int lengthOfLastWord(String s) { + // don't forget rangeCheck + if (s == null || s.length() == 0) { + return 0; + } + int len = s.length(); + int i = len - 1; + while (i >= 0 && s.charAt(i) == ' ') { + i--; + } + if (i == -1) { + return 0; + } + int count = 0; + while (i >= 0 && s.charAt(i) != ' ') { + count++; + i--; + } + return count; + } + +} diff --git a/algorithms/java/src/lengthOfLastWord/TestLengthOfLastWord.java b/algorithms/java/src/lengthOfLastWord/TestLengthOfLastWord.java new file mode 100644 index 000000000..936cb0f75 --- /dev/null +++ b/algorithms/java/src/lengthOfLastWord/TestLengthOfLastWord.java @@ -0,0 +1,18 @@ +package lengthOfLastWord; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for 58. Length of Last Word + */ +public class TestLengthOfLastWord { + @Test + public void test() { + LengthOfLastWord solution = new LengthOfLastWord(); + String str1 = "Hello World"; + Assert.assertTrue(solution.lengthOfLastWord(str1) == 5); + String str2 = "Thank you very much "; + Assert.assertTrue(solution.lengthOfLastWord(str2) == 4); + } +} 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/java/src/minStack/MinStack.java b/algorithms/java/src/minStack/MinStack.java new file mode 100644 index 000000000..7129779d9 --- /dev/null +++ b/algorithms/java/src/minStack/MinStack.java @@ -0,0 +1,60 @@ +// Source : https://leetcode.com/problems/min-stack/description/ +// Author : Tianming Cao +// Date : 2018-02-02 + +/********************************************************************************** + * Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. + * + * push(x) -- Push element x onto stack. + * pop() -- Removes the element on top of the stack. + * top() -- Get the top element. + * getMin() -- Retrieve the minimum element in the stack. + * Example: + * MinStack minStack = new MinStack(); + * minStack.push(-2); + * minStack.push(0); + * minStack.push(-3); + * minStack.getMin(); --> Returns -3. + * minStack.pop(); + * minStack.top(); --> Returns 0. + * minStack.getMin(); --> Returns -2. + * + **********************************************************************************/ +package minStack; + +import java.util.Stack; + +public class MinStack { + public Stack mainStack; + /** + * Call an extra stack named assistStack to store the min value. + * While we doing push operation, compare x with the top of assistStack and push the smaller value into assistStack. + * The other operations pop,top and getMin is very simple. + **/ + public Stack assistStack; + public MinStack() { + mainStack = new Stack(); + assistStack = new Stack(); + } + public void push(int x) { + mainStack.push(x); + if (assistStack.isEmpty()) { + assistStack.push(x); + } else { + assistStack.push(Math.min(x, getMin())); + } + } + + public void pop() { + mainStack.pop(); + assistStack.pop(); + } + + public int top() { + return mainStack.peek(); + } + + public int getMin() { + return assistStack.peek(); + } +} diff --git a/algorithms/java/src/minStack/TestMinStack.java b/algorithms/java/src/minStack/TestMinStack.java new file mode 100644 index 000000000..3c1f9c5f3 --- /dev/null +++ b/algorithms/java/src/minStack/TestMinStack.java @@ -0,0 +1,22 @@ +package minStack; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for 155. Min Stack + */ +public class TestMinStack { + @Test + public void test() { + MinStack minStack = new MinStack(); + minStack.push(3); + minStack.push(4); + minStack.push(1); + minStack.push(2); + Assert.assertTrue(minStack.getMin() == 1); + minStack.pop(); + minStack.pop(); + Assert.assertTrue(minStack.getMin() == 3); + } +} diff --git a/algorithms/java/src/myQueue/MyQueue.java b/algorithms/java/src/myQueue/MyQueue.java new file mode 100644 index 000000000..1abde5b6f --- /dev/null +++ b/algorithms/java/src/myQueue/MyQueue.java @@ -0,0 +1,102 @@ +// Source : https://leetcode.com/problems/implement-queue-using-stacks/description/ +// Author : Tianming Cao +// Date : 2018-02-02 + +/********************************************************************************** + * Implement the following operations of a queue using stacks. + * + * push(x) -- Push element x to the back of queue. + * pop() -- Removes the element from in front of queue. + * peek() -- Get the front element. + * empty() -- Return whether the queue is empty. + * + * Notes: + * You must use only standard operations of a stack -- which means only push to top, peek/pop from top, size, and is empty operations are valid. + * Depending on your language, stack may not be supported natively. You may simulate a stack by using a list or deque (double-ended queue), as long as you use only standard operations of a stack. + * You may assume that all operations are valid (for example, no pop or peek operations will be called on an empty queue). + * + **********************************************************************************/ +package myQueue; + +import java.util.Stack; + +/** + * This problem is a sibling of problem 225(https://leetcode.com/problems/implement-stack-using-queues/description/) + * The solution is: + * 1. stack1 is always in charge of push operation + * 2. stack2 is always in charge of peek and pop operation + * 3. if we want to do peek or pop operation, but stack2 is empty, + * we should first pop all the elements from stack1 and push them into stack2 in turn. + * Give a Example: + * + * First, push numbers "1,2,3,4,5" to stack1, then stack1's structure is: + * + * |5| + * |4| + * |3| + * |2| + * |1| + * + * Second, if we want to get the front element "1",we should pop all the elements of stack1 and push them into stack2, + * after this, stack1 is empty, and stack2's structrue is: + * + * |1| + * |2| + * |3| + * |4| + * |5| + * + * So we can get stack2's top element "1" as the front element of queue. + * + * Next, if we want to push "6" to the back of queue, we should push "6" into stack1 as before, so stack1's structure is: + * + * |6| + * + * Finally, if we want to do pop operation twice ,we should remove the top element of stack2 twice, so stack2's structure is: + * + * |3| + * |4| + * |5| + * + * as expect, the removed element is "1" and "2". + */ +public class MyQueue { + public Stack stack1; + public Stack stack2; + public int size; + public MyQueue() { + stack1 = new Stack(); + stack2 = new Stack(); + size = 0; + } + + public void push(int x) { + stack1.push(x); + size++; + } + + public int pop() { + if (stack2.isEmpty()) { + while (!stack1.isEmpty()) { + stack2.push(stack1.pop()); + } + } + int value = stack2.pop(); + size--; + return value; + } + + public int peek() { + if (stack2.isEmpty()) { + while (!stack1.isEmpty()) { + stack2.push(stack1.pop()); + } + } + int value = stack2.peek(); + return value; + } + + public boolean empty() { + return size == 0 ? true : false; + } +} diff --git a/algorithms/java/src/myQueue/TestMyQueue.java b/algorithms/java/src/myQueue/TestMyQueue.java new file mode 100644 index 000000000..cc77ca169 --- /dev/null +++ b/algorithms/java/src/myQueue/TestMyQueue.java @@ -0,0 +1,23 @@ +package myQueue; + +import org.junit.Assert; +import org.junit.Test; +/** + * Test for 232. Implement Queue using Stacks + */ +public class TestMyQueue { + @Test + public void test(){ + MyQueue queue=new MyQueue(); + Assert.assertTrue(queue.empty()); + queue.push(1); + queue.push(2); + queue.push(3); + queue.push(4); + Assert.assertTrue(queue.pop()==1); + Assert.assertTrue(queue.pop()==2); + queue.push(5); + Assert.assertTrue(queue.peek()==3); + Assert.assertTrue(!queue.empty()); + } +} diff --git a/algorithms/java/src/myStack/MyStack.java b/algorithms/java/src/myStack/MyStack.java new file mode 100644 index 000000000..1c995c554 --- /dev/null +++ b/algorithms/java/src/myStack/MyStack.java @@ -0,0 +1,94 @@ +// Source : https://leetcode.com/problems/implement-stack-using-queues/description/ +// Author : Tianming Cao +// Date : 2018-02-02 + +/********************************************************************************** + * Implement the following operations of a stack using queues. + + * push(x) -- Push element x onto stack. + * pop() -- Removes the element on top of the stack. + * top() -- Get the top element. + * empty() -- Return whether the stack is empty. + * Notes: + * You must use only standard operations of a queue -- which means only push to back, peek/pop from front, size, and is empty operations are valid. + * Depending on your language, queue may not be supported natively. You may simulate a queue by using a list or deque (double-ended queue), as long as you use only standard operations of a queue. + * You may assume that all operations are valid (for example, no pop or top operations will be called on an empty stack). + * + **********************************************************************************/ +package myStack; + +import java.util.LinkedList; +import java.util.Queue; +/********************************************************************************** + * This problem is a sibling of problem 232(https://leetcode.com/problems/implement-queue-using-stacks/description/). + * The train of thought is: + * If we want to pop a element,first we should judge which queue is not empty assumed queue1,another empty queue assumed queue2. + * Next,we pop all element from queue1 and push them into queue2 util queue1's size is 1. + * Finally the last element in queue1 is the correct pop value. + * If queue1 is empty and queue2 is not empty,the step is symmetric. + * The top operation is similar with pop operation. + **********************************************************************************/ +public class MyStack { + public Queue queue1; + public Queue queue2; + public int flag; + public int size; + public MyStack() { + queue1=new LinkedList(); + queue2=new LinkedList(); + flag=1; + size=0; + } + + public void push(int x) { + if(flag==1){ + queue1.offer(x); + }else{ + queue2.offer(x); + } + size++; + } + + public int pop() { + int value; + if(flag==1){ + while(queue1.size()>1){ + queue2.offer(queue1.poll()); + } + value=queue1.poll(); + flag=2; + }else{ + while(queue2.size()>1){ + queue1.offer(queue2.poll()); + } + value=queue2.poll(); + flag=1; + } + size--; + return value; + } + + public int top() { + if(flag==1){ + while(queue1.size()>1){ + queue2.offer(queue1.poll()); + } + int value=queue1.poll(); + queue2.offer(value); + flag=2; + return value; + }else{ + while(queue2.size()>1){ + queue1.offer(queue2.poll()); + } + int value=queue2.poll(); + queue1.offer(value); + flag=1; + return value; + } + } + + public boolean empty() { + return size==0?true:false; + } +} diff --git a/algorithms/java/src/myStack/TestMyStack.java b/algorithms/java/src/myStack/TestMyStack.java new file mode 100644 index 000000000..0dd54382b --- /dev/null +++ b/algorithms/java/src/myStack/TestMyStack.java @@ -0,0 +1,23 @@ +package myStack; + +import org.junit.Assert; +import org.junit.Test; +/** + * Test for 225. Implement Stack using Queues + */ +public class TestMyStack { +@Test +public void test(){ + MyStack stack=new MyStack(); + stack.push(1); + stack.push(2); + stack.push(3); + stack.push(4); + Assert.assertTrue(stack.empty()==false); + Assert.assertTrue(stack.pop()==4); + Assert.assertTrue(stack.pop()==3); + Assert.assertTrue(stack.top()==2); + stack.push(5); + Assert.assertTrue(stack.top()==5); +} +} diff --git a/algorithms/java/src/palindromeNumber/PalindromeNumber.java b/algorithms/java/src/palindromeNumber/PalindromeNumber.java new file mode 100644 index 000000000..06f61c2ec --- /dev/null +++ b/algorithms/java/src/palindromeNumber/PalindromeNumber.java @@ -0,0 +1,51 @@ +// Source : https://oj.leetcode.com/problems/palindrome-number/ +// Author : Tianming Cao +// Date : 2018-02-11 + +/********************************************************************************** + * + * Determine whether an integer is a palindrome. Do this without extra space. + * + * Some hints: + * Could negative integers be palindromes? (ie, -1) + * + * If you are thinking of converting the integer to string, note the restriction of using extra space. + * + * You could also try reversing an integer. + * However, if you have solved the problem "Reverse Integer", you know that the reversed integer might overflow. + * How would you handle such case? + * + * There is a more generic way of solving this problem. + * + **********************************************************************************/ +package palindromeNumber; + +public class PalindromeNumber { + + /** + * The simple way is : + * Reverse x to reverseX and judge whether reverseX is equal to x + * For example: + * x is 1234321, then reverseX is 1234321, they are equal, so 1234321 is palindrome + * x is 1234123, then reverseX is 3214321, they are not equal, so 1234123 is not palindrome + */ + public boolean isPalindrome(int x) { + if (x < 0) { + return false; + } + if (x < 10) { + return true; + } + int n = x; + int reverseX = 0; + while (n > 0) { + reverseX = 10 * reverseX + n % 10; + n /= 10; + } + if (reverseX == x) { + return true; + } else { + return false; + } + } +} diff --git a/algorithms/java/src/palindromeNumber/TestPalindromeNumber.java b/algorithms/java/src/palindromeNumber/TestPalindromeNumber.java new file mode 100644 index 000000000..d8462abdb --- /dev/null +++ b/algorithms/java/src/palindromeNumber/TestPalindromeNumber.java @@ -0,0 +1,20 @@ +package palindromeNumber; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for 9. Palindrome Number + */ +public class TestPalindromeNumber { + @Test + public void test() { + PalindromeNumber solution = new PalindromeNumber(); + boolean flag1 = solution.isPalindrome(1234567); + Assert.assertTrue(!flag1); + boolean flag2 = solution.isPalindrome(1234321); + Assert.assertTrue(flag2); + boolean flag3 = solution.isPalindrome(12344321); + Assert.assertTrue(flag3); + } +} diff --git a/algorithms/java/src/powXn/PowXn.java b/algorithms/java/src/powXn/PowXn.java new file mode 100644 index 000000000..296039323 --- /dev/null +++ b/algorithms/java/src/powXn/PowXn.java @@ -0,0 +1,98 @@ +// Source : https://leetcode.com/problems/powx-n/ +// Author : Tianming Cao +// Date : 2018-02-11 + +/********************************************************************************** + * + * Implement pow(x, n). + * + * Example 1: + * + * Input: 2.00000, 10 + * Output: 1024.00000 + * + * Example 2: + * + * Input: 2.10000, 3 + * Output: 9.26100 + * + **********************************************************************************/ +package powXn; + +public class PowXn { + + /** + * Divide-and-Conquer method + * For example: + * + * 3^9=(3^4)^2*3 + * โ†“ + * 3^4=(3^2)^2 + * โ†“ + * 3^2=3*3 + * โ†“ + * 3=3 + * + * So, both Space and Time are O(logN) + */ + public double recursion(double x, long n) { + if (n == 1) { + return x; + } + //We'd better use unsigned right shift + double half = recursion(x, n >>> 1); + if ((n & 1) == 0) { + return half * half; + } else { + return half * half * x; + } + } + + public double myPow01(double x, int n) { + if (n == 0 || x == 1) { + return 1; + } + // Avoid being out of bounds, we should cast int to long + long m = n; + double result = recursion(x, Math.abs(m)); + if (n > 0) { + return result; + } else { + return 1 / result; + } + } + + public double myPow02(double x, int n) { + if (n == 0 || x == 1) { + return 1; + } + // Avoid being out of bounds, we should cast int to long + long m = n; + double result = bitFunction(x, Math.abs(m)); + if (n > 0) { + return result; + } else { + return 1 / result; + } + } + + /** + * Solution with bit-manipulation + * For example: + * 9=1001 + * 3^9=(3^1)^1*(3^2)^0*(3^4)^0*(3^8)^1 + * Space is O(1), Time is O(logN) + */ + public double bitFunction(double x, long n) { + double multy = 1; + double base = x; + for (long k = n; k >= 1; k >>>= 1) { + if ((k & 1) > 0) { + multy = multy * base; + } + base *= base; + } + return multy; + } + +} diff --git a/algorithms/java/src/powXn/TestPowXn.java b/algorithms/java/src/powXn/TestPowXn.java new file mode 100644 index 000000000..6b6835dc4 --- /dev/null +++ b/algorithms/java/src/powXn/TestPowXn.java @@ -0,0 +1,18 @@ +package powXn; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for 50. Pow(x, n) + */ +public class TestPowXn { + @Test + public void test() { + PowXn solution = new PowXn(); + Assert.assertTrue(solution.myPow01(3, 9) == 19683); + Assert.assertTrue(solution.myPow02(3, 9) == 19683); + Assert.assertTrue(solution.myPow01(2.10000, -3)-0.10798<0.0001); + Assert.assertTrue(solution.myPow02(2.10000, -3)-0.10798<0.0001); + } +} diff --git a/algorithms/java/src/removeDuplicatesFromSortedArray/RemoveDuplicatesFromSortedArray.java b/algorithms/java/src/removeDuplicatesFromSortedArray/RemoveDuplicatesFromSortedArray.java new file mode 100644 index 000000000..fb877c838 --- /dev/null +++ b/algorithms/java/src/removeDuplicatesFromSortedArray/RemoveDuplicatesFromSortedArray.java @@ -0,0 +1,38 @@ +// Source : https://leetcode.com/problems/remove-duplicates-from-sorted-array/description/ +// Author : Tianming Cao +// Date : 2018-02-02 + +/********************************************************************************** + * Implement the following operations of a stack using queues. + + * Given a sorted array, remove the duplicates in-place such that each element appear only once and return the new length. + + * Do not allocate extra space for another array, + * you must do this by modifying the input array in-place with O(1) extra memory. + + * Example: + + * Given nums = [1,1,2], + + * Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. + * It doesn't matter what you leave beyond the new length. + * + **********************************************************************************/ +package removeDuplicatesFromSortedArray; + +public class RemoveDuplicatesFromSortedArray { + public int removeDuplicates(int[] nums) { + if (nums == null || nums.length == 0) { + return 0; + } + int n = nums.length; + int len = 0; + for (int i = 1; i < n; i++) { + if (nums[i] != nums[len]) { + nums[len + 1] = nums[i]; + len++; + } + } + return len + 1; + } +} diff --git a/algorithms/java/src/removeDuplicatesFromSortedArray/TestRemoveDuplicates.java b/algorithms/java/src/removeDuplicatesFromSortedArray/TestRemoveDuplicates.java new file mode 100644 index 000000000..7756f45b6 --- /dev/null +++ b/algorithms/java/src/removeDuplicatesFromSortedArray/TestRemoveDuplicates.java @@ -0,0 +1,27 @@ +package removeDuplicatesFromSortedArray; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for 26. Remove Duplicates from Sorted Array + */ +public class TestRemoveDuplicates { + @Test + public void test() { + int[] nums1 = {0, 0, 0, 0, 0, 1, 2, 2, 3, 3, 4, 4}; + RemoveDuplicatesFromSortedArray solution = new RemoveDuplicatesFromSortedArray(); + int len1 = solution.removeDuplicates(nums1); + Assert.assertTrue(len1 == 5); + assertSorted(nums1, len1); + int[] nums2 = {1, 2, 2, 2, 3, 4, 5, 6, 6, 7, 7, 7, 8}; + int len2 = solution.removeDuplicates(nums2); + Assert.assertTrue(len2 == 8); + assertSorted(nums2, len2); + } + private void assertSorted(int[] array, int len) { + for (int i = 0; i < len - 1; i++) { + Assert.assertTrue(array[i] < array[i + 1]); + } + } +} diff --git a/algorithms/java/src/reverseLinkedList/ListNode.java b/algorithms/java/src/reverseLinkedList/ListNode.java new file mode 100644 index 000000000..b38b556b2 --- /dev/null +++ b/algorithms/java/src/reverseLinkedList/ListNode.java @@ -0,0 +1,46 @@ +package reverseLinkedList; + +public class ListNode { + public int val; + public ListNode next; + public ListNode(int x) { + val = x; + } + @Override + public String toString() { + return "ListNode [val=" + val + "]"; + } + public ListNode(int val, ListNode next) { + super(); + this.val = val; + this.next = next; + } + /** + * This is an assistant function, use it, we can easily see the structure of list + */ + public static String listToString(ListNode head) { + if (head == null) { + return ""; + } + StringBuilder sb = new StringBuilder(); + while (head.next != null) { + sb.append(head.val).append(","); + head = head.next; + } + sb.append(head.val); + return sb.toString(); + } + + /** + * This is an assistant function, use it, we can create a linkedList by array. + */ + public static ListNode arrayToList(int[] array) { + ListNode head = new ListNode(0); + ListNode p = head; + for (int i : array) { + p.next = new ListNode(i); + p = p.next; + } + return head.next; + } +} diff --git a/algorithms/java/src/reverseLinkedList/ReverseLinkedList.java b/algorithms/java/src/reverseLinkedList/ReverseLinkedList.java new file mode 100644 index 000000000..06ae90bcc --- /dev/null +++ b/algorithms/java/src/reverseLinkedList/ReverseLinkedList.java @@ -0,0 +1,58 @@ +// Source : https://leetcode.com/problems/reverse-linked-list/description/ +// Author : Tianming Cao +// Date : 2018-02-11 + +/********************************************************************************** + * + * Reverse a singly linked list. + * + * Hint: + * A linked list can be reversed either iteratively or recursively. Could you implement both? + * + **********************************************************************************/ +package reverseLinkedList; + +public class ReverseLinkedList { + + /** + * The iterative solution + */ + public ListNode reverseList(ListNode head) { + if (head == null) { + return head; + } + ListNode p = head; + ListNode next = p.next; + while (next != null) { + ListNode temp = next.next; + next.next = p; + p = next; + next = temp; + } + head.next = null; + return p; + } + + public ListNode reverseListRecursion(ListNode head) { + if (head == null) { + return head; + } + ListNode newHead = recursion(head); + head.next = null; + return newHead; + } + /** + * The recursive solution + */ + public ListNode recursion(ListNode p) { + if (p.next == null) { + return p; + } else { + ListNode next = p.next; + ListNode newHead = recursion(next); + next.next = p; + return newHead; + } + } + +} diff --git a/algorithms/java/src/reverseLinkedList/TestReverseLinkedList.java b/algorithms/java/src/reverseLinkedList/TestReverseLinkedList.java new file mode 100644 index 000000000..f87e5e0a2 --- /dev/null +++ b/algorithms/java/src/reverseLinkedList/TestReverseLinkedList.java @@ -0,0 +1,22 @@ +package reverseLinkedList; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for 206. Reverse Linked List + */ +public class TestReverseLinkedList { + @Test + public void test(){ + ReverseLinkedList solution=new ReverseLinkedList(); + int[] array1={1,2,3,4,5,6}; + ListNode head1=ListNode.arrayToList(array1); + ListNode newHead1=solution.reverseList(head1); + Assert.assertTrue(ListNode.listToString(newHead1).equals("6,5,4,3,2,1")); + int[] array2={6,5,4,3,2,1}; + ListNode head2=ListNode.arrayToList(array2); + ListNode newHead2=solution.reverseListRecursion(head2); + Assert.assertTrue(ListNode.listToString(newHead2).equals("1,2,3,4,5,6")); + } +} diff --git a/algorithms/java/src/reverseLinkedListII/ListNode.java b/algorithms/java/src/reverseLinkedListII/ListNode.java new file mode 100644 index 000000000..a2b1c208b --- /dev/null +++ b/algorithms/java/src/reverseLinkedListII/ListNode.java @@ -0,0 +1,46 @@ +package reverseLinkedListII; + +public class ListNode { + public int val; + public ListNode next; + public ListNode(int x) { + val = x; + } + @Override + public String toString() { + return "ListNode [val=" + val + "]"; + } + public ListNode(int val, ListNode next) { + super(); + this.val = val; + this.next = next; + } + /** + * This is an assistant function, use it, we can easily see the structure of list + */ + public static String listToString(ListNode head) { + if (head == null) { + return ""; + } + StringBuilder sb = new StringBuilder(); + while (head.next != null) { + sb.append(head.val).append(","); + head = head.next; + } + sb.append(head.val); + return sb.toString(); + } + + /** + * This is an assistant function, use it, we can create a linkedList by array. + */ + public static ListNode arrayToList(int[] array) { + ListNode head = new ListNode(0); + ListNode p = head; + for (int i : array) { + p.next = new ListNode(i); + p = p.next; + } + return head.next; + } +} diff --git a/algorithms/java/src/reverseLinkedListII/ReverseLinkedListII.java b/algorithms/java/src/reverseLinkedListII/ReverseLinkedListII.java new file mode 100644 index 000000000..e2d5d0b7d --- /dev/null +++ b/algorithms/java/src/reverseLinkedListII/ReverseLinkedListII.java @@ -0,0 +1,53 @@ +// Source : https://leetcode.com/problems/reverse-linked-list-ii/description/ +// Author : Tianming Cao +// Date : 2018-02-11 + +/********************************************************************************** + * + * Reverse a linked list from position m to n. Do it in-place and in one-pass. + * + * For example: + * Given 1->2->3->4->5->NULL, m = 2 and n = 4, + * + * return 1->4->3->2->5->NULL. + * + * Note: + * Given m, n satisfy the following condition: + * 1 โ‰ค m โ‰ค n โ‰ค length of list. + * + **********************************************************************************/ +package reverseLinkedListII; + +public class ReverseLinkedListII { + public ListNode reverseBetween(ListNode head, int m, int n) { + // Assume that the list is:[1,2,3,4,5,6,7] m=3 n=5 + if (head == null || m == n) { + // bounds check + return head; + } + // We'd better create a default head due to m may equals 1 + ListNode defaultHead = new ListNode(0); + defaultHead.next = head; + int index = 1; + ListNode pre = defaultHead; + while (index < m) { + pre = pre.next; + index++; + } + // pre is 2, first is 3 + ListNode first = pre.next; + ListNode p = first; + ListNode next = p.next; + while (index < n) { + ListNode t = next.next; + next.next = p; + p = next; + next = t; + index++; + } + // next is 6 + first.next = next; + pre.next = p; + return defaultHead.next; + } +} diff --git a/algorithms/java/src/reverseLinkedListII/TestReverseLinkedListII.java b/algorithms/java/src/reverseLinkedListII/TestReverseLinkedListII.java new file mode 100644 index 000000000..b0aae856a --- /dev/null +++ b/algorithms/java/src/reverseLinkedListII/TestReverseLinkedListII.java @@ -0,0 +1,24 @@ +package reverseLinkedListII; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for 92. Reverse Linked List II + */ +public class TestReverseLinkedListII { + @Test + public void test() { + ReverseLinkedListII solution = new ReverseLinkedListII(); + int[] array1 = {1, 2, 3, 4, 5, 6, 7}; + ListNode head1 = ListNode.arrayToList(array1); + ListNode newHead1 = solution.reverseBetween(head1, 3, 5); + Assert.assertTrue(ListNode.listToString(newHead1).equals( + "1,2,5,4,3,6,7")); + int[] array2 = {7, 6, 5, 4, 3, 2, 1}; + ListNode head2 = ListNode.arrayToList(array2); + ListNode newHead2 = solution.reverseBetween(head2, 1, 7); + Assert.assertTrue(ListNode.listToString(newHead2).equals( + "1,2,3,4,5,6,7")); + } +} diff --git a/algorithms/java/src/reverseWordsInAString/ReverseWordsInAString.java b/algorithms/java/src/reverseWordsInAString/ReverseWordsInAString.java new file mode 100644 index 000000000..c866af57b --- /dev/null +++ b/algorithms/java/src/reverseWordsInAString/ReverseWordsInAString.java @@ -0,0 +1,35 @@ +// Source : https://leetcode.com/problems/reverse-words-in-a-string/description/ +// Author : Tianming Cao +// Date : 2018-02-11 + +/********************************************************************************** + * + * Given an input string, reverse the string word by word. + * + * For example, + * Given s = "the sky is blue", + * return "blue is sky the". + * + * Update (2015-02-12): + * For C programmers: Try to solve it in-place in O(1) space. + * + **********************************************************************************/ +package reverseWordsInAString; + +public class ReverseWordsInAString { + + public String reverseWords(String s) { + if (s == null || s.length() == 0) { + return s; + } + s = s.trim(); + String[] array = s.split("\\s+"); + StringBuilder sb = new StringBuilder(); + int len = array.length; + for (int i = len - 1; i > 0; i--) { + sb.append(array[i]).append(" "); + } + sb.append(array[0]); + return sb.toString(); + } +} diff --git a/algorithms/java/src/reverseWordsInAString/TestReverseWordsInAString.java b/algorithms/java/src/reverseWordsInAString/TestReverseWordsInAString.java new file mode 100644 index 000000000..4a5db14cd --- /dev/null +++ b/algorithms/java/src/reverseWordsInAString/TestReverseWordsInAString.java @@ -0,0 +1,17 @@ +package reverseWordsInAString; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for 151. Reverse Words in a String + */ +public class TestReverseWordsInAString { + @Test + public void test() { + ReverseWordsInAString solution = new ReverseWordsInAString(); + String str = " the sky is blue "; + String result = solution.reverseWords(str); + Assert.assertTrue(result.equals("blue is sky the")); + } +} diff --git a/algorithms/java/src/rotateArray/RotateArray.java b/algorithms/java/src/rotateArray/RotateArray.java new file mode 100644 index 000000000..899f53be8 --- /dev/null +++ b/algorithms/java/src/rotateArray/RotateArray.java @@ -0,0 +1,55 @@ +// Source : https://leetcode.com/problems/rotate-array/description/ +// Author : Tianming Cao +// Date : 2018-02-02 + +/********************************************************************************** + * Rotate an array of n elements to the right by k steps. + * + * For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4]. + * + * Note: + * Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem. + * + * Hint: + * Could you do it in-place with O(1) extra space? + * Related problem: Reverse Words in a String II + * + **********************************************************************************/ +package rotateArray; +/********************************************************************************** + * + * For example, with n = 9 and k = 4, the array is [1,2,3,4,5,6,7,8,9] + * The train of thought is: + * 1. Reverse 1-5 to [5,4,3,2,1] + * 2. Reverse 6-9 to [9,8,7,6] + * 3. Reverse the entire array [5,4,3,2,1,9,8,7,6] to [6,7,8,9,1,2,3,4,5] + * It's a liner time and in-place algorithm + * + **********************************************************************************/ +public class RotateArray { + + public void rotate(int[] nums, int k) { + //bounds check + if (nums == null || nums.length == 0 || k == 0) { + return; + } + int n = nums.length; + //k may be larger than n + k = k % n; + rotateRange(0, n - k - 1, nums); + rotateRange(n - k, n - 1, nums); + rotateRange(0, n - 1, nums); + } + + private void rotateRange(int start, int end, int[] array) { + for (int i = start, j = end; i < j; i++, j--) { + swap(array, i, j); + } + } + private void swap(int[] array, int i, int j) { + int t = array[i]; + array[i] = array[j]; + array[j] = t; + } + +} diff --git a/algorithms/java/src/rotateArray/TestRotateArray.java b/algorithms/java/src/rotateArray/TestRotateArray.java new file mode 100644 index 000000000..15a41ca77 --- /dev/null +++ b/algorithms/java/src/rotateArray/TestRotateArray.java @@ -0,0 +1,27 @@ +package rotateArray; + +import java.util.Arrays; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for 189. Rotate Array + * + */ +public class TestRotateArray { + @Test + public void test() { + RotateArray solution = new RotateArray(); + int[] array1 = {1, 2, 3, 4, 5, 6, 7}; + int k1 = 24; + solution.rotate(array1, k1); + int[] expectArray1 = {5, 6, 7, 1, 2, 3, 4}; + Assert.assertTrue(Arrays.equals(array1, expectArray1)); + int[] array2 = {1, 2, 3, 4, 5, 6, 7, 8, 9}; + int k2 = 4; + solution.rotate(array2, k2); + int[] expectArray2 = {6, 7, 8, 9, 1, 2, 3, 4, 5}; + Assert.assertTrue(Arrays.equals(array2, expectArray2)); + } +} diff --git a/algorithms/java/src/searchA2DMatrixII/SearchA2DMatrixII.java b/algorithms/java/src/searchA2DMatrixII/SearchA2DMatrixII.java new file mode 100644 index 000000000..ca38cabb4 --- /dev/null +++ b/algorithms/java/src/searchA2DMatrixII/SearchA2DMatrixII.java @@ -0,0 +1,57 @@ +๏ปฟ// Source : https://leetcode.com/problems/search-a-2d-matrix-ii/description/ +// Author : Tianming Cao +// Date : 2018-01-27 +/********************************************************************************** + * Write an efficient algorithm that searches for a value in an m x n matrix. + * This matrix has the following properties: + * + * Integers in each row are sorted in ascending from left to right. + * Integers in each column are sorted in ascending from top to bottom. + * For example, + * + * Consider the following matrix: + * + * [ + * [1, 4, 7, 11, 15], + * [2, 5, 8, 12, 19], + * [3, 6, 9, 16, 22], + * [10, 13, 14, 17, 24], + * [18, 21, 23, 26, 30] + * ] + * Given target = 5, return true. + * + * Given target = 20, return false. + * + **********************************************************************************/ +package searchA2DMatrixII; +/********************************************************************************** + * This probleam is similar to problem 74(https://leetcode.com/problems/search-a-2d-matrix/description/). + * One solution is: + * Compare rightTopNumber with target to judge rowIndex and colIndex which place to move, + * until thay out of range or find target. + * Another solution is using binarySearch. + **********************************************************************************/ +public class SearchA2DMatrixII { + public boolean searchMatrix(int[][] matrix, int target) { + if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { + return false; + } else { + int m=matrix.length; + int n=matrix[0].length; + int row=0; + int col=n-1; + while(row=0){ + int rightTopNumber=matrix[row][col]; + if(rightTopNumber==target){ + return true; + }else if(target>rightTopNumber){ + row++; + }else{ + col--; + } + } + return false; + } + } + +} diff --git a/algorithms/java/src/searchA2DMatrixII/Test_240.java b/algorithms/java/src/searchA2DMatrixII/Test_240.java new file mode 100644 index 000000000..b70d0ef40 --- /dev/null +++ b/algorithms/java/src/searchA2DMatrixII/Test_240.java @@ -0,0 +1,19 @@ +package searchA2DMatrixII; + +import org.junit.Assert; +import org.junit.Test; +/** + * Test for 240. Search a 2D Matrix II + */ +public class Test_240 { + @Test + public void test() { + SearchA2DMatrixII solution = new SearchA2DMatrixII(); + int[][] matrix = {{1, 4, 7, 11, 15}, {2, 5, 8, 12, 19}, + {3, 6, 9, 16, 22}, {10, 13, 14, 17, 24}, {18, 21, 23, 26, 30}}; + int target = 5; + Assert.assertTrue(solution.searchMatrix(matrix, target)); + target = 20; + Assert.assertTrue(!solution.searchMatrix(matrix, target)); + } +} diff --git a/algorithms/java/src/strStr/StrStrKmp.java b/algorithms/java/src/strStr/StrStrKmp.java new file mode 100644 index 000000000..a5fe657dc --- /dev/null +++ b/algorithms/java/src/strStr/StrStrKmp.java @@ -0,0 +1,126 @@ +// Source : https://leetcode.com/problems/implement-strstr/description/ +// Inspired by : http://wiki.jikexueyuan.com/project/kmp-algorithm/define.html +// Author : Tianming Cao +// Date : 2018-02-11 + +/********************************************************************************** + * + * Implement strStr(). + * + * Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. + * + * Example 1: + * + * Input: haystack = "hello", needle = "ll" + * Output: 2 + * + * Example 2: + * + * Input: haystack = "aaaaa", needle = "bba" + * Output: -1 + * + **********************************************************************************/ +package strStr; + +public class StrStrKmp { + + /** + * KMP-Algorithm + */ + public int strStr(String haystack, String needle) { + if (haystack == null && needle == null) { + return 0; + } + if (haystack == null && needle != null) { + return -1; + } + if (haystack != null && needle == null) { + return -1; + } + int m = haystack.length(); + int n = needle.length(); + if (m < n) { + return -1; + } + if (n == 0) { + return 0; + } + int[] nextArray = getNext(needle); + int i = 0; + int j = 0; + while (i < m) { + if (j == -1) { + // If pointer j is in boundary, move i to the right and reset j + i++; + j = 0; + } else { + if (haystack.charAt(i) == needle.charAt(j)) { + // While matching succeess, move both pointer i and pointer j to the right + i++; + j++; + if (j == n) { + return i - n; + } + } else { + /*** + * For example: + * + * next: [-1,0,0,0,0,1,2] + * + * i + * โ†“ + * haystack:BBC ABCDAB ABCDABCDABDE + * j + * โ†“ + * needle: ABCDABD + * + * + * So the next step is: + * + * i + * โ†“ + * haystack:BBC ABCDAB ABCDABCDABDE + * j + * โ†“ + * needle: ABCDABD + */ + j = nextArray[j]; + } + } + } + return -1; + } + /** + * Generate the next-array of needle string + * + * For example: + * + * next-array of "ABCDABD" is: [-1,0,0,0,0,1,2] + * + * For letter "D", the longest prefix "AB" is equal to the longest suffix "AB", + * the string "AB"'s length is 2, so letter "D"'s next value is 2. + */ + public int[] getNext(String str) { + int len = str.length(); + int[] next = new int[len]; + next[0] = -1; + int k = -1; + int j = 0; + while (j < len - 1) { + if (k == -1) { + k = 0; + next[j + 1] = 0; + j++; + } else { + if (str.charAt(j) == str.charAt(k)) { + next[j + 1] = k + 1; + k++; + j++; + } else { + k = next[k]; + } + } + } + return next; + } +} diff --git a/algorithms/java/src/strStr/TestStrStrKmp.java b/algorithms/java/src/strStr/TestStrStrKmp.java new file mode 100644 index 000000000..9cc68e9f7 --- /dev/null +++ b/algorithms/java/src/strStr/TestStrStrKmp.java @@ -0,0 +1,25 @@ +package strStr; + +import org.junit.Assert; +import org.junit.Test; +/** + * Test for 28. Implement strStr() using KMP-Algorithm + */ +public class TestStrStrKmp { + @Test + public void testKmp() { + StrStrKmp solution = new StrStrKmp(); + String hayStack1 = "aabbccagdbbccdec"; + String needle1 = "bbccd"; + int result1 = solution.strStr(hayStack1, needle1); + Assert.assertTrue(result1 == 9); + String hayStack2 = "aabbccagdbbccdec"; + String needle2 = "bbccf"; + int result2 = solution.strStr(hayStack2, needle2); + Assert.assertTrue(result2 == -1); + String hayStack3 = "BBC ABCDAB ABCDABCDABDE"; + String needle3 = "ABCDABD"; + int result3 = solution.strStr(hayStack3, needle3); + Assert.assertTrue(result3 == 15); + } +} diff --git a/algorithms/java/src/validAnagram/TestValidAnagram.java b/algorithms/java/src/validAnagram/TestValidAnagram.java new file mode 100644 index 000000000..015dcb848 --- /dev/null +++ b/algorithms/java/src/validAnagram/TestValidAnagram.java @@ -0,0 +1,16 @@ +package validAnagram; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for 242. Valid Anagram + */ +public class TestValidAnagram { + @Test + public void test() { + ValidAnagram solution = new ValidAnagram(); + Assert.assertTrue(solution.isAnagram("anagram", "nagaram")); + Assert.assertTrue(!solution.isAnagram("rat", "car")); + } +} diff --git a/algorithms/java/src/validAnagram/ValidAnagram.java b/algorithms/java/src/validAnagram/ValidAnagram.java new file mode 100644 index 000000000..b1bfe9904 --- /dev/null +++ b/algorithms/java/src/validAnagram/ValidAnagram.java @@ -0,0 +1,53 @@ +// Source : https://leetcode.com/problems/valid-anagram/description/ +// Author : Tianming Cao +// Date : 2018-02-11 + +/********************************************************************************** + * + * Given two strings s and t, write a function to determine if t is an anagram of s. + * + * For example, + * s = "anagram", t = "nagaram", return true. + * s = "rat", t = "car", return false. + * + * Note: + * You may assume the string contains only lowercase alphabets. + * + * Follow up: + * What if the inputs contain unicode characters? How would you adapt your solution to such case? + * + **********************************************************************************/ +package validAnagram; + +public class ValidAnagram { + + /** + * Like counting-sort + */ + public boolean isAnagram(String s, String t) { + if (s == null && t == null) { + return true; + } + if (s.length() != t.length()) { + return false; + } + final int mapLen = 26; + int[] map1 = new int[mapLen]; + int[] map2 = new int[mapLen]; + int len = s.length(); + for (int i = 0; i < len; i++) { + char c1 = s.charAt(i); + map1[c1 - 'a']++; + // ASCII of letter a is 97 + int c2 = t.charAt(i); + map2[c2 - 97]++; + } + for (int i = 0; i < mapLen; i++) { + if (map1[i] != map2[i]) { + return false; + } + } + return true; + } + +} diff --git a/algorithms/java/src/validPalindrome/TestValidPalindrome.java b/algorithms/java/src/validPalindrome/TestValidPalindrome.java new file mode 100644 index 000000000..c66ca43b4 --- /dev/null +++ b/algorithms/java/src/validPalindrome/TestValidPalindrome.java @@ -0,0 +1,17 @@ +package validPalindrome; + +import org.junit.Assert; +import org.junit.Test; +/** + * Test for 125. Valid Palindrome + */ +public class TestValidPalindrome { + @Test + public void test() { + ValidPalindrome solution = new ValidPalindrome(); + String str1 = "A man, a plan, a canal: Panama"; + Assert.assertTrue(solution.isPalindrome(str1)); + String str2 = "race a car"; + Assert.assertTrue(!solution.isPalindrome(str2)); + } +} diff --git a/algorithms/java/src/validPalindrome/ValidPalindrome.java b/algorithms/java/src/validPalindrome/ValidPalindrome.java new file mode 100644 index 000000000..73185d22e --- /dev/null +++ b/algorithms/java/src/validPalindrome/ValidPalindrome.java @@ -0,0 +1,59 @@ +// Source : https://leetcode.com/problems/valid-palindrome/description/ +// Author : Tianming Cao +// Date : 2018-02-11 + +/********************************************************************************** + * + * Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. + * + * For example, + * "A man, a plan, a canal: Panama" is a palindrome. + * "race a car" is not a palindrome. + * + * Note: + * Have you consider that the string might be empty? This is a good question to ask during an interview. + * + * For the purpose of this problem, we define empty string as valid palindrome. + * + **********************************************************************************/ +package validPalindrome; + +public class ValidPalindrome { + private boolean isAlphaNumber(char c) { + if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) { + return true; + } else { + return false; + } + } + /** + * We need two pointers like below: + * + * i j + * โ†“-------> <--------โ†“ + * a,b c d e e d;c b a + + * + * Move them from border to mid, util i meet j or s[i]!=s[j] + */ + public boolean isPalindrome(String s) { + if (s == null || s.length() <= 1) { + return true; + } + s = s.toLowerCase(); + int i = 0, j = s.length() - 1; + while (i < j) { + while (!isAlphaNumber(s.charAt(i)) && i < j) { + i++; + } + while (!isAlphaNumber(s.charAt(j)) && i < j) { + j--; + } + if (s.charAt(i) != s.charAt(j)) { + return false; + } + i++; + j--; + } + return true; + } +} diff --git a/database/README.md b/database/README.md new file mode 100644 index 000000000..930500a76 --- /dev/null +++ b/database/README.md @@ -0,0 +1,6 @@ +### LeetCode Database + + +| # | Title | Solution | Difficulty | +|---| ----- | -------- | ---------- | +|1|[Trips and Users](https://leetcode.com/problems/trips-and-users/)| [MySQL](./TripsAndUsers.sql)|Hard| diff --git a/database/TripsAndUsers.sql b/database/TripsAndUsers.sql new file mode 100644 index 000000000..ed57bf8c3 --- /dev/null +++ b/database/TripsAndUsers.sql @@ -0,0 +1,9 @@ +SELECT t.`Request_at` AS Day, +ROUND(COUNT(CASE WHEN t.`Status` = 'cancelled_by_driver' OR t.`Status` = 'cancelled_by_client' THEN 1 END) / COUNT(*), 2) AS "Cancellation Rate" +FROM Trips t +INNER JOIN Users u +ON t.Client_Id = u.Users_Id +WHERE u.Banned = 'No' +AND t.Request_at >= '2013-10-01' +AND t.Request_at <= '2013-10-03' +GROUP BY t.Request_at \ No newline at end of file diff --git a/myPracticeWithNotes/LargestPalindromeString.cpp b/myPracticeWithNotes/LargestPalindromeString.cpp new file mode 100644 index 000000000..de9920124 --- /dev/null +++ b/myPracticeWithNotes/LargestPalindromeString.cpp @@ -0,0 +1,117 @@ +/* +You are given a string num consisting of digits only. + +Return the largest palindromic integer (in the form of a string) that can be formed using digits taken from num. It should not contain leading zeroes. + +Notes: + +You do not need to use all the digits of num, but you must use at least one digit. +The digits can be reordered. + +Example 1: +Input: num = "444947137" +Output: "7449447" +Explanation: +Use the digits "4449477" from "444947137" to form the palindromic integer "7449447". +It can be shown that "7449447" is the largest palindromic integer that can be formed. + +Example 2: +Input: num = "00009" +Output: "9" +Explanation: +It can be shown that "9" is the largest palindromic integer that can be formed. +Note that the integer returned should not contain leading zeroes. + +Notes: +๐Ÿ“Œ Key Steps in Your Code: +Count digit frequency using vector freq(10, 0). + +***Important: Looping from 9 to 0, build the left side of the palindrome. + +Build left side of palindrome from highest digits down. + +Add freq[i] / 2 copies of digit i. + +Skip leading 0s unless no other digit was used. + +Pick middle digit (odd-count) if exists. + +Mirror left to create right side. + +If no left, but middle is '0' or any digit, return middle. +0099 + +009 +00099 +Time: O(N + 10 log 10) โ‰ˆ O(N) +Space: O(1) (fixed-size frequency array) +*/ +#include +#include +#include +#include +using namespace std; + +class Solution +{ +public: + string largestPalindromic(string num) + { + // First lets get the frequency of each digit + vector freq(10, 0); + for (char c : num) + { + freq[c - '0']++; + } + + // Now let's build the largest palindromic number + string left = "", middle = ""; + for (int i = 9; i >= 0; i--) + { + // cout << "Frequency of " << i << ": " << freq[i] << endl; + if (freq[i] % 2 == 1 && middle.empty()) + { + middle = to_string(i); // Choose the odd digit for the middle + } + + // If we are at digit 0 and no middle digit is set, skip adding leading zeroes + if (left.empty() && i == 0) + { + if (middle.empty()) + { + // Special case if we just have "00" as input + // If no other digits are present, we can use 0 as the middle + middle = "0"; + } + + // If we are at digit 0 and no middle digit is set, skip adding leading zeroes + continue; + } + left += string(freq[i] / 2, '0' + i); // Append half of the even digits + } + // Lets print left, middle here + // cout << "Left part: " << left << endl; + // cout << "Middle part: " << middle << endl; + + // If we have a left part, we can form a palindrome + if (!left.empty()) + { + // Form the largest palindrome + return left + middle + string(left.rbegin(), left.rend()); + } + // If no left part, return the middle digit (if exists) + return middle; + } +}; + +// Example usage: +int main() +{ + Solution solution; + string num = "00099"; + string result = solution.largestPalindromic(num); + // Expected output: "90009" + // Print the result + printf("Result:%s\n", result.c_str()); + return 0; +} diff --git a/myPracticeWithNotes/bestTimeToBuyStockI.cpp b/myPracticeWithNotes/bestTimeToBuyStockI.cpp new file mode 100644 index 000000000..d3ded3ba5 --- /dev/null +++ b/myPracticeWithNotes/bestTimeToBuyStockI.cpp @@ -0,0 +1,50 @@ +// bestTimeTobuyStockI +/* +You can buy and sell the stock Any number of times, +but you must sell the stock before you buy again. +Simple greedy approach: +If the price goes up tomorrow, we can make a profit by buying today and selling tomorrow. + +That means: +You don't even need to track buys/sells explicitly +Just accumulate every positive difference in prices. + +1, 2, 3, 4, 5 +4 is the max profit. + +1 2 1 4 20 +20 is the max profit. + +*/ +#include +#include +using namespace std; + +int maxProfit(vector &prices) +{ + int profit = 0; + for (int i = 1; i < prices.size(); ++i) + { + if (prices[i] > prices[i - 1]) + { + profit += prices[i] - prices[i - 1]; // Buy yesterday, sell today + } + } + return profit; +} + +int main() +{ + vector prices1 = {7, 1, 5, 3, 6, 4}; + cout << "Max Profit for prices1: " << maxProfit(prices1) << endl; // Expected output: 7 + + vector prices2 = {1, 2, 3, 4, 5}; + cout << "Max Profit for prices2: " << maxProfit(prices2) << endl; // Expected output: 4 + + vector prices3 = {7, 6, 4, 3, 1}; + cout << "Max Profit for prices3: " << maxProfit(prices3) << endl; // Expected output: 0 + + vector prices4 = {1, 2, 1, 4, 20}; + cout << "Max Profit for prices4: " << maxProfit(prices4) << endl; // Expected output: 20 + return 0; +} diff --git a/myPracticeWithNotes/bestTimeToBuyStockII.cpp b/myPracticeWithNotes/bestTimeToBuyStockII.cpp new file mode 100644 index 000000000..e25a8bf92 --- /dev/null +++ b/myPracticeWithNotes/bestTimeToBuyStockII.cpp @@ -0,0 +1,80 @@ +// Best time to buy a stock II +/* +You are given an integer array prices where prices[i] is the price of a given stock on the ith day. + +On each day, you may decide to buy and/or sell the stock. You can only hold at most one share of the stock at any time. However, you can buy it then immediately sell it on the same day. + +Find and return the maximum profit you can achieve. + + + +Example 1: + +Input: prices = [7,1,5,3,6,4] +Output: 7 +Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4. +Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3. +Total profit is 4 + 3 = 7. +Example 2: + +Input: prices = [1,2,3,4,5] +Output: 4 +Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4. +Total profit is 4. +Example 3: + +Input: prices = [7,6,4,3,1] +Output: 0 +Explanation: There is no way to make a positive profit, so we never buy the stock to achieve the maximum profit of 0. + +Notes: +Greedy Approach: +We can buy and sell the stock multiple times, so we should buy whenever the price goes up. +Every day we check if the price is higher than the previous day, and if so, we add the difference to our total profit. +We do not need to keep track of minimum prices or maximum prices, as we can simply accumulate profits from every upward movement in price. +*/ + +#include +#include +#include +using namespace std; + +class Solution +{ +public: + int maxProfit(vector &prices) + { + int maxProfit = 0; // Initialize total profit + // Iterate through the price list starting from the second day + for (int i = 1; i < prices.size(); ++i) + { + // If today's price is higher than yesterday's, add the difference to profit + if (prices[i] > prices[i - 1]) + { + maxProfit += prices[i] - prices[i - 1]; // Accumulate profit from every upward price movement + } + } + // Return the total profit from all possible transactions + return maxProfit; + } +}; + +int main() +{ + Solution sol; + vector prices1 = {7, 1, 5, 3, 6, 4}; + vector prices2 = {1, 2, 3, 4, 5}; + vector prices3 = {7, 6, 4, 3, 1}; + + // Test cases + int profit1 = sol.maxProfit(prices1); + int profit2 = sol.maxProfit(prices2); + int profit3 = sol.maxProfit(prices3); + + // Output results + printf("Max Profit for prices1: %d\n", profit1); // Expected: 7 + printf("Max Profit for prices2: %d\n", profit2); // Expected: 4 + printf("Max Profit for prices3: %d\n", profit3); // Expected: 0 + + return 0; +} diff --git a/myPracticeWithNotes/bestTimeToBuyStockIII.cpp b/myPracticeWithNotes/bestTimeToBuyStockIII.cpp new file mode 100644 index 000000000..c4007be2c --- /dev/null +++ b/myPracticeWithNotes/bestTimeToBuyStockIII.cpp @@ -0,0 +1,105 @@ +/* +You are given an array prices where prices[i] is the price of a given stock on the ith day. + +Find the maximum profit you can achieve. You may complete at most two transactions. + +Note: You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again). + + + +Example 1: + +Input: prices = [3,3,5,0,0,3,1,4] +Output: 6 +Explanation: Buy on day 4 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3. +Then buy on day 7 (price = 1) and sell on day 8 (price = 4), profit = 4-1 = 3. +Example 2: + +Input: prices = [1,2,3,4,5] +Output: 4 +Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4. +Note that you cannot buy on day 1, buy on day 2 and sell them later, as you are engaging multiple transactions at the same time. You must sell before buying again. +Example 3: + +Input: prices = [7,6,4,3,1] +Output: 0 +Explanation: In this case, no transaction is done, i.e. max profit = 0. + + +Constraints: + +1 <= prices.length <= 105 +0 <= prices[i] <= 105 + +Notes: + This problem can be solved using dynamic programming. +As the rule says we can sell only after buying, +Lets start from left looking for minPrice and maxProfit +Then we can start from right looking for maxPrice and maxProfit + +So our left pass array will store the max(maxProfit so far, current price - minPrice so far) +And in our right pass we travel from end to start looking for maxPrice and maxProfit +So our right pass array will store the max(maxProfit so far, maxPrice so far - current price) + +If you take both left and right pass on Day 4, +In left pass we will have the max profit by buying at min price before Day 4 and selling on Day 4 +In right pass we will have the max profit by buying at Day 4 and selling at max price after Day 4 +*/ +#include +#include +#include +using namespace std; + +class Solution +{ +public: + int maxProfit(vector &prices) + { + int n = prices.size(); + if (n < 2) + return 0; + + vector left(n, 0), right(n, 0); + int minPrice = prices[0]; + for (int i = 1; i < n; ++i) + { + minPrice = min(minPrice, prices[i]); + // store the max(maxProfit so far, current price - minPrice so far) + left[i] = max(left[i - 1], prices[i] - minPrice); + } + + int maxPrice = prices[n - 1]; + for (int i = n - 2; i >= 0; --i) + { + maxPrice = max(maxPrice, prices[i]); + // store the max(maxProfit so far, maxPrice so far - current price) + right[i] = max(right[i + 1], maxPrice - prices[i]); + } + + int maxProfit = 0; + for (int i = 0; i < n; ++i) + { + // On Day i, + // we combine the max profit by choosing the least price before this Day i and selling today from left[i] + // and the max profit by choosing the highest price after this Day i and buying today from right[i] + maxProfit = max(maxProfit, left[i] + right[i]); + } + + return maxProfit; + } +}; + +int main() +{ + Solution sol; + vector prices1 = {3, 3, 5, 0, 0, 3, 1, 4}; + cout << "Max Profit for prices1: " << sol.maxProfit(prices1) << endl; // Expected output: 6 + + vector prices2 = {1, 2, 3, 4, 5}; + cout << "Max Profit for prices2: " << sol.maxProfit(prices2) << endl; // Expected output: 4 + + vector prices3 = {7, 6, 4, 3, 1}; + cout << "Max Profit for prices3: " << sol.maxProfit(prices3) << endl; // Expected output: 0 + + return 0; +} diff --git a/myPracticeWithNotes/cinemaMaxFamilyGroups.cpp b/myPracticeWithNotes/cinemaMaxFamilyGroups.cpp new file mode 100644 index 000000000..1ba318658 --- /dev/null +++ b/myPracticeWithNotes/cinemaMaxFamilyGroups.cpp @@ -0,0 +1,149 @@ +/* +A cinema has n rows of seats, numbered from 1 to n and there are ten seats in each row, labelled from 1 to 10 as shown in the figure above. + +Given the array reservedSeats containing the numbers of seats already reserved, for example, reservedSeats[i] = [3,8] means the seat located in row 3 and labelled with 8 is already reserved. + +Return the maximum number of four-person groups you can assign on the cinema seats. A four-person group occupies four adjacent seats in one single row. Seats across an aisle (such as [3,3] and [3,4]) are not considered to be adjacent, but there is an exceptional case on which an aisle split a four-person group, in that case, the aisle split a four-person group in the middle, which means to have two people on each side. + + 1 2 3 4 5 6 7 8 9 10 + _ _ _ _ _ _ _ _ _ _ + +Example 1: + +Input: n = 3, reservedSeats = [[1,2],[1,3],[1,8],[2,6],[3,1],[3,10]] +Output: 4 +Explanation: The figure above shows the optimal allocation for four groups, where seats mark with blue are already reserved and contiguous seats mark with orange are for one group. +Example 2: + +Input: n = 2, reservedSeats = [[2,1],[1,8],[2,6]] +Output: 2 +Example 3: + +Input: n = 4, reservedSeats = [[4,3],[1,4],[4,6],[1,7]] +Output: 4 + + +Constraints: + +1 <= n <= 10^9 +1 <= reservedSeats.length <= min(10*n, 10^4) +reservedSeats[i].length == 2 +1 <= reservedSeats[i][0] <= n +1 <= reservedSeats[i][1] <= 10 +All reservedSeats[i] are distinct. + +We are given: + +n rows in a cinema. + +Each row has 10 seats labeled 1 to 10. + +A group of 4 people needs 4 adjacent seats in the same row, but cannot span across aisles (between seat 3โ€“4 or 7โ€“8). + +Valid group blocks are: + +Left block: seats 2,3,4,5 + +Right block: seats 6,7,8,9 + +Middle block: seats 4,5,6,7 (this is allowed even though it straddles an aisle) + +So a reserved seat at column col will set bit 1 << col. + +๐ŸŽฏ Predefined Block Masks: + 10 9 8 7 6 5 4 3 2 1 Bits +Left block (seats 2-5): 0 0 0 0 0 1 1 1 1 0 โ†’ bits 2 to 5 +Middle block (seats 4-7): 0 0 0 1 1 1 1 0 0 0 โ†’ bits 4 to 7 +Right block (seats 6-9): 0 1 1 1 1 0 0 0 0 0 โ†’ bits 6 to 9 + +We check if the corresponding bits in the mask are unset โ†’ that block is available. +*/ + +#include +#include +#include +#include // Include bitset for binary representation +using namespace std; + +class Solution +{ +public: + int maxNumberOfFamilies(int n, vector> &reservedSeats) + { + // rowMap will only store the rows that have reserved seats + // key: row number, value: 10-bit mask representing reserved seats in that row + // So we don't need to store all rows, just the ones with reserved seats + // Since this is a hash we do not have to worry about the row starting from 0 + // We are using rows as 1 to n, so we can directly use the row number as key + unordered_map rowMap; + // Step 1: Build bitmask for each row with reserved seats + for (const auto &seat : reservedSeats) + { + int row = seat[0]; + int col = seat[1]; + // so first left shift 1 to the left by (col - 1) positions + // This sets the bit corresponding to the column in the row's bitmask + // OR it with the existing row's bitmask to mark the seat as reserved + rowMap[row] |= (1 << (col - 1)); + } + + int totalGroups = 0; + // Step 2: Calculate maximum groups for each row + // We only calculate for rows that have reserved seats + // We can have at most 2 groups per row if there are no reserved seats in the blocks + for (const auto &row : rowMap) + { + int rowSeatMask = row.second; + // Check for left block (seats 2-5) + // if any of the bits 2, 3, 4, or 5 are set, then AND will be non-zero + // That means the left block is not available + // If the result of rowSeatMask & 0b0000011110 is 0, + // it means none of those seats are reserved, and we can place a family. + // So we negate it with ! to get a true when the seats are available. + bool left = !(rowSeatMask & 0b0000011110); // seats 2-5 + bool right = !(rowSeatMask & 0b0111100000); // seats 6-9 + bool middle = !(rowSeatMask & 0b0001111000); // seats 4-7 + + if (left && right) + { + // If both left and right blocks are available, we can place 2 groups + totalGroups += 2; + } + else if (left || right || middle) + { + // If any one of the blocks is available, we can place 1 group + totalGroups += 1; + } + std::cout << "Row " << row.first << ": Reserved Mask = " << rowSeatMask + << " (binary: " << std::bitset<10>(rowSeatMask) << ") Total Groups = " << totalGroups << std::endl; + } + // Step 3: Add full rows (no reserved seats) + // Each full row can have 2 groups (left and right blocks) + totalGroups += (n - rowMap.size()) * 2; + return totalGroups; + } +}; + +int main() +{ + Solution sol; + vector> reservedSeats1 = {{1, 2}, {1, 3}, {1, 8}, {2, 6}, {3, 1}, {3, 10}}; + int n1 = 3; + int result1 = sol.maxNumberOfFamilies(n1, reservedSeats1); + // Expected output: 4 + printf("Max number of families for n=%d: %d\n", n1, result1); + + vector> reservedSeats2 = {{2, 1}, {1, 8}, {2, 6}}; + int n2 = 2; + int result2 = sol.maxNumberOfFamilies(n2, reservedSeats2); + // Expected output: 2 + printf("Max number of families for n=%d: %d\n", n2, result2); + + vector> reservedSeats3 = {{4, 3}, {1, 4}, {4, 6}, {1, 7}}; + int n3 = 4; + int result3 = sol.maxNumberOfFamilies(n3, reservedSeats3); + // Expected output: 4 + printf("Max number of families for n=%d: %d\n", n3, result3); + + return 0; +} diff --git a/myPracticeWithNotes/findMissingPositive.cpp b/myPracticeWithNotes/findMissingPositive.cpp new file mode 100644 index 000000000..cd045b818 --- /dev/null +++ b/myPracticeWithNotes/findMissingPositive.cpp @@ -0,0 +1,118 @@ +/* +findMissingPositive +Given an unsorted integer array nums. +Return the smallest positive integer that is not present in nums. +You must implement an algorithm that runs in O(n) time and uses O(1) auxiliary space. +Example 1: + +Input: nums = [1,2,0] +Output: 3 +Explanation: The numbers in the range [1,2] are all in the array. +Example 2: + +Input: nums = [3,4,-1,1] +Output: 2 +Explanation: 1 is in the array but 2 is missing. +Example 3: + +Input: nums = [7,8,9,11,12] +Output: 1 +Explanation: The smallest positive integer 1 is missing. + +****Missing Positive Integer**** +Explanation: If there was no O(n) constraint, we could sort the array and then scan +through it to find the first missing positive integer. +However, we need to do this in O(n) time and O(1) space. +We can achieve this by rearranging the elements in the array such that each number +is placed at its correct index => Weโ€™ll try to place value x at index x - 1. + +Step 1: Ignore invalid numbers (โ‰ค 0 and > n) +Valid values in range [1, n=3] are: 1, 2 +Step 2: Rearranged array (optional in logic, helpful for understanding): +Weโ€™ll try to place value x at index x - 1. + +1 should be at index 0 + +2 at index 1 + +0 is ignored + +Resulting array could look like: +[1, 2, 0] +Step 3: Scan from left to right: +nums[0] == 1 โœ… + +nums[1] == 2 โœ… + +nums[2] != 3 โŒ + +So the first missing positive integer is 3. + +*/ + +#include +#include +#include +using namespace std; + +class Solution +{ +public: + int firstMissingPositive(vector &nums) + { + int n = nums.size(); + + // Step 1: Put each number in its correct position if possible + for (int i = 0; i < n; ++i) + { + // nums[i] should be placed at nums[nums[i] - 1] and continue to swap until + // the current number is either out of range or already in the correct position. + // We also ensure that we don't swap a number to its own position again. + // This ensures that we only swap valid numbers (1 to n) and avoid infinite loops + // or unnecessary swaps. + + // Step 1 : Ignore invalid numbers(โ‰ค 0 and > n) + // because we are looking for the smallest positive integer. + // Valid values in range[1, n = 3] are : 1, 2 + // Input: nums = [7,8,9,11,12] n = 5 + // Output: 1 + // Explanation: The smallest positive integer 1 is missing. + + while (nums[i] >= 1 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) + { + swap(nums[i], nums[nums[i] - 1]); + } + } + + // Step 2: Scan through the array and find the first index i such that nums[i] != i + 1 + for (int i = 0; i < n; ++i) + { + if (nums[i] != i + 1) + { + return i + 1; + } + } + + // Step 3: All values are in correct positions, so return n + 1 + return n + 1; + } +}; + +int main() +{ + Solution sol; + vector nums1 = {1, 2, 0}; + vector nums2 = {3, 4, -1, 1}; + vector nums3 = {7, 8, 9, 11, 12}; + + int result1 = sol.firstMissingPositive(nums1); + int result2 = sol.firstMissingPositive(nums2); + int result3 = sol.firstMissingPositive(nums3); + + // Expected outputs: 3, 2, 1 + printf("First Missing Positive for [1, 2, 0]: %d\n", result1); + printf("First Missing Positive for [3, 4, -1, 1]: %d\n", result2); + printf("First Missing Positive for [7, 8, 9, 11, 12]: %d\n", result3); + + return 0; +} diff --git a/myPracticeWithNotes/gcdOfStrings.cpp b/myPracticeWithNotes/gcdOfStrings.cpp new file mode 100644 index 000000000..33bfdbacb --- /dev/null +++ b/myPracticeWithNotes/gcdOfStrings.cpp @@ -0,0 +1,66 @@ +/* GCD of strings */ +/* +๐Ÿง  Notes: Greatest Common Divisor of Strings +Concept: + +If a string x divides both str1 and str2, then both strings can be expressed as multiples of x. + +Why str1 + str2 == str2 + str1? + +This checks if the order of repetition is consistent. + +If both concatenations yield the same result, it implies both strings are composed of the same base string repeated some number of times. + +If not equal: + +No such base string exists โ†’ return "". + +GCD Logic: + +If base string exists, its length must divide the lengths of both str1 and str2. + +Therefore, compute gcd(str1.size(), str2.size()) and extract the prefix of that length. + +Final Step: + +return str1.substr(0, gcdLength); โ€” gives the actual repeating base string. + +Time Complexity: + +O(n + m), linear in total length of both strings. + +Edge Cases: + +Completely unrelated strings like "LEET" and "CODE". +*/ +#include +#include // for std::gcd +using namespace std; + +class Solution +{ +public: + string gcdOfStrings(string str1, string str2) + { + // Check if they have non-zero GCD string. + if (str1 + str2 != str2 + str1) + { + return ""; + } + + // Get the GCD of the two lengths. + int gcdLength = gcd(str1.size(), str2.size()); + return str1.substr(0, gcdLength); + } +}; + +// Example usage: +int main() +{ + Solution solution; + string str1 = "ABCABC"; + string str2 = "ABC"; + string result = solution.gcdOfStrings(str1, str2); + // Expected output: "ABC" + return 0; +} diff --git a/myPracticeWithNotes/longestHappyString.cpp b/myPracticeWithNotes/longestHappyString.cpp new file mode 100644 index 000000000..9475f163a --- /dev/null +++ b/myPracticeWithNotes/longestHappyString.cpp @@ -0,0 +1,128 @@ +/* +A string s is called happy if it satisfies the following conditions: + +s only contains the letters 'a', 'b', and 'c'. +s does not contain any of "aaa", "bbb", or "ccc" as a substring. +s contains at most a occurrences of the letter 'a'. +s contains at most b occurrences of the letter 'b'. +s contains at most c occurrences of the letter 'c'. +Given three integers a, b, and c, return the longest possible happy string. If there are multiple longest happy strings, return any of them. If there is no such string, return the empty string "". + +A substring is a contiguous sequence of characters within a string. + + + +Example 1: + +Input: a = 1, b = 1, c = 7 +Output: "ccaccbcc" +Explanation: "ccbccacc" would also be a correct answer. +Example 2: + +Input: a = 7, b = 1, c = 0 +Output: "aabaa" +Explanation: It is the only correct answer in this case. + +๐Ÿ” Key Idea: +At every step, greedily choose the character with the most remaining count โ€” unless it would cause 3 in a row. + +If it would cause 3 in a row, use the next best (second most frequent character) instead. + +๐Ÿ› ๏ธ Data Structure: +Use a max heap (priority queue) to always pick the character with the most remaining count. + +๐Ÿ” Algorithm (Greedy + Priority Queue): +Put (count, char) pairs into a max heap (using negative count for max-heap behavior). + +While the heap is not empty: + +Pop the char with highest remaining count. + +If the last two characters in the result are the same as this character, we can't use it. Try the next one. + +If we can't use any character, we're done. + +Else, use the character, update its count, and push it back into the heap if it still has remaining count. + + +*/ + +#include +#include +#include +#include +using namespace std; + +class Solution +{ +public: + string longestHappyString(int a, int b, int c) + { + // Result string to build the happy string + string result = ""; + // Max heap to store counts of characters with their respective letters + priority_queue> maxHeap; + // Push the counts and characters into the max heap + if (a > 0) + maxHeap.push({a, 'a'}); + if (b > 0) + maxHeap.push({b, 'b'}); + if (c > 0) + maxHeap.push({c, 'c'}); + + while (!maxHeap.empty()) + { + // Get the character with the maximum count + auto [c1, ch1] = maxHeap.top(); + maxHeap.pop(); + // Check if the last two characters in the result are the same as this character + + // int len = result.size(); + // if (len >= 2 && result[len - 1] == ch1 && result[len - 2] == ch1) + if (result.ends_with(string(2, ch1))) // C++20 feature to check if the last two characters are same as ch1 + { + // If so, we cannot use this character, we need to try the next one + if (maxHeap.empty()) + { + // If there's no other character to use, we break out of the loop + break; + } + // Get the next character with the second highest count + auto [c2, ch2] = maxHeap.top(); + maxHeap.pop(); + // Append the second character to the result + result += ch2; + // If the second character still has remaining count, push it back into the heap + if (--c2 > 0) + { + maxHeap.push({c2, ch2}); + } + // Push the first character back into the heap + maxHeap.push({c1, ch1}); + } + else + { + // If we can use the first character, append it to the result + result += ch1; + // Decrease its count and push it back into the heap if it still has remaining count + if (--c1 > 0) + { + maxHeap.push({c1, ch1}); + } + } + } + return result; + } +}; + +int main() +{ + Solution sol; + int a = 1, b = 1, c = 7; + cout << "Longest Happy String: " << sol.longestHappyString(a, b, c) << endl; + + a = 7, b = 1, c = 0; + cout << "Longest Happy String: " << sol.longestHappyString(a, b, c) << endl; + + return 0; +} diff --git a/myPracticeWithNotes/maxNumberOfPotHoles.cpp b/myPracticeWithNotes/maxNumberOfPotHoles.cpp new file mode 100644 index 000000000..d8fbc38ee --- /dev/null +++ b/myPracticeWithNotes/maxNumberOfPotHoles.cpp @@ -0,0 +1,125 @@ +/* +You are given a string road, consisting only of characters "x" and ".", where each "x" denotes a pothole and each "." denotes a smooth road, along with an integer budget. + +In one repair operation, you can repair n consecutive potholes for a price of n + 1. + +Return the maximum number of potholes that can be fixed such that the sum of the costs of all repairs doesn't exceed the given budget. + +Notes: +โœ… Problem: Max Number of Potholes Repaired Within Budget +๐Ÿง  Problem Summary: +You're given a string road with 'x' representing potholes and '.' as smooth road, along with a budget. + +Repair cost for n consecutive potholes = n + 1 + +You can only repair complete segments, but if budget is tight, you may partially repair the final segment. + +Goal: Maximize the number of potholes repaired within the given budget. + +๐Ÿ› ๏ธ Approach Summary: +Traverse the string and find segments of consecutive 'x's. + +Store each as {segment_length, segment_cost} in a vector. + +Sort segments by ascending cost. + +Greedily repair as many full segments as possible. + +If one full segment exceeds budget, partially repair it: + +You can fix budget_remaining - 1 potholes (since cost = potholes + 1). + +๐Ÿ” Key Techniques: +Greedy Strategy: Choose cheapest segments first. + +Segment Preprocessing: Add a . at the end to capture trailing segments. + +Custom Comparator: Sort by cost to optimize budget usage. + +Edge Handling: + +Handles trailing potholes (push_back('.')) + +Allows partial repair of final unaffordable segment + +๐Ÿงฎ Time & Space: +Time: O(n log n) โ€“ due to sorting segment costs + +Space: O(n) โ€“ worst case all 1-length pothole segments + +๐Ÿ“Œ Notes for Interviews: +This problem is a classic greedy pattern with twist: full vs. partial repair trade-off. + +Be ready to explain why you sort by cost, and how partial repair logic works. + +Can lead into follow-up system design questions about batching, budget constraints, or real-world sensor signal prioritization. +*/ +#include +#include +#include +#include +using namespace std; + +class Solution +{ +public: + int maxNumberOfPotHoles(string road, int budget) + { + road.push_back('.'); // Append a dot to handle the last segment of potholes + int k = 0; // Count of potholes + vector> repairCosts; // Store costs of repairing segments + for (auto c : road) + { + if (c == 'x') + { + ++k; // Increment pothole count + } + else + { + if (k > 0) + { + // Calculate cost for the segment of potholes + repairCosts.push_back({k, k + 1}); + } + k = 0; // Reset count for next segment + } + } + // Now that i have cost vector we have to sort it by max potholes that can be repaired. + sort(repairCosts.begin(), repairCosts.end(), [](const pair &a, const pair &b) + { + return a.second < b.second; // Sort by cost + }); + + int totalCost = 0; + int maxPotholes = 0; + for (const auto &poth : repairCosts) + { + if (totalCost + poth.second <= budget) + { + totalCost += poth.second; // Add cost of repairing this segment + maxPotholes += poth.first; // Add number of potholes repaired + } + else + { + // If adding whole segment exceeds lets take Part of the segment to fit in budget + int partialSegment = budget - totalCost - 1; // -1 because we need to account for the cost of repairing + maxPotholes += partialSegment; // Add the number of potholes we can repair with the remaining budget + break; // If budget exceeded, stop processing + } + } + + return maxPotholes; // Return the maximum number of potholes repaired + } +}; + +// Example usage: +int main() +{ + Solution solution; + string road = "xxx..xxx.xxx..xxxxxx..xxx"; + int budget = 10; + int result = solution.maxNumberOfPotHoles(road, budget); + // Output the result + cout << "Maximum potholes repaired: " << result << endl; + return 0; +} diff --git a/myPracticeWithNotes/mergeSortedArray.cpp b/myPracticeWithNotes/mergeSortedArray.cpp new file mode 100644 index 000000000..1a793e40d --- /dev/null +++ b/myPracticeWithNotes/mergeSortedArray.cpp @@ -0,0 +1,61 @@ +/* + โœ… NOTES: Merging Two Sorted Arrays In-Place (Leetcode-style) + + ๐Ÿ”ธ Problem Summary: + - nums1 has m sorted elements followed by n empty (0) slots + - nums2 has n sorted elements + - Merge nums2 into nums1 as one sorted array (in-place) + + ๐Ÿ”น Key Points: + 1. Merge from the end (backward) to avoid overwriting nums1's values. + 2. Use three pointers: + - i: end of actual nums1 elements (m - 1) + - j: end of nums2 (n - 1) + - res: last index of nums1 (m + n - 1) + 3. Handle edge cases: + - If nums2 is empty, no action needed. + - If nums1 is empty (m == 0), copy nums2 into nums1. + 4. After merging common parts, copy remaining nums2 elements (if any). + 5. No need to copy remaining nums1 elements โ€” they are already in place. + + ๐Ÿง  Tip: This is a common two-pointer technique used in merging problems. + + tags: #array #string #arrayString +*/ + +class Solution { +public: + void merge(vector& nums1, int m, vector& nums2, int n) { + + int i = m - 1, j = n - 1; // i: pointer for nums1, j: for nums2 + + // If nums2 is empty, nothing to merge + if (n == 0) { + return; + } + + // If nums1 is empty (has 0 valid elements), just copy nums2 + if (m == 0) { + nums1 = nums2; + return; + } + + int res = m + n - 1; // res: position to insert next largest value + + // Merge from the end of both arrays + while (i >= 0 && j >= 0) { + if (nums1[i] >= nums2[j]) { + nums1[res--] = nums1[i--]; + } else { + nums1[res--] = nums2[j--]; + } + } + + // If any elements are left in nums2, copy them + while (j >= 0) { + nums1[res--] = nums2[j--]; + } + + // Remaining nums1 elements (if any) are already in correct place + } +}; diff --git a/myPracticeWithNotes/mergeStringsAlternatively.cpp b/myPracticeWithNotes/mergeStringsAlternatively.cpp new file mode 100644 index 000000000..80e8d0046 --- /dev/null +++ b/myPracticeWithNotes/mergeStringsAlternatively.cpp @@ -0,0 +1,90 @@ +/* +You are given two strings word1 and word2. Merge the strings by adding letters in alternating order, starting with word1. If a string is longer than the other, append the additional letters onto the end of the merged string. + +Return the merged string. + + + +Example 1: + +Input: word1 = "abc", word2 = "pqr" +Output: "apbqcr" +Explanation: The merged string will be merged as so: +word1: a b c +word2: p q r +merged: a p b q c r +*/ + +#include +#include + +using namespace std; + +/* +Key Points for Revision: + +1. Problem: Merge two strings by alternating their characters. If one string is longer, append the rest at the end. + +2. Approach: + - Use two indices to iterate through both strings. + - Add characters alternately to the result string. + - After one string ends, append the remaining characters from the other. + +3. Edge Cases: + - Strings of different lengths. + - One or both strings could be empty. + +4. Complexity: + - Time: O(n + m), where n and m are the lengths of the two strings. + - Space: O(n + m) for the merged string. + +5. STL Usage: + - Use std::string for easy character appending. + - Use string::size() for length checks. + +6. Readability: + - Clear variable names (i, j for indices, merged for result). + - Separate loops for alternating and appending remaining characters. + +7. Testing: + - Test with equal length strings, different lengths, and empty strings. +*/ +class Solution +{ +public: + string mergeAlternately(string word1, string word2) + { + string merged; + int i = 0, j = 0; + + // Merge characters from both strings alternately + while (i < word1.size() && j < word2.size()) + { + merged += word1[i++]; + merged += word2[j++]; + } + + // Append remaining characters from word1, if any + while (i < word1.size()) + { + merged += word1[i++]; + } + + // Append remaining characters from word2, if any + while (j < word2.size()) + { + merged += word2[j++]; + } + + return merged; + } +}; +int main() +{ + Solution solution; + string word1 = "abc"; + string word2 = "pqr"; + string result = solution.mergeAlternately(word1, word2); + cout << "Merged String: " << result << endl; // Output: "apbqcr" + return 0; +} diff --git a/myPracticeWithNotes/minNumberOfFoodBucketsHampsters.cpp b/myPracticeWithNotes/minNumberOfFoodBucketsHampsters.cpp new file mode 100644 index 000000000..c2e8a312a --- /dev/null +++ b/myPracticeWithNotes/minNumberOfFoodBucketsHampsters.cpp @@ -0,0 +1,127 @@ +// Minimum Number of Food Buckets to Feed the Hamsters +#include +#include +#include +using namespace std; +/* +Minimum Number of Food Buckets to Feed the Hamsters +LeetCode Problem No. 2086 +https://leetcode.com/problems/minimum-number-of-food-buckets-to-feed-the-hamsters/ +Medium + +You are given a 0-indexed string hamsters where hamsters[i] is either: + +'H' indicating that there is a hamster at index i, or +'.' indicating that index i is empty. +You will add some number of food buckets at the empty indices in order to feed the hamsters. A hamster can be fed if there is at least one food bucket to its left or to its right. More formally, a hamster at index i can be fed if you place a food bucket at index i - 1 and/or at index i + 1. + +Return the minimum number of food buckets you should place at empty indices to feed all the hamsters or -1 if it is impossible to feed all of them. + +Input: hamsters = "H..H" +Output: 2 +Explanation: We place two food buckets at indices 1 and 2. +It can be shown that if we place only one food bucket, one of the hamsters will not be fed. + +Input: hamsters = ".H.H." +Output: 1 +Explanation: We place one food bucket at index 2. + +Input: hamsters = ".HHH." +Output: -1 +Explanation: If we place a food bucket at every empty index as shown, the hamster at index 2 will not be able to eat. + +Notes +๐Ÿ” Intuition +We want to greedily place a bucket at the most optimal location for each hamster, while minimizing overlap and avoiding double-placing. + +The best spot to put a bucket for an 'H' is at i + 1 if itโ€™s a dot, because: + +It feeds the hamster at i. + +It might also feed the next hamster at i + 2. + +But we have to be careful to avoid conflicts like placing buckets that donโ€™t help or double feeding unnecessarily. +๐Ÿ’ก Greedy Strategy +Loop through the string: + +When you see an 'H': + +First, check if a bucket is already placed at i - 1 (we can skip this hamster). + +Next, try placing a bucket at i + 1, if itโ€™s a '.' Mark it as 'B'. + +If thatโ€™s not possible, try placing a bucket at i - 1, if itโ€™s a '.'. + +If neither is possible, return -1 (this hamster canโ€™t be fed). +*/ + +class Solution +{ +public: + int minimumBuckets(string hamsters) + { + int n = hamsters.size(); + int buckets = 0; + + for (int i = 0; i < n; ++i) + { + if (hamsters[i] == 'H') + { + // First, check if a bucket is already placed at i - 1(we can skip this hamster). + // Covers BH..... + if (i > 0 && hamsters[i - 1] == 'B') + { + continue; + } + + // Next, try placing a bucket at i + 1, if itโ€™s a '.' Mark it as 'B'. + if (i + 1 < n && hamsters[i + 1] == '.') + { + hamsters[i + 1] = 'B'; // Place a bucket at i+1 + buckets++; + } + // If thatโ€™s not possible, try placing a bucket at i - 1, if itโ€™s a '.'. + // H..H + else if (i > 0 && hamsters[i - 1] == '.') + { + hamsters[i - 1] = 'B'; // Place a bucket at i-1 + buckets++; + } + // If neither side is available, it's impossible to feed this hamster + else + { + return -1; + } + } + } + // Return the total number of buckets placed + return buckets; + } +}; + +int main() +{ + Solution sol; + string hamsters1 = "H..H"; + cout << "Minimum Buckets for '" << hamsters1 << "': " << sol.minimumBuckets(hamsters1) << endl; + + string hamsters2 = ".H.H."; + cout << "Minimum Buckets for '" << hamsters2 << "': " << sol.minimumBuckets(hamsters2) << endl; + + string hamsters3 = ".HHH."; + cout << "Minimum Buckets for '" << hamsters3 << "': " << sol.minimumBuckets(hamsters3) << endl; + + // Add tests for edge cases + string hamsters4 = "H"; + cout << "Minimum Buckets for '" << hamsters4 << "': " << sol.minimumBuckets(hamsters4) << endl; + + string hamsters5 = "."; + cout << "Minimum Buckets for '" << hamsters5 << "': " << sol.minimumBuckets(hamsters5) << endl; + + string hamsters6 = "HH"; + cout << "Minimum Buckets for '" << hamsters6 << "': " << sol.minimumBuckets(hamsters6) << endl; + + string hamsters7 = "H.H"; + cout << "Minimum Buckets for '" << hamsters7 << "': " << sol.minimumBuckets(hamsters7) << endl; + return 0; +} diff --git a/myPracticeWithNotes/pathWithMaxMinValue.cpp b/myPracticeWithNotes/pathWithMaxMinValue.cpp new file mode 100644 index 000000000..9a6f25d2c --- /dev/null +++ b/myPracticeWithNotes/pathWithMaxMinValue.cpp @@ -0,0 +1,140 @@ +// Path With Maximum Minimum Value +/* +Medium: leetcode 1102 +Given a 2D grid of integers, find the path from the top-left corner to the bottom-right +corner that maximizes the minimum value along the path. + +This means we want to avoid paths that go through very small numbers, if possible. +In this problem, we have a 2-dimensional grid represented by an m x n matrix. + The goal is to find a path from the top-left corner (0, 0) to the + bottom-right corner (m - 1, n - 1) such that the minimum value encountered on + this path is as high as possible. In other words, we are trying to maximize the + minimum value. While moving through the grid, we can move in any of the + four cardinal directions: up, down, left, or right. + The 'score' of a path is defined as the smallest number on that path. + For example, if a path goes through the numbers [8, 4, 5, 9], +the path's score would be 4, since that is the smallest number encountered on the path. +Example: +Input: grid = [[5,4,5],[1,2,6],[7,4,6]] +Output: 4 +Input: [[5,4,5],[1,2,6],[7,4,6]] +Output: 4 + +Input: [[2,2,1,2,2,2],[1,2,2,2,1,2]] +Output: 2 + +Input: [[3,4,6,3,4],[0,2,1,1,7],[8,8,3,2,7],[3,2,4,9,8],[4,1,2,0,0],[4,6,5,4,3]] +Output: 3 + + +Evaluate my approach +At (i,j) row, col i look around me to find the max value (assume we have another a visited vector) +And we keep track of our path and min value in that path +But i am not sure if this approach we can reach the m-1, n-1 that is our destination + +Your approach is on the right track conceptually, +but it has some critical limitations. +Let's walk through it and evaluate where it works and where it may fall short. + +๐Ÿ” Your Approach Summary: +At position (i, j), you look around (up, down, left, right) for the neighbor with the highest value (among unvisited ones). + +You move to that neighbor. + +While moving, you track the path and maintain the minimum value seen on this path. + +You stop when you reach (m-1, n-1). + +โœ… Strengths: +This greedy strategy intuitively tries to avoid small numbers, which aligns with the goal of maximizing the minimum value. + +You're maintaining a visited array, which prevents cycles and revisits. + +โŒ Weaknesses (Why This Might Fail): +Greedy โ‰  Optimal in this problem: + +Just because a neighbor has a high value now doesn't mean it leads to the best overall path. + +You might choose a high-value cell early on and get stuck later with low values. + +The best path might involve a lower-valued step early to reach a better region. + +Can Miss Valid Paths: + +You only explore the highest-valued neighbor, +but there could be multiple viable paths, +and ignoring the others might cause you to miss the optimal path to (m-1, n-1). + +No Backtracking or State Comparison: + +If you reach a cell with a worse minimum score than a previously discovered path to that same cell, you're not reconsidering it. + +๐Ÿ“‰ Example Where It Might Fail: +plaintext +Copy +Edit +Start at (0, 0): 5 +Neighbors: (0, 1)=4, (1, 0)=1 โ†’ pick (0, 1) +Then maybe stuck at lower-valued paths, +but better route might have started at (1, 0) โ†’ (2, 0)=7 โ†’ (2, 1)=4 โ†’ ... +This is a classic scenario where greedy fails to explore better long-term options. + + +*/ + +#include +#include +#include +using namespace std; + +class Solution +{ +public: + int maximumMinimumPath(vector> &grid) + { + int m = grid.size(), n = grid[0].size(); + + // Track visited cells to avoid re-processing + vector> visited(m, vector(n, false)); + + // Max-heap (priority queue): store tuples of (min_value_along_path, x, y) + // We use negative value because C++ priority_queue is a max-heap by default + priority_queue> pq; + + // Start from (0, 0) with the starting value + pq.push({grid[0][0], 0, 0}); + visited[0][0] = true; + + // Possible movement directions: right, down, up, left + vector> dirs = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; + + while (!pq.empty()) + { + auto [minVal, x, y] = pq.top(); // Current best candidate cell + pq.pop(); + + // If we reached bottom-right cell, return the max-min value found + if (x == m - 1 && y == n - 1) + return minVal; + + for (auto [dx, dy] : dirs) + { + int nx = x + dx; + int ny = y + dy; + + // Check if the new coordinates are valid and unvisited + if (nx >= 0 && ny >= 0 && nx < m && ny < n && !visited[nx][ny]) + { + visited[nx][ny] = true; + + // The new path's minimum value is the min of current and next cell + int nextMin = min(minVal, grid[nx][ny]); + + pq.push({nextMin, nx, ny}); + } + } + } + + return -1; // Edge case: path doesn't exist (shouldn't happen with valid input) + } +}; diff --git a/myPracticeWithNotes/reverseTheWords1.cpp b/myPracticeWithNotes/reverseTheWords1.cpp new file mode 100644 index 000000000..088893545 --- /dev/null +++ b/myPracticeWithNotes/reverseTheWords1.cpp @@ -0,0 +1,97 @@ +// Reverse the words +/* +Input: +s = "the sky is blue" +Step 1: Reverse the entire string: + +s = "eulb si yks eht" +Step 2: Process word by word: +Skip leading spaces + + Copy each word into position right + Reverse each copied word (to fix it) + Add a space + Keep track of the write pointer (right) and start of next word (left) + +Example flow: +After word Operation Intermediate s +"eulb" reverse โ†’ "blue" "blue si yks eht" +"si" reverse โ†’ "is" "blue is yks eht" +"yks" reverse โ†’ "sky" "blue is sky eht" +"eht" reverse โ†’ "the" "blue is sky the" + +Finally trims the last extra space: s.resize(right - 1); +*/ +#include +class Solution +{ +public: + string reverseWords(string s) + { + // Step 1: Reverse the entire string + // s = "the sky is blue" + reverse(s.begin(), s.end()); // Now words are in reverse order + // s = "eulb si yks eht" + + int n = s.size(); + int i = 0; // Pointer to read through the string + int right = 0; // Pointer to write characters in place + int left = 0; // Marks the beginning of the current word in the new string + + while (i < n) + { + // Skip spaces + while (i < n && s[i] == ' ') + i++; + + // If we reached the end after skipping spaces, break + if (i == n) + break; + + // Start copying the word (non-space characters) + // s = "eulb si yks eht" + while (i < n && s[i] != ' ') + { + s[right++] = s[i++]; // Copy current word character to the write position + } + + // Reverse the copied word in-place (to fix the word after full string reverse) + reverse(s.begin() + left, s.begin() + right); + + // Add a single space after the word + s[right++] = ' '; + + // Update left for the next word + left = right; + + // Skip the space after word (because last i++ will have landed on space) + i++; + } + + // Remove the last extra space added (if any words were added) + if (right > 0) + s.resize(right - 1); // Remove trailing space + + return s; + } +}; + +/*Less performant way*/ +int main() +{ + string s = "the sky is blue"; + stringstream ss(s); + string word; + string result; + + // "Pop" each word from s and "append" to result + while (ss >> word) + { + // append to front to reverse order + result = word + " " + result; + } + + // Remove trailing space + if (!result.empty()) + result.pop_back(); +} diff --git a/myPracticeWithNotes/stringcompareTest.cpp b/myPracticeWithNotes/stringcompareTest.cpp new file mode 100644 index 000000000..3078d0fb7 --- /dev/null +++ b/myPracticeWithNotes/stringcompareTest.cpp @@ -0,0 +1,49 @@ +#include +#include +using namespace std; + +int main() +{ + string s = "abcdef"; + // Compare substring "bcd" starting at index 1 with "bcd" + if (s.compare(4, 3, "efg") == 0) + { + cout << "Substring matches 'efg'" << endl; + } + else + { + cout << "Substring does not match 'efg'" << endl; + } + + // Compare substring "ef" starting at index 4 with "ef" + if (s.compare(4, 2, "ef") == 0) + { + cout << "Substring matches 'ef'" << endl; + } + else + { + cout << "Substring does not match 'ef'" << endl; + } + + // Compare substring at index 5 with "fg" (should not match) + if (s.compare(5, 2, "fg") == 0) + { + cout << "Substring matches 'fg'" << endl; + } + else + { + cout << "Substring does not match 'fg'" << endl; + } + + // Compare substring at index 5 with "f" (should match) + if (s.compare(5, 2, "f") == 0) + { + cout << "Substring matches 'f'" << endl; + } + else + { + cout << "Substring does not match 'f'" << endl; + } + + return 0; +} 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..1c170524d 100755 --- a/scripts/comments.sh +++ b/scripts/comments.sh @@ -1,13 +1,20 @@ #!/bin/bash set -e -AUTHOR="Hao Chen" -LEETCODE_URL=https://leetcode.com/problems/ -LEETCODE_NEW_URL=https://leetcode.com/problems/ -LEETCODE_OLD_URL=https://oj.leetcode.com/problems/ +AUTHOR="NOBODY" COMMENT_TAG="//" FILE_EXT=".cpp" +pushd `dirname $0` > /dev/null +SCRIPTPATH=`pwd -P` +popd > /dev/null +SCRIPTFILE=`basename $0` + +COLOR_INFO='\033[0;36m' +COLOR_NONE='\033[0m' + +source ${SCRIPTPATH}/lib/query_problem.sh + function usage() { @@ -23,6 +30,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' @@ -35,57 +54,6 @@ function detect_os() echo ${platform} } -function install_xidel() -{ - echo "Install xidel ..." - if [ ! -d ./xidel ]; then - mkdir xidel - fi - cd xidel - - platform=`detect_os` - - if [[ "$platform" == "unknown" ]]; then - echo "Unknown platform, please install 'xidel' manually!" - exit 1; - fi - - #install the xidel on Linux platform - if [[ "$platform" == "linux" ]]; then - hardware=`uname -m` - xidel_tar=xidel-0.8.4.linux64.tar.gz - case $hardware in - x86_64 ) xidel_tar=xidel-0.8.4.linux64.tar.gz - ;; - i686 ) xidel_tar=xidel-0.8.4.linux32.tar.gz - ;; - * ) echo "Cannot install xidel, please install it manually!" - exit 1; - esac - if [ ! -f ${xidel_tar} ]; then - echo "Downloading xidel......" - curl -L http://softlayer-sng.dl.sourceforge.net/project/videlibri/Xidel/Xidel%200.8.4/${xidel_tar} -o ${xidel_tar} - fi - tar -zxvf ${xidel_tar} - ./install.sh - fi - - #install the xidel on MacOS platform - #refer to: https://www.evernote.com/shard/s69/sh/ff1e78f3-a369-4855-b18f-6184ce789c45/f3511927d0fb356ce883835f2eb712e0 - if [[ "$platform" == "macos" ]]; then - echo "Downloading xidel......" - xidel_zip=xidel.zip - if [ ! -f ${xidel_zip} ]; then - curl -L https://www.evernote.com/shard/s69/sh/ff1e78f3-a369-4855-b18f-6184ce789c45/f3511927d0fb356ce883835f2eb712e0/res/9f156868-01b4-4838-9c2f-935d7a236e05/${xidel_zip} -o ${xidel_zip} - fi - unzip ${xidel_zip} - mv xidel /usr/local/bin/ - fi - - cd .. - echo "Install xidel successfullly !" -} - if [ $# -lt 1 ] || [[ "${1}" != ${LEETCODE_NEW_URL}* ]] && [[ "${1}" != ${LEETCODE_OLD_URL}* ]]; then usage @@ -96,17 +64,29 @@ if [[ "${1}" == ${LEETCODE_OLD_URL}* ]]; then LEETCODE_URL=${LEETCODE_OLD_URL} fi -IS_SHELL=`curl ${1} 2>/dev/null | grep Bash |wc -l` -if [ ${IS_SHELL} -gt 0 ]; then - COMMENT_TAG='#' - FILE_EXT='.sh' -fi - leetcode_url=$1 current_time=`date +%Y-%m-%d` platform=`detect_os` +get_question_slug ${leetcode_url} + + +TRUE_CMD=`which true` +xidel=`type -P xidel || ${TRUE_CMD}` +if [ -z "${xidel}" ]; then + echo "xidel not found !" + install_xidel +fi + +#grab the problem information +query_problem ${leetcode_url} ${QUESTION_TITLE_SLUG} + +if [ "${QUESTION_CATEGORY}" == "Shell" ]; then + COMMENT_TAG='#' + FILE_EXT='.sh' +fi + if [ $# -gt 1 ] && [ -f $2 ]; then source_file=$2 if [[ "$platform" == "linux" ]]; then @@ -115,8 +95,8 @@ if [ $# -gt 1 ] && [ -f $2 ]; then current_time=`stat -f %a ${source_file} | xargs -I time date -r time +%Y-%m-%d` fi else - source_file=${1#${LEETCODE_URL}} - source_file=${source_file::${#source_file}-1} + source_file=$QUESTION_TITLE_SLUG + #source_file=${source_file::${#source_file}-1} source_file=`echo $source_file | awk -F '-' '{for (i=1; i<=NF; i++) printf("%s", toupper(substr($i,1,1)) substr($i,2)) }'`${FILE_EXT} if [ ! -f ${source_file} ]; then @@ -132,12 +112,16 @@ else fi fi + # the source file is existed but it is empty, add a line, # otherwise it could casue the comments inserts failed. 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 @@ -147,38 +131,44 @@ if ! grep -Fq "${COMMENT_TAG} Author :" $source_file ; then rm ${source_file}.bak fi -#grab the problem description and add the comments -TRUE_CMD=`which true` -xidel=`type -P xidel || ${TRUE_CMD}` -if [ -z "${xidel}" ]; then - echo "xidel not found !" - install_xidel -fi -# using xidel grab the problem description + +#echo "$QUESTION_CONTENT" +#echo $QUESTION_DIFFICULTY +#echo $QUESTION_TITLE +#echo $QUESTION_ID +#echo $QUESTION_CATEGORY + + +TMP_FILE=/tmp/tmp.txt + # 1) the `fold` command is used to wrap the text at centain column # 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 |\ + .cpp ) echo "$QUESTION_CONTENT" |\ + 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 + sed 's/^*/ /' > ${TMP_FILE} ;; - .sh ) xidel ${leetcode_url} -q -e "css('div.question-content')" | \ - grep -v ' ' |sed '/^$/N;/^\n$/D' | fold -w 85 -s| \ + .sh ) echo "$QUESTION_CONTENT" |\ + 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 + > ${TMP_FILE} ;; * ) echo "Bad file extension!" exit 1; esac +#remove the ^M chars +cat -v ${TMP_FILE} | tr -d '^M' > ${TMP_FILE}.1 +mv ${TMP_FILE}.1 ${TMP_FILE} + #insert the problem description into the source file, and remove it -sed -i.bak '4 r /tmp/tmp.txt' ${source_file} +sed -i.bak '4 r '${TMP_FILE}'' ${source_file} rm -f ${source_file}.bak rm -f /tmp/tmp.txt diff --git a/scripts/lib/query_problem.sh b/scripts/lib/query_problem.sh new file mode 100644 index 000000000..f895507c9 --- /dev/null +++ b/scripts/lib/query_problem.sh @@ -0,0 +1,135 @@ +#!/bin/bash + +LEETCODE_URL=https://leetcode.com/problems/ +LEETCODE_NEW_URL=https://leetcode.com/problems/ +LEETCODE_OLD_URL=https://oj.leetcode.com/problems/ + + +function get_question_slug() +{ + QUESTION_TITLE_SLUG=${1#${LEETCODE_URL}} + QUESTION_TITLE_SLUG=$(echo $QUESTION_TITLE_SLUG | sed 's/\/.*//g') # remove the needless url path +} + +function query_problem() +{ + TMP_JSON_FILE=tmp.json + +# curl -s "https://leetcode.com/graphql?query=query%20getQuestionDetail(%24titleSlug%3A%20String!)%20%7B%0A%20%20isCurrentUserAuthenticated%0A%20%20question(titleSlug%3A%20%24titleSlug)%20%7B%0A%20%20%20%20questionId%0A%20%20%20%20questionFrontendId%0A%20%20%20%20questionTitle%0A%20%20%20%20translatedTitle%0A%20%20%20%20questionTitleSlug%0A%20%20%20%20content%0A%20%20%20%20translatedContent%0A%20%20%20%20difficulty%0A%20%20%20%20stats%0A%20%20%20%20contributors%0A%20%20%20%20similarQuestions%0A%20%20%20%20discussUrl%0A%20%20%20%20mysqlSchemas%0A%20%20%20%20randomQuestionUrl%0A%20%20%20%20sessionId%0A%20%20%20%20categoryTitle%0A%20%20%20%20submitUrl%0A%20%20%20%20interpretUrl%0A%20%20%20%20codeDefinition%0A%20%20%20%20sampleTestCase%0A%20%20%20%20enableTestMode%0A%20%20%20%20metaData%0A%20%20%20%20enableRunCode%0A%20%20%20%20enableSubmit%0A%20%20%20%20judgerAvailable%0A%20%20%20%20infoVerified%0A%20%20%20%20envInfo%0A%20%20%20%20urlManager%0A%20%20%20%20article%0A%20%20%20%20questionDetailUrl%0A%20%20%20%20discussCategoryId%0A%20%20%20%20discussSolutionCategoryId%0A%20%20%20%20libraryUrl%0A%20%20%20%20companyTags%20%7B%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20slug%0A%20%20%20%20%20%20translatedName%0A%20%20%20%20%7D%0A%20%20%20%20topicTags%20%7B%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20slug%0A%20%20%20%20%20%20translatedName%0A%20%20%20%20%7D%0A%20%20%7D%0A%20%20interviewed%20%7B%0A%20%20%20%20interviewedUrl%0A%20%20%20%20companies%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20name%0A%20%20%20%20%20%20slug%0A%20%20%20%20%7D%0A%20%20%20%20timeOptions%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20name%0A%20%20%20%20%7D%0A%20%20%20%20stageOptions%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20name%0A%20%20%20%20%7D%0A%20%20%7D%0A%20%20subscribeUrl%0A%20%20isPremium%0A%20%20loginUrl%0A%7D%0A&operationName=getQuestionDetail&variables=%7B%22titleSlug%22%3A%22${2}%22%7D" > ${TMP_JSON_FILE} + + # + # NOTE: leetcode server supports `br` encoding and make it high priority. But curl doesn't support it, + # So, you need make sure the `accept-encoding` hasn't br in the request header. + # (if you copy & paste the curl script from Chrome, the `br` could be added!) + # + curl -s 'https://leetcode.com/graphql' \ + -H 'origin: https://leetcode.com' \ + -H 'accept-encoding: gzip, deflate' \ + -H 'accept-language: zh-CN,zh;q=0.9,und;q=0.8,en;q=0.7' \ + -H 'cookie: __cfduid=dae082e425ee3916c04a5170b832e268e1524142659; _ga=GA1.2.1432146910.1524142661; _gid=GA1.2.650843898.1529736240; csrftoken=iSKedVXxGDkBBXbP9chsyXhbIrRedF7iw2EMRZiemtzKD8vjHSWZJKkKQVIwZKp7; __atuvc=2%7C25; __atuvs=5b2ded02313c83c4001; _gat=1' \ + -H 'x-csrftoken: iSKedVXxGDkBBXbP9chsyXhbIrRedF7iw2EMRZiemtzKD8vjHSWZJKkKQVIwZKp7' \ + -H 'pragma: no-cache' \ + -H 'content-type: application/json' \ + -H 'accept: */*' -H 'cache-control: no-cache' \ + -H 'authority: leetcode.com' \ + -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36' \ + -H "referer: ${1}" \ + --data-binary '{"operationName":"getQuestionDetail","variables":{"titleSlug":"'${2}'"},"query":"query getQuestionDetail($titleSlug: String!) {\n isCurrentUserAuthenticated\n question(titleSlug: $titleSlug) {\n questionId\n questionFrontendId\n questionTitle\n translatedTitle\n questionTitleSlug\n content\n translatedContent\n difficulty\n stats\n allowDiscuss\n contributors\n similarQuestions\n mysqlSchemas\n randomQuestionUrl\n sessionId\n categoryTitle\n submitUrl\n interpretUrl\n codeDefinition\n sampleTestCase\n enableTestMode\n metaData\n enableRunCode\n enableSubmit\n judgerAvailable\n infoVerified\n envInfo\n urlManager\n article\n questionDetailUrl\n libraryUrl\n companyTags {\n name\n slug\n translatedName\n __typename\n }\n topicTags {\n name\n slug\n translatedName\n __typename\n }\n __typename\n }\n interviewed {\n interviewedUrl\n companies {\n id\n name\n slug\n __typename\n }\n timeOptions {\n id\n name\n __typename\n }\n stageOptions {\n id\n name\n __typename\n }\n __typename\n }\n subscribeUrl\n isPremium\n loginUrl\n}\n"}' --compressed > ${TMP_JSON_FILE} + + + # xidel change the -q option to -s after 0.9.4 version, so we have to check that + # if xidel has -q option, then it will return error. + + OPT= + + set +e + xidel -q 2>/dev/null + if [ $? -ne 0 ]; then + OPT=-q + else + # if xidel has -s option, then it will return error. + xidel -s 2>/dev/null + if [ $? -ne 0 ]; then + OPT=-s + fi + fi + set -e + + QUESTION_CONTENT=$(xidel ${OPT} ${TMP_JSON_FILE} -e '$json("data").question.content' | sed -e 's/<[^>]*>//g; s/ / /g; s/&/\&/g; s/</\/g; s/"/\"/g; s/'/\'"'"'/g; s/“/\"/g;') + + QUESTION_DIFFICULTY=$(xidel ${OPT} ${TMP_JSON_FILE} -e '$json("data").question.difficulty') + + QUESTION_TITLE=$(xidel ${OPT} ${TMP_JSON_FILE} -e '$json("data").question.questionTitle') + + QUESTION_ID=$(xidel ${OPT} ${TMP_JSON_FILE} -e '$json("data").question.questionId') + + QUESTION_FRONTEND_ID=$(xidel ${OPT} ${TMP_JSON_FILE} -e '$json("data").question.questionFrontendId') + + QUESTION_CATEGORY=$(xidel ${OPT} ${TMP_JSON_FILE} -e '$json("data").question.categoryTitle') + + rm -f $TMP_JSON_FILE +} + +function detect_os() +{ + platform='unknown' + ostype=`uname` + if [[ "$ostype" == 'Linux' ]]; then + platform='linux' + elif [[ "$ostype" == 'Darwin' ]]; then + platform='macos' + fi + echo ${platform} +} + +function install_xidel() +{ + echo "Install xidel ..." + if [ ! -d ./xidel ]; then + mkdir xidel + fi + cd xidel + + platform=`detect_os` + + if [[ "$platform" == "unknown" ]]; then + echo "Unknown platform, please install 'xidel' manually!" + exit 1; + fi + + #install the xidel on Linux platform + xidel_ver=0.9.6 + if [[ "$platform" == "linux" ]]; then + hardware=`uname -m` + xidel_tar=xidel-${xidel_ver}.linux64.tar.gz + case $hardware in + x86_64 ) xidel_tar=xidel-${xidel_ver}.linux64.tar.gz + ;; + i686 ) xidel_tar=xidel-${xidel_ver}.linux32.tar.gz + ;; + * ) echo "Cannot install xidel, please install it manually!" + exit 1; + esac + if [ ! -f ${xidel_tar} ]; then + echo "Downloading xidel......" + curl -s -L https://jaist.dl.sourceforge.net/project/videlibri/Xidel/Xidel%20${xidel_ver}/${xidel_tar} -o ${xidel_tar} + fi + tar -zxvf ${xidel_tar} + sudo ./install.sh + fi + + #install the xidel on MacOS platform + #refer to: https://www.evernote.com/shard/s69/sh/ff1e78f3-a369-4855-b18f-6184ce789c45/f3511927d0fb356ce883835f2eb712e0 + if [[ "$platform" == "macos" ]]; then + echo "Downloading xidel......" + xidel_zip=xidel.zip + if [ ! -f ${xidel_zip} ]; then + curl -L https://www.evernote.com/shard/s69/sh/ff1e78f3-a369-4855-b18f-6184ce789c45/f3511927d0fb356ce883835f2eb712e0/res/de33e89a-cdc6-42b5-a476-32e2df1cf4bc/${xidel_zip} -o ${xidel_zip} + fi + unzip ${xidel_zip} + mv xidel /usr/local/bin/ + fi + + cd .. + echo "Install xidel successfullly !" +} diff --git a/scripts/readme.sh b/scripts/readme.sh new file mode 100755 index 000000000..a66a3b355 --- /dev/null +++ b/scripts/readme.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +pushd `dirname $0` > /dev/null +SCRIPTPATH=`pwd -P` +popd > /dev/null +SCRIPTFILE=`basename $0` + +COLOR_INFO='\033[0;36m' +COLOR_NONE='\033[0m' + +source ${SCRIPTPATH}/lib/query_problem.sh + +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}'` + +URL=$(echo $URL | sed -e 's/oj\.leetcode\.com/leetcode\.com/g') + +get_question_slug ${URL} +query_problem ${URL} ${QUESTION_TITLE_SLUG} + +#echo "$QUESTION_CONTENT" +#echo $QUESTION_DIFFICULTY +#echo $QUESTION_TITLE +#echo $QUESTION_ID +#echo $QUESTION_FRONTEND_ID +#echo $QUESTION_CATEGORY + + +FILE=`echo ${FILE} | sed "s/.*\/algorithms/\.\/algorithms/"` + +echo "|${QUESTION_FRONTEND_ID}|[${QUESTION_TITLE}](${URL}) | [C++](${FILE})|${QUESTION_DIFFICULTY}|"