├── .gitignore ├── LICENSE ├── README.md ├── algorithms ├── 3Sum │ ├── README.md │ └── solve.cpp ├── 4Sum │ ├── README.md │ └── solve.cpp ├── AddBinary │ ├── README.md │ └── solve.cpp ├── AddTwoNumber │ ├── README.md │ └── src.cpp ├── AddandSearchWord │ ├── README.md │ └── trie.cpp ├── Anagrams │ ├── README.md │ └── solve.cpp ├── BalancedBinaryTree │ ├── ' │ ├── README.md │ └── solve.cpp ├── BestTimetoBuyandSellStock │ ├── README.md │ ├── in.txt │ ├── solve1.c │ └── solve2.c ├── BestTimetoBuyandSellStockII │ ├── README.md │ └── solve.c ├── BestTimetoBuyandSellStockIII │ ├── README.md │ ├── TLE_solve.cpp │ ├── in.txt │ └── solve.cpp ├── BinaryTreeInorderTraversal │ ├── README.md │ └── solve.cpp ├── BinaryTreeLevelOrderTraversal │ ├── README.md │ └── tree.cpp ├── BinaryTreeLevelOrderTraversal2 │ ├── README.md │ └── tree.cpp ├── BinaryTreePostorderTraversal │ ├── README.md │ └── tree.cpp ├── BinaryTreePreorderTraversal │ ├── README.md │ └── tree.cpp ├── BinaryTreeRightSideView │ ├── README.md │ └── solve.cpp ├── BinaryTreeZigzagLevelOrderTraversal │ └── tree.cpp ├── BitwiseANDofNumbersRange │ ├── README.md │ └── solve.c ├── CompareVersionNumbers │ ├── README.md │ ├── in.txt │ └── solve.c ├── ContainerWithMostWater │ ├── README.md │ ├── solve.c │ └── test.c ├── ContainsDuplicate │ ├── README.md │ └── solve.cpp ├── ContainsDuplicateII │ ├── README.md │ └── solve.cpp ├── CopyListwithRandomPointer │ ├── README.md │ └── solve.cpp ├── CountPrimes │ ├── README.md │ ├── img │ │ └── Sieve_of_Eratosthenes_animation.gif │ └── solve.cpp ├── CountandSay │ ├── README.md │ ├── itos.cpp │ ├── solve.cpp │ └── stoi.cpp ├── CountingBits │ ├── README.md │ └── solve.cpp ├── CourseSchedule │ ├── README.md │ ├── bfs.cpp │ └── dfs.cpp ├── CourseScheduleII │ ├── README.md │ └── bfs.cpp ├── DecodeWays │ └── solve.c ├── DeleteNodeinaLinkedList │ ├── README.md │ └── list.cpp ├── DivideTwoIntegers │ ├── README.md │ ├── in.txt │ └── solve.c ├── EditDistance │ ├── README.md │ ├── in.txt │ └── solve.c ├── EvaluateReversePolishNotation │ ├── README.md │ └── Solution.java ├── ExcelSheetColumnNumber │ ├── README.md │ ├── in.txt │ └── solve.c ├── ExcelSheetColumnTitle │ ├── README.md │ └── solve.cpp ├── FactorialTrailingZeroes │ ├── README.md │ └── solve.c ├── FindMinimuminRotatedSortedArray │ ├── README.md │ ├── in.txt │ └── solve.cpp ├── FindMinimuminRotatedSortedArray2 │ ├── README.md │ ├── in.txt │ └── solve.cpp ├── FindPeakElement │ ├── README.md │ ├── in.txt │ └── solve.cpp ├── FlattenBinaryTreetoLinkedList │ ├── README.md │ └── solve.cpp ├── GenerateParentheses │ ├── README.md │ └── solve.cpp ├── GrayCode │ ├── README.md │ ├── TLE_solve.cpp │ └── solve.cpp ├── HappyNumber │ ├── README.md │ └── solve.cpp ├── HouseRobber │ ├── README.md │ └── src.c ├── HouseRobberII │ ├── README.md │ ├── in.txt │ └── src.c ├── HouseRobberIII │ ├── README.md │ └── tree.cpp ├── ImplementQueueusingStacks │ ├── README.md │ └── solve.cpp ├── ImplementTrie │ ├── README.md │ └── trie.cpp ├── ImplementstrStr │ ├── README.md │ └── strstr.cpp ├── InsertionSortList │ ├── README.md │ ├── in.txt │ └── list.c ├── IntegertoRoman │ ├── README.md │ └── solve.cpp ├── InterleavingString │ ├── README.md │ ├── in.txt │ ├── solve.cpp │ └── test.cpp ├── IntersectionofTwoLinkedLists │ ├── README.md │ └── solve.c ├── InvertBinaryTree │ ├── README.md │ └── tree.cpp ├── IsomorphicStrings │ ├── README.md │ └── solve.cpp ├── KthLargestElementinanArray │ ├── README.md │ └── solve.cpp ├── KthSmallestElementinaBST │ ├── README.md │ └── tree.cpp ├── LRUCache │ ├── README.md │ ├── in.txt │ ├── solve.c │ └── solve.cpp ├── LargestNumber │ ├── README.md │ ├── solve.c │ └── solve.cpp ├── LengthofLastWord │ ├── LengthofLastWord.c │ └── README.md ├── LetterCombinationsofaPhoneNumber │ ├── README.md │ ├── keypad.png │ └── solve.cpp ├── LinkedListCycle │ ├── README.md │ └── solve.c ├── LinkedListCycle2 │ ├── README.md │ ├── cycle.png │ ├── cycleList.c │ └── solve.c ├── LongestCommonPrefix │ ├── README.md │ └── solve.cpp ├── LongestConsecutiveSequence │ ├── README.md │ ├── in.txt │ └── solve.cpp ├── LongestSubstringWithoutRepeatingCharacters │ ├── README.md │ ├── src1.cpp │ └── src2.cpp ├── LowestCommonAncestorofaBinarySearchTree │ ├── README.md │ └── tree.cpp ├── LowestCommonAncestorofaBinaryTree │ ├── README.md │ └── tree.cpp ├── MajorityElement │ ├── README.md │ ├── in.txt │ └── solve.c ├── MaximumDepthofBinaryTree │ ├── README.md │ └── solve.c ├── MaximumProductSubarray │ ├── README.md │ ├── in.txt │ ├── run.sh │ └── solve.cpp ├── MaximumSubarray │ ├── README.md │ ├── in.txt │ └── solve.c ├── MedianofTwoSortedArrays │ ├── README.md │ ├── kth.c │ └── solve.c ├── MergeSortedArray │ ├── README.md │ ├── in.txt │ └── solve.cpp ├── MergeTwoSortedLists │ ├── README.md │ └── src.c ├── MergekSortedLists │ ├── README.md │ ├── TLE_solve.cpp │ ├── solve.cpp │ └── solve2.cpp ├── MinStack │ ├── README.md │ └── minStack.cpp ├── MinimumDepthofBinaryTree │ ├── README.md │ └── solve.cpp ├── MinimumPathSum │ ├── README.md │ ├── in.txt │ └── solve.cpp ├── MultiplyStrings │ ├── README.md │ ├── in.txt │ └── solve.cpp ├── NextPermutation │ ├── README.md │ └── nextPermutation.c ├── Numberof1Bits │ ├── README.md │ └── solve.c ├── NumberofIslands │ ├── README.md │ └── solve.cpp ├── PalindromeLinkedList │ ├── README.md │ └── list.cpp ├── PalindromeNumber │ ├── README.md │ └── solve.c ├── PartitionList │ ├── README.md │ ├── in.txt │ └── list.cpp ├── PascalsTriangle │ ├── README.md │ └── solve.cpp ├── PascalsTriangleII │ ├── README.md │ └── solve.cpp ├── PathSum │ ├── README.md │ └── solve.c ├── PathSum2 │ ├── README.md │ └── solve.cpp ├── PermutationSequence │ ├── README.md │ └── permutationSequence.c ├── Permutations │ ├── README.md │ └── permutations.cpp ├── Permutations2 │ └── README.md ├── PlusOne │ ├── README.md │ ├── in.txt │ └── solve.cpp ├── PopulatingNextRightPointersinEachNode │ ├── README.md │ └── tree.cpp ├── PopulatingNextRightPointersinEachNodeII │ ├── README.md │ └── tree.cpp ├── Pow │ ├── README.md │ ├── in.txt │ └── pow.c ├── PowerofTwo │ ├── README.md │ └── solve.c ├── ProductofArrayExceptSelf │ ├── README.md │ └── solve.cpp ├── RegularExpressionMatching │ ├── README.md │ ├── in.txt │ └── match.c ├── RemoveDuplicatesfromSortedArray │ ├── README.md │ └── solve.c ├── RemoveDuplicatesfromSortedList │ ├── README.md │ └── solve.c ├── RemoveDuplicatesfromSortedList2 │ ├── README.md │ └── solve.c ├── RemoveElement │ ├── README.md │ └── solve.c ├── RemoveLinkedListElements │ ├── README.md │ └── solve.c ├── RemoveNthNodeFromEndofList │ ├── README.md │ └── solve.c ├── ReorderList │ ├── README.md │ ├── in.txt │ └── solve.cpp ├── ReverseBits │ ├── README.md │ ├── in.txt │ └── solve.c ├── ReverseInteger │ ├── README.md │ ├── solve.c │ └── test.c ├── ReverseLinkedList │ ├── README.md │ └── solve.cpp ├── ReverseLinkedListII │ ├── README.md │ └── solve.cpp ├── ReverseNodesink-Group │ ├── README.md │ └── list.cpp ├── ReverseWordsinaString │ ├── README.md │ └── solve.c ├── RomantoInteger │ ├── README.md │ └── solve.cpp ├── RotateArray │ ├── README.md │ └── solve.c ├── SameTree │ ├── README.md │ └── solve.c ├── SearchInsertPosition │ ├── README.md │ └── solve.c ├── Searcha2DMatrix │ ├── README.md │ ├── in.txt │ └── solve.cpp ├── SearchforaRange │ ├── README.md │ ├── in.txt │ └── solve.cpp ├── SearchinRotatedSortedArray │ ├── README.md │ ├── in.txt │ └── solve.c ├── SingleNumber │ ├── README.md │ └── solve.c ├── SortColors │ ├── README.md │ └── sort.c ├── SortList │ ├── README.md │ ├── in.txt │ ├── list.cpp │ └── solve.cpp ├── Sqrt │ ├── README.md │ ├── in.txt │ └── solve.c ├── StringtoInteger │ ├── README.md │ ├── atoi.c │ └── test.c ├── Subsets │ ├── README.md │ └── solve.cpp ├── SubsetsII │ ├── README.md │ └── solve.cpp ├── SumRoottoLeafNumbers │ ├── README.md │ └── tree.cpp ├── SummaryRanges │ ├── README.md │ └── solve.cpp ├── SwapNodesinPairs │ ├── README.md │ └── list.cpp ├── SymmetricTree │ ├── README.md │ └── solve.c ├── Template │ ├── list │ │ ├── list.c │ │ └── list.cpp │ └── tree │ │ └── tree.cpp ├── Triangle │ ├── README.md │ └── solve.cpp ├── TwoSum │ ├── README.md │ └── src.cpp ├── UniqueBinarySearchTrees │ ├── README.md │ └── solve.c ├── ValidAnagram │ ├── README.md │ ├── in.txt │ └── solve.c ├── ValidNumber │ ├── README.md │ ├── in.txt │ ├── test.c │ └── validNumber.c ├── ValidPalindrome │ ├── README.md │ └── solve.cpp ├── ValidParentheses │ ├── README.md │ ├── in.txt │ └── solve.c ├── ValidSudoku │ ├── README.md │ ├── in.txt │ └── solve.cpp ├── ValidateBinarySearchTree │ ├── README.md │ └── tree.cpp ├── WordBreak │ ├── README.md │ └── solve.cpp └── WordSearch │ ├── README.md │ └── solve.cpp ├── database ├── .gitkeep ├── CombineTwoTables │ ├── README.md │ └── solve.sql ├── ConsecutiveNumbers │ ├── README.md │ ├── consecutiveNumbers.sql │ └── when.sql ├── CustomersWhoNeverOrder │ ├── README.md │ └── solve.sql ├── DeleteDuplicateEmails │ ├── README.md │ └── solve.sql ├── DepartmentHighestSalary │ ├── README.md │ └── solve.sql ├── DepartmentTopThreeSalaries │ └── solve.sql ├── DuplicateEmails │ ├── README.md │ └── duplicateEmails.sql ├── EmployeesEarningMoreThanTheirManagers │ ├── README.md │ └── employeesEarningMoreThanTheirManagers.sql ├── NthHighestSalary │ ├── README.md │ ├── functions.sql │ └── solve.sql ├── RankScores │ ├── README.md │ └── solve.sql ├── RisingTemperature │ ├── README.md │ └── solve.sql └── SecondHighestSalary │ ├── README.md │ └── solve.sql └── shell ├── .gitkeep ├── TenthLine ├── README.md ├── file.txt └── tenthLine.sh ├── TransposeFile ├── README.md ├── file.txt ├── transposeFile.sh └── transposeFile2.sh ├── ValidPhoneNumbers ├── README.md ├── file.txt └── validPhoneNumbers.sh └── WordFrequency ├── README.md ├── wordFrequency.sh └── words.txt /.gitignore: -------------------------------------------------------------------------------- 1 | a.out 2 | *~ 3 | *.swp 4 | core 5 | # Object files 6 | *.o 7 | *.ko 8 | *.obj 9 | *.elf 10 | 11 | # Precompiled Headers 12 | *.gch 13 | *.pch 14 | 15 | # Libraries 16 | *.lib 17 | *.a 18 | *.la 19 | *.lo 20 | 21 | # Shared objects (inc. Windows DLLs) 22 | *.dll 23 | *.so 24 | *.so.* 25 | *.dylib 26 | 27 | # Executables 28 | *.exe 29 | *.out 30 | *.app 31 | *.i*86 32 | *.x86_64 33 | *.hex 34 | 35 | # Debug files 36 | *.dSYM/ 37 | *.class 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 krystism 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /algorithms/Anagrams/README.md: -------------------------------------------------------------------------------- 1 | ## Anagrams 2 | 3 | Given an array of strings, return all groups of strings that are anagrams. 4 | 5 | Note: All inputs will be in lower-case. 6 | 7 | ## Solution 8 | 9 | 两个单词的字符相同,只是排列顺序不同,称为回文构词法(anagrams), 比如tea eta ate aet都是anagrams。 10 | 11 | 题目要求找出所有的anagrams组,比如`["dog","cat","god","tac", "hello", "world"]`, 应该返回`["dog","cat","god","tac"]`, 12 | 因为dog 和 god是一组, cat和tac是一组,即 13 | 14 | ``` 15 | [ 16 | ["dog", "god"], 17 | ["cat", "tac"] 18 | ] 19 | ``` 20 | 21 | 判断两个字符串是不是anagrams,最简单的方法是对字符排序然后判断是否相等。比如`tac`、`cat`按字符排序后分别为`act`、`act`,显然是相等的,因此互为anagrams. 22 | 23 | 给定一个字符串数组,如何找出所有的anagrams组。当一个字符串处理时,我们需要判断之前是否出现过互为anagrams的字符串。 24 | 如果没有出现过,我们保存到一个map中,key保存字符串的排序后的字符串,value保存第一次出现的索引。若已经出现过,并且当前是 25 | 第二次出现,则前一次出现的和当前的字符串互为anagrams 26 | 27 | ```cpp 28 | vector anagrams(const vector& strs) { 29 | unordered_map m; 30 | vector result; 31 | for (int i = 0; i < strs.size(); ++i) { 32 | string s = strs[i]; 33 | sort(begin(s), end(s)); 34 | if (m.find(s) == m.end()) { 35 | m[s] = i; 36 | } else { 37 | if (m[s] >= 0) { 38 | result.push_back(strs[m[s]]); 39 | m[s] = -1; 40 | } 41 | result.push_back(strs[i]); 42 | } 43 | } 44 | return result; 45 | } 46 | ``` 47 | -------------------------------------------------------------------------------- /algorithms/Anagrams/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | vector anagrams(const vector& strs) { 9 | unordered_map m; 10 | vector result; 11 | for (int i = 0; i < strs.size(); ++i) { 12 | string s = strs[i]; 13 | sort(begin(s), end(s)); 14 | if (m.find(s) == m.end()) { 15 | m[s] = i; 16 | } else { 17 | if (m[s] >= 0) { 18 | result.push_back(strs[m[s]]); 19 | m[s] = -1; 20 | } 21 | result.push_back(strs[i]); 22 | } 23 | } 24 | return result; 25 | } 26 | }; 27 | int main(int argc, char **argv) 28 | { 29 | Solution solution; 30 | vector strs = {"tea", "and", "ate", "eat", "den"}; 31 | auto result = solution.anagrams(strs); 32 | for_each(begin(result), end(result), [](string s) {cout << s << " ";}); 33 | cout << endl; 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /algorithms/BalancedBinaryTree/': -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | struct TreeNode { 4 | int val; 5 | TreeNode *left; 6 | TreeNode *right; 7 | TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | }; 9 | class Solution { 10 | public: 11 | bool isBalanced(TreeNode *root) { 12 | if (root == NULL) 13 | return true; 14 | if (root->left && root->right) 15 | return isBalanced(root->left) && isBalanced(root->right); 16 | if (root->left) { 17 | return root->left->left && !root->left->right; 18 | if (root->left->left || root->left->right) 19 | return false; 20 | else 21 | return true; 22 | } 23 | } 24 | 25 | }; 26 | int main(int argc, char **argv) 27 | { 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /algorithms/BalancedBinaryTree/README.md: -------------------------------------------------------------------------------- 1 | ## Balanced Binary Tree 2 | 3 | Given a binary tree, determine if it is height-balanced. 4 | 5 | For this problem, a height-balanced binary tree is defined as a binary tree in which the depth of the two subtrees of every node never differ by more than 1. 6 | 7 | ## Solution 8 | 9 | 分别求左右子树的高度,如果高度之差大于1,则不是平衡树 10 | 11 | 而如果子树不是平衡树,结果也一定不是平衡树,因此再求左右子树的同时,顺便判断是否平衡树,能够提高速度 12 | 13 | ## Code 14 | ```cpp 15 | bool isBalanced(TreeNode *root) { 16 | bool unbalenced = false; 17 | getHeight(unbalenced, root); 18 | return !unbalenced; 19 | } 20 | int getHeight(bool &unbalenced, TreeNode *root) { 21 | if (root == NULL || unbalenced) 22 | return -1; 23 | int left = getHeight(unbalenced, root->left); 24 | int right = getHeight(unbalenced, root->right); 25 | if (abs(left, right) > 1) { 26 | unbalenced = true; 27 | } 28 | return 1 + (left > right ? left : right); 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /algorithms/BalancedBinaryTree/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | struct TreeNode { 4 | int val; 5 | TreeNode *left; 6 | TreeNode *right; 7 | TreeNode(int x) : val(x), left(NULL), right(NULL) {} 8 | }; 9 | static inline int abs(int a, int b) 10 | { 11 | return a > b ? a - b : b - a; 12 | } 13 | class Solution { 14 | public: 15 | bool isBalanced(TreeNode *root) { 16 | bool unbalenced = false; 17 | getHeight(unbalenced, root); 18 | return !unbalenced; 19 | } 20 | int getHeight(bool &unbalenced, TreeNode *root) { 21 | if (root == NULL || unbalenced) 22 | return -1; 23 | int left = getHeight(unbalenced, root->left); 24 | int right = getHeight(unbalenced, root->right); 25 | if (abs(left, right) > 1) { 26 | unbalenced = true; 27 | } 28 | return 1 + (left > right ? left : right); 29 | } 30 | 31 | }; 32 | int main(int argc, char **argv) 33 | { 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /algorithms/BestTimetoBuyandSellStock/README.md: -------------------------------------------------------------------------------- 1 | ## Best Time to Buy and Sell Stock 2 | 3 | Say you have an array for which the ith element is the price of a given stock on day i. 4 | 5 | If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit. 6 | 7 | ## Solution 8 | 9 | 本质就是求数对之差最大值,只需要保存前面的最小值,然后当前值减去最小值一定是最大的 10 | 11 | ```c 12 | int maxProfit(int *a, int n) 13 | { 14 | int min = a[0]; 15 | int max = 0; 16 | for (int i = 1; i < n; ++i) { 17 | min = MIN(min, a[i]); 18 | max = MAX(max, a[i] - min); 19 | } 20 | return max; 21 | } 22 | ``` 23 | -------------------------------------------------------------------------------- /algorithms/BestTimetoBuyandSellStock/in.txt: -------------------------------------------------------------------------------- 1 | 5 2 | 3 4 1 5 6 3 | 5 4 | 5 4 3 2 1 5 | 5 6 | 1 2 3 4 5 7 | -------------------------------------------------------------------------------- /algorithms/BestTimetoBuyandSellStock/solve1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | static inline int MIN(int a, int b) 6 | { 7 | return a < b ? a : b; 8 | } 9 | static inline int MAX(int a, int b) 10 | { 11 | return a > b ? a : b; 12 | } 13 | int maxProfit(int *a, int n) 14 | { 15 | int min = a[0]; 16 | int max = 0; 17 | for (int i = 1; i < n; ++i) { 18 | min = MIN(min, a[i]); 19 | max = MAX(max, a[i] - min); 20 | } 21 | return max; 22 | } 23 | int main(int argc, char **argv) 24 | { 25 | int a[20], n; 26 | while (scanf("%d", &n) != EOF) { 27 | for (int i = 0; i < n; ++i) 28 | scanf("%d", a + i); 29 | printf("maxProfit = %d\n", maxProfit(a, n)); 30 | } 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /algorithms/BestTimetoBuyandSellStock/solve2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | static inline int MIN(int a, int b) 6 | { 7 | return a < b ? a : b; 8 | } 9 | static inline int MAX(int a, int b) 10 | { 11 | return a > b ? a : b; 12 | } 13 | int maxProfit(int *a, int n) 14 | { 15 | int max = a[n - 1]; 16 | int profit = 0; 17 | for (int i = n - 2; i >= 0; --i) { 18 | max = MAX(max, a[i]); 19 | profit = MAX(profit, max - a[i]); 20 | } 21 | return profit; 22 | } 23 | /* 24 | int maxProfit(int *a, int n) 25 | { 26 | int min = a[0]; 27 | int max = 0; 28 | for (int i = 1; i < n; ++i) { 29 | min = MIN(min, a[i]); 30 | max = MAX(max, a[i] - min); 31 | } 32 | return max; 33 | } 34 | */ 35 | int main(int argc, char **argv) 36 | { 37 | int a[20], n; 38 | while (scanf("%d", &n) != EOF) { 39 | for (int i = 0; i < n; ++i) 40 | scanf("%d", a + i); 41 | printf("maxProfit = %d\n", maxProfit(a, n)); 42 | } 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /algorithms/BestTimetoBuyandSellStockII/README.md: -------------------------------------------------------------------------------- 1 | ## Best Time to Buy and Sell Stock II 2 | 3 | Say you have an array for which the ith element is the price of a given stock on day i. 4 | 5 | Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again). 6 | 7 | ## Solution 8 | 9 | 贪心算法,只要当天比昨天的贵,即有钱赚,就买买买! 10 | 11 | ```c 12 | int maxProfit(int *a, int n) 13 | { 14 | if (a == NULL || n < 1) 15 | return 0; 16 | int profit = 0; 17 | for (int i = 1; i < n; ++i) { 18 | int diff = a[i] - a[i - 1]; 19 | if (diff > 0) 20 | profit += diff; 21 | } 22 | return profit; 23 | } 24 | ``` 25 | 26 | ## 扩展 27 | 28 | [Best Time to Buy and Sell Stock](../BestTimetoBuyandSellStock), 只能交易一次,动态规划 29 | [Best Time to Buy and Sell Stock II](#),能不限次数交易, 贪心算法 30 | [Best Time to Buy and Sell Stock III](../Best Time to Buy and Sell Stock III) 31 | -------------------------------------------------------------------------------- /algorithms/BestTimetoBuyandSellStockII/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int maxProfit(int *a, int n) 5 | { 6 | if (a == NULL || n < 1) 7 | return 0; 8 | int profit = 0; 9 | for (int i = 1; i < n; ++i) { 10 | int diff = a[i] - a[i - 1]; 11 | if (diff > 0) 12 | profit += diff; 13 | } 14 | return profit; 15 | } 16 | int main(int argc, char **argv) 17 | { 18 | int a[] = {3, 1, 2, 6,5,6}; 19 | printf("%d\n", maxProfit(a, 6)); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /algorithms/BestTimetoBuyandSellStockIII/TLE_solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | class Solution { 8 | public: 9 | int maxProfit(vector& prices) { 10 | int n = prices.size(); 11 | if (n <= 1) 12 | return 0; 13 | int profit = 0; 14 | for (int i = 0; i < prices.size(); ++i) { 15 | int p = maxProfit(prices, 0, i) + maxProfit(prices, i, n - 1); 16 | profit = max(profit, p); 17 | } 18 | return profit; 19 | } 20 | private: 21 | int maxProfit(vector& a, int s, int t) { 22 | if (s >= t) 23 | return 0; 24 | int profit = 0; 25 | int minPrice = a[s]; 26 | for (int i = s + 1; i <= t; ++i) { 27 | minPrice = min(minPrice, a[i]); 28 | profit = max(profit, a[i] - minPrice); 29 | } 30 | return profit; 31 | } 32 | }; 33 | int main(int argc, char **argv) 34 | { 35 | Solution solution; 36 | vector prices; 37 | int n; 38 | while(scanf("%d", &n) != EOF) { 39 | prices.clear(); 40 | for (int i = 0; i < n; ++i) { 41 | int v; 42 | scanf("%d", &v); 43 | prices.push_back(v); 44 | } 45 | printf("maxProfit = %d\n", solution.maxProfit(prices)); 46 | } 47 | return 0; 48 | 49 | } 50 | -------------------------------------------------------------------------------- /algorithms/BestTimetoBuyandSellStockIII/in.txt: -------------------------------------------------------------------------------- 1 | 2 2 | 1 2 3 | 7 4 | 1 2 6 1 3 5 6 5 | 4 6 | 1 6 2 7 7 | 4 8 | 1 5 6 7 9 | 7 10 | 3 2 0 6 1 7 9 11 | -------------------------------------------------------------------------------- /algorithms/BestTimetoBuyandSellStockIII/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | static inline void print(const vector &v) 8 | { 9 | for_each(v.begin(), v.end(), [](int i){cout << i << " ";}); 10 | cout << endl; 11 | } 12 | class Solution { 13 | public: 14 | int maxProfit(vector& prices) { 15 | int n = prices.size(); 16 | if (n <= 1) 17 | return 0; 18 | vector leftMin(n, 0); 19 | leftMin[0] = prices[0]; 20 | for (int i = 1; i < n; ++i) { 21 | leftMin[i] = min(leftMin[i - 1], prices[i]); 22 | } 23 | vector rightMax(n, 0); 24 | rightMax[0] = prices[n - 1]; 25 | for (int i = n - 2, k = 1; i >=0; --i, k++) 26 | rightMax[k] = max(rightMax[k - 1], prices[i]); 27 | int left = 0, right = 0; 28 | int profit = 0; 29 | for (int i = 0; i < n; ++i) { 30 | left = max(left, prices[i] - leftMin[i]); 31 | right = rightMax[n - i - 1] - prices[i]; 32 | profit = max(profit, left + right); 33 | } 34 | return profit; 35 | } 36 | }; 37 | int main(int argc, char **argv) 38 | { 39 | Solution solution; 40 | vector prices; 41 | int n; 42 | while(scanf("%d", &n) != EOF) { 43 | prices.clear(); 44 | for (int i = 0; i < n; ++i) { 45 | int v; 46 | scanf("%d", &v); 47 | prices.push_back(v); 48 | } 49 | printf("maxProfit = %d\n", solution.maxProfit(prices)); 50 | } 51 | return 0; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /algorithms/BinaryTreeInorderTraversal/README.md: -------------------------------------------------------------------------------- 1 | ## Binary Tree Inorder Traversal 2 | 3 | Given a binary tree, return the inorder traversal of its nodes' values. 4 | 5 | For example: 6 | Given binary tree `{1,#,2,3}`, 7 | ``` 8 | 1 9 | \ 10 | 2 11 | / 12 | 3 13 | ``` 14 | return `[1,3,2]`. 15 | 16 | Note: Recursive solution is trivial, could you do it iteratively? 17 | 18 | OJ's Binary Tree Serialization: 19 | The serialization of a binary tree follows a level order traversal, where '#' signifies a path terminator where no node exists below. 20 | 21 | Here's an example: 22 | ``` 23 | 1 24 | / \ 25 | 2 3 26 | / 27 | 4 28 | \ 29 | 5 30 | ``` 31 | The above binary tree is serialized as "`{1,2,3,#,#,4,#,#,5}`". 32 | 33 | ## Solution 34 | 35 | 递归方法 36 | ```cpp 37 | void recursive(vector &result, TreeNode *root) { 38 | if (root == nullptr) 39 | return; 40 | recursive(result, root->left); 41 | result.push_back(root->val); 42 | recursive(result, root->right); 43 | } 44 | ``` 45 | 46 | 迭代方法 47 | 48 | ```cpp 49 | void loop(vector &result, TreeNode *root) { 50 | if (root == nullptr) 51 | return; 52 | stack s; 53 | TreeNode *cur = root; 54 | while (cur || !s.empty()) { 55 | while (cur) { 56 | s.push(cur); 57 | cur = cur->left; 58 | } 59 | cur = s.top(); 60 | s.pop(); 61 | result.push_back(cur->val); 62 | cur = cur->right; 63 | } 64 | } 65 | ``` 66 | -------------------------------------------------------------------------------- /algorithms/BinaryTreeLevelOrderTraversal/README.md: -------------------------------------------------------------------------------- 1 | ## Binary Tree Level Order Traversal 2 | 3 | Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). 4 | 5 | For example: 6 | Given binary tree `{3,9,20,#,#,15,7}`, 7 | ``` 8 | 3 9 | / \ 10 | 9 20 11 | / \ 12 | 15 7 13 | ``` 14 | return its level order traversal as: 15 | ``` 16 | [ 17 | [3], 18 | [9,20], 19 | [15,7] 20 | ] 21 | ``` 22 | confused what "`{1,#,2,3}`" means? > read more on how binary tree is serialized on OJ. 23 | 24 | ## Solution 25 | 26 | 27 | 层次遍历,使用队列。 28 | 29 | 需要保存层次,因此封装了一个桶用于保存处于的层次 30 | ```cpp 31 | vector> levelOrder(TreeNode *root) { 32 | vector> result; 33 | if (root == nullptr) 34 | return result; 35 | queue q; 36 | result.push_back(vector()); 37 | int curLevel = 0; 38 | q.push(Bucket(root, 0)); 39 | while (!q.empty()) { 40 | Bucket bucket = q.front(); 41 | q.pop(); 42 | TreeNode *p = bucket.node; 43 | int level = bucket.level; 44 | if (level != curLevel) { 45 | result.push_back(vector()); 46 | curLevel++; 47 | } 48 | result[curLevel].push_back(p->val); 49 | if (p->left) 50 | q.push(Bucket(p->left, level + 1)); 51 | if (p->right) 52 | q.push(Bucket(p->right, level + 1)); 53 | } 54 | return result; 55 | } 56 | ``` 57 | -------------------------------------------------------------------------------- /algorithms/BinaryTreeLevelOrderTraversal2/README.md: -------------------------------------------------------------------------------- 1 | ## Binary Tree Level Order Traversal II 2 | 3 | Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root). 4 | 5 | For example: 6 | Given binary tree `{3,9,20,#,#,15,7}`, 7 | ``` 8 | 3 9 | / \ 10 | 9 20 11 | / \ 12 | 15 7 13 | ``` 14 | return its bottom-up level order traversal as: 15 | ``` 16 | [ 17 | [15,7], 18 | [9,20], 19 | [3] 20 | ] 21 | ``` 22 | confused what "`{1,#,2,3}`" means? > read more on how binary tree is serialized on OJ. 23 | 24 | ## Solution 25 | 26 | 思路就是常规的BFS,然后把结果reverse ? 27 | 28 | 应该还有其他更优算法? 29 | ```cpp 30 | vector> levelOrderBottom(TreeNode *root) { 31 | vector> result; 32 | if (root == nullptr) 33 | return result; 34 | queue q; 35 | result.push_back(vector()); 36 | int curLevel = 0; 37 | q.push(Bucket(root, 0)); 38 | while (!q.empty()) { 39 | Bucket bucket = q.front(); 40 | q.pop(); 41 | TreeNode *p = bucket.node; 42 | int level = bucket.level; 43 | if (level != curLevel) { 44 | result.push_back(vector()); 45 | curLevel++; 46 | } 47 | result[curLevel].push_back(p->val); 48 | if (p->left) 49 | q.push(Bucket(p->left, level + 1)); 50 | if (p->right) 51 | q.push(Bucket(p->right, level + 1)); 52 | } 53 | reverse(result.begin(), result.end()); 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /algorithms/BinaryTreePreorderTraversal/README.md: -------------------------------------------------------------------------------- 1 | ## Binary Tree Preorder Traversal 2 | 3 | Given a binary tree, return the preorder traversal of its nodes' values. 4 | 5 | For example: 6 | Given binary tree {1,#,2,3}, 7 | ``` 8 | 1 9 | \ 10 | 2 11 | / 12 | 3 13 | ``` 14 | 15 | return `[1,2,3]`. 16 | 17 | Note: Recursive solution is trivial, could you do it iteratively? 18 | 19 | ## Solution 20 | 21 | 前序遍历,使用递归,就太简单了。 22 | 23 | 如何使用迭代的方式,其实就是使用栈模拟递归(注意递归(DFS)和栈的关系,队列和BFS的关系) 24 | 25 | 先访问节点,然后压入右孩子,压入左孩子. 26 | ```cpp 27 | vector preorderTraversal(TreeNode *root) { 28 | vector result; 29 | if (root == NULL) 30 | return result; 31 | stacks; 32 | s.push(root); 33 | while (!s.empty()) { 34 | TreeNode *p = s.top(); 35 | s.pop(); 36 | result.push_back(p->val); 37 | if (p->right) 38 | s.push(p->right); 39 | if (p->left) 40 | s.push(p->left); 41 | } 42 | return result; 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /algorithms/BinaryTreeRightSideView/README.md: -------------------------------------------------------------------------------- 1 | ## Binary Tree Right Side View 2 | 3 | Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom. 4 | 5 | For example: 6 | Given the following binary tree, 7 | 8 | ``` 9 | 10 | 1 <--- 11 | / \ 12 | 2 3 <--- 13 | \ \ 14 | 5 4 <--- 15 | ``` 16 | 17 | You should return `[1, 3, 4]`. 18 | 19 | ## Solution 20 | 21 | 求每一层的最右的一个节点,层次遍历树,每一层的最后一个节点就是结果元素 22 | 23 | 使用一个桶封装树节点,加上层次,当遍历层次更新时,上一个节点就是上一个层次的最后一个节点 24 | 25 | ## Code 26 | ```cpp 27 | typedef struct bucket{ 28 | TreeNode *node; 29 | int level; 30 | bucket(TreeNode *n, int l):node(n), level(l){} 31 | } bucket, *Bucket; 32 | class Solution { 33 | public: 34 | vector rightSideView(TreeNode *root) { 35 | vector result; 36 | if (root == nullptr) 37 | return result; 38 | queue q; 39 | q.push(bucket(root, 0)); 40 | int level = 0; 41 | while (!q.empty()) { 42 | auto b = q.front(); 43 | q.pop(); 44 | auto p = b.node; 45 | if (p->left) 46 | q.push(bucket(p->left, level + 1)); 47 | if (p->right) 48 | q.push(bucket(p->right, level + 1)); 49 | if (q.empty() || q.front().level != level) { 50 | result.push_back(p->val); 51 | level = q.front().level; 52 | } 53 | } 54 | return result; 55 | } 56 | }; 57 | ``` 58 | -------------------------------------------------------------------------------- /algorithms/CompareVersionNumbers/README.md: -------------------------------------------------------------------------------- 1 | ## Compare Version Numbers 2 | 3 | Compare two version numbers version1 and version2. 4 | If version1 > version2 return 1, if version1 < version2 return -1, otherwise return 0. 5 | 6 | You may assume that the version strings are non-empty and contain only digits and the . character. 7 | The . character does not represent a decimal point and is used to separate number sequences. 8 | For instance, 2.5 is not "two and a half" or "half way to version three", it is the fifth second-level revision of the second first-level revision. 9 | 10 | Here is an example of version numbers ordering: 11 | 12 | `0.1 < 1.1 < 1.2 < 13.37` 13 | Credits: 14 | Special thanks to @ts for adding this problem and creating all test cases. 15 | 16 | ## Sulution 17 | 18 | 直接按`.`划分,依次比较即可,如果比较不相等后面就不需要比较了。比如`1.2.12 和 1.3.123`,当第二个子版本序列`2 < 3`,因此后面不需要比较了。 19 | 20 | 注意不能用`sprintf(buf, "%f", version)`把字符串转化成浮点再比较大小,因为有可能有多个`.`,即多个子版本。 21 | 22 | ## Code 23 | ```c 24 | int compareVersion(char* version1, char* version2) { 25 | char *p = version1; 26 | char *q = version2; 27 | while (*p || *q) { 28 | int d1 = 0; 29 | while (*p && isdigit(*p)) { 30 | d1 *= 10; 31 | d1 += (*p - '0'); 32 | p++; 33 | } 34 | int d2 = 0; 35 | while (*q && isdigit(*q)) { 36 | d2 *= 10; 37 | d2 += (*q - '0'); 38 | q++; 39 | } 40 | if (d1 > d2) 41 | return 1; 42 | if (d1 < d2) 43 | return -1; 44 | if (*p) 45 | p++; 46 | if (*q) 47 | q++; 48 | } 49 | return 0; 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /algorithms/CompareVersionNumbers/in.txt: -------------------------------------------------------------------------------- 1 | 1.1.1 1.1.2 2 | 1.2.2 1.1.1 3 | 1.1 2.1 4 | 1 1.2 5 | -------------------------------------------------------------------------------- /algorithms/CompareVersionNumbers/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | int compareVersion(char* version1, char* version2) { 6 | char *p = version1; 7 | char *q = version2; 8 | while (*p || *q) { 9 | int d1 = 0; 10 | while (*p && isdigit(*p)) { 11 | d1 *= 10; 12 | d1 += (*p - '0'); 13 | p++; 14 | } 15 | int d2 = 0; 16 | while (*q && isdigit(*q)) { 17 | d2 *= 10; 18 | d2 += (*q - '0'); 19 | q++; 20 | } 21 | if (d1 > d2) 22 | return 1; 23 | if (d1 < d2) 24 | return -1; 25 | if (*p) 26 | p++; 27 | if (*q) 28 | q++; 29 | } 30 | return 0; 31 | } 32 | int main(int argc, char **argv) 33 | { 34 | char s1[20],s2[20]; 35 | while (scanf("%s%s", s1, s2) != EOF) { 36 | switch (compareVersion(s1, s2)) { 37 | case 1: 38 | printf("%s > %s\n", s1, s2); 39 | break; 40 | case -1: 41 | printf("%s < %s\n", s1, s2); 42 | break; 43 | default: 44 | printf("%s == %s\n", s1, s2); 45 | } 46 | } 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /algorithms/ContainerWithMostWater/README.md: -------------------------------------------------------------------------------- 1 | ## Container With Most Water 2 | Given n non-negative integers a1, a2, ..., an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water. 3 | 4 | Note: You may not slant the container. 5 | 6 | ## Solution 7 | 8 | 首先需要知道这些问题: 9 | 10 | * 面积由长和宽, 宽度由x轴间隔决定,高度由短的直线决定 11 | * 当宽度减少时,面积要变大,高度必须变大 12 | * 可以使用控制变量法,先宽度从最大开始,即`i = 0, j = n - 1`, i向有移动 13 | j向左移动。每次求面积,获取最大值 14 | * 当i,j移动时,宽度必然减少,因此高度必须增大,因此高度减少的可以排除掉 15 | * 面积由短的决定,因此先移动短的。 16 | 17 | 有了上面思路,算法就出来了,设left,right分别指示左直线和右直线,初始化left =0, right = n - 1,当left <= right, 左移left,否则右移right。 18 | 19 | ## Code 20 | ```c 21 | int maxArea(int a[], int n) 22 | { 23 | int max = -1; 24 | int left = 0, right = n - 1; 25 | for (int i = 1; i < n; ++i) { 26 | int area = (a[left] <= a[right] ? a[left] : a[right]) * (right - left); 27 | max = max < area ? area : max; 28 | if (a[left] <= a[right]) { 29 | int l = a[left]; 30 | left++; 31 | while (left < right && a[left] <= l) { 32 | left++; 33 | } 34 | } else { 35 | int r = a[right]; 36 | right--; 37 | while (left < right && a[right] <= r) { 38 | right--; 39 | } 40 | } 41 | } 42 | return max; 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /algorithms/ContainerWithMostWater/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int maxArea(int a[], int n) 4 | { 5 | int max = -1; 6 | int left = 0, right = n - 1; 7 | for (int i = 1; i < n; ++i) { 8 | int area = (a[left] <= a[right] ? a[left] : a[right]) * (right - left); 9 | max = max < area ? area : max; 10 | if (a[left] <= a[right]) { 11 | int l = a[left]; 12 | left++; 13 | while (left < right && a[left] <= l) { 14 | left++; 15 | } 16 | } else { 17 | int r = a[right]; 18 | right--; 19 | while (left < right && a[right] <= r) { 20 | right--; 21 | } 22 | } 23 | } 24 | return max; 25 | } 26 | int main(int argc, char **argv) 27 | { 28 | int a[] = {2, 3, 4, 1}; 29 | int b[] = {1,2,1}; 30 | printf("%d\n", maxArea(a, 4)); 31 | printf("%d\n", maxArea(b, 3)); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /algorithms/ContainerWithMostWater/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int main(int argc, char **argv) 4 | { 5 | printf("%d\n", INT_MIN - 1); 6 | printf("%d\n", INT_MAX + 1); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /algorithms/ContainsDuplicate/README.md: -------------------------------------------------------------------------------- 1 | ## Contains Duplicate 2 | 3 | Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct. 4 | 5 | ## Solution 6 | 7 | 直接使用hashtable即可 8 | 9 | ```cpp 10 | bool containsDuplicate(vector &nums) { 11 | unordered_set set; 12 | for (int i : nums) { 13 | if (set.find(i) != set.end()) 14 | return true; 15 | else 16 | set.insert(i); 17 | } 18 | return false; 19 | } 20 | ``` 21 | 22 | ## 扩展 23 | 24 | * [Contains Duplicate](../ContainsDuplicate): 判断一个数组是否存在重复元素 25 | * [Contains Duplicate II](../ContainsDuplicateII):判断一个数组在指定距离内是否存在重复元素 26 | * [Contains Duplicate III](../ContainsDuplicateIII):判断一个数组在指定距离内是否存在元素距离小于t 27 | -------------------------------------------------------------------------------- /algorithms/ContainsDuplicate/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | bool containsDuplicate(vector &nums) { 9 | unordered_set set; 10 | for (int i : nums) { 11 | if (set.find(i) != set.end()) 12 | return true; 13 | else 14 | set.insert(i); 15 | } 16 | return false; 17 | } 18 | }; 19 | int main(int argc, char **argv) 20 | { 21 | Solution solution; 22 | vector nums = {2,3,4,1}; 23 | cout << solution.containsDuplicate(nums) << endl; 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /algorithms/ContainsDuplicateII/README.md: -------------------------------------------------------------------------------- 1 | ## Contains Duplicate II 2 | 3 | Given an array of integers and an integer k, find out whether there there are two distinct indices i and j in the array such that nums[i] = nums[j] and the difference between i and j is at most k. 4 | 5 | ## Solution 6 | 7 | 使用hashmap,key存储值,value存储索引, 若`nums[i]`在hashmap中,则若`i - map[nums[i]] <= k`, 返回true 8 | 9 | ```cpp 10 | bool containsNearbyDuplicate(vector &nums, int k) { 11 | unordered_map map; 12 | int n = nums.size(); 13 | for (int i = 0; i < n; ++i) { 14 | if (map.find(nums[i]) != map.end()) { 15 | int s = map[nums[i]]; 16 | if (i - s <= k) 17 | return true; 18 | } 19 | map[nums[i]] = i; 20 | } 21 | return false; 22 | } 23 | ``` 24 | 25 | ## 扩展 26 | 27 | * [Contains Duplicate](../ContainsDuplicate): 判断一个数组是否存在重复元素 28 | * [Contains Duplicate II](../ContainsDuplicateII):判断一个数组在指定距离内是否存在重复元素 29 | * [Contains Duplicate III](../ContainsDuplicateIII):判断一个数组在指定距离内是否存在元素距离小于t 30 | -------------------------------------------------------------------------------- /algorithms/ContainsDuplicateII/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | bool containsNearbyDuplicate(vector &nums, int k) { 9 | unordered_map map; 10 | int n = nums.size(); 11 | for (int i = 0; i < n; ++i) { 12 | if (map.find(nums[i]) != map.end()) { 13 | int s = map[nums[i]]; 14 | if (i - s <= k) 15 | return true; 16 | } 17 | map[nums[i]] = i; 18 | } 19 | return false; 20 | } 21 | }; 22 | int main(int argc, char **argv) 23 | { 24 | Solution solution; 25 | vector nums = {2,3,4,1}; 26 | cout << solution.containsNearbyDuplicate(nums, 1) << endl; 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /algorithms/CountPrimes/img/Sieve_of_Eratosthenes_animation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/int32bit/leetcode/4cf8d30509f4b994b1845765807380eeffb95c73/algorithms/CountPrimes/img/Sieve_of_Eratosthenes_animation.gif -------------------------------------------------------------------------------- /algorithms/CountPrimes/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | bool isPrime(int n) 6 | { 7 | //asssert(n > 0); 8 | if (n <= 3) 9 | return true; 10 | for (int i = 2; i <= sqrt(n); ++i) { 11 | if (n % i == 0) 12 | return false; 13 | } 14 | return true; 15 | } 16 | class Solution { 17 | public: 18 | int countPrimes(int n) { 19 | vector flags(n, true); 20 | flags[0] = false; 21 | flags[1] = false; 22 | int sqr = sqrt(n - 1); 23 | for (int i = 2; i <= sqr; ++i) { 24 | if (flags[i]) { 25 | for (int j = i * i; j < n; j += i) 26 | flags[j] = false; 27 | } 28 | } 29 | return count(flags.begin(), flags.end(), true); 30 | } 31 | }; 32 | int main(int argc, char **argv) 33 | { 34 | Solution solution; 35 | int n; 36 | while (scanf("%d", &n) != EOF) { 37 | printf("Pi(%d) = %d\n", n, solution.countPrimes(n)); 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /algorithms/CountandSay/itos.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | int main(int argc, char **argv) 8 | { 9 | /* Method 1 使用sprintf */ 10 | char buf[20]; 11 | sprintf(buf, "%d", 123); 12 | string s1(buf); 13 | cout << "s1 = " << s1 << endl; 14 | 15 | /* Method 2 使用stringstream */ 16 | stringstream ss; 17 | ss << 123; 18 | string s2 = ss.str(); 19 | s2.push_back('c'); 20 | cout << "s2 = " << s2 << endl; 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /algorithms/CountandSay/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | class Solution { 9 | public: 10 | string countAndSay(int n) { 11 | n--; 12 | string result = "1"; 13 | while (n--) { 14 | result = next(result); 15 | } 16 | return result; 17 | } 18 | private: 19 | string next(string s) { 20 | int n = s.size(); 21 | if (n < 1) 22 | return ""; 23 | char cur = s[0]; 24 | int count = 1; 25 | string result; 26 | for (int i = 1; i < n; ++i) { 27 | if (cur != s[i]) { 28 | result += itos(count); 29 | result.push_back(cur); 30 | cur = s[i]; 31 | count = 1; 32 | } else { 33 | ++count; 34 | } 35 | } 36 | result += itos(count); 37 | result += cur; 38 | return result; 39 | } 40 | string itos(int i) { 41 | ss.str(""); 42 | ss.clear(); 43 | ss << i; 44 | return ss.str(); 45 | } 46 | stringstream ss; 47 | }; 48 | int main(int argc, char **argv) 49 | { 50 | Solution solution; 51 | int n; 52 | while (scanf("%d", &n) != EOF) { 53 | cout << solution.countAndSay(n) << endl; 54 | } 55 | return 0; 56 | 57 | } 58 | -------------------------------------------------------------------------------- /algorithms/CountandSay/stoi.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | int main(int argc, char **argv) 8 | { 9 | /* 使用stoi */ 10 | string s1 = "123"; 11 | cout << stoi(s1) << endl; 12 | /* 使用sscanf */ 13 | int i; 14 | sscanf(s1.c_str(), "%d", &i); 15 | cout << i << endl; 16 | /* 使用stringstream */ 17 | stringstream ss; 18 | int j; 19 | ss << s1; 20 | ss >> j; 21 | cout << j << endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /algorithms/CountingBits/README.md: -------------------------------------------------------------------------------- 1 | ## Counting Bits 2 | 3 | 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. 4 | 5 | Example: 6 | For `num = 5` you should return `[0,1,1,2,1,2]`. 7 | 8 | Follow up: 9 | 10 | * 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? 11 | * Space complexity should be O(n). 12 | * Can you do it like a boss? Do it without using any builtin function like\_\_builtin\_popcount in c++ or in any other language. 13 | 14 | ## Solution 15 | 16 | 很容易实现O(n * sizeof(num))的方法: 17 | 18 | ```c 19 | int countBit(int n) 20 | { 21 | int sum = 0; 22 | while (n) { 23 | sum++; 24 | n &= (n - 1); 25 | } 26 | return sum; 27 | } 28 | int *countBits(int num, int *size) 29 | { 30 | *size = num + 1; 31 | int* ans = (int *)malloc(sizeof(int) * *size); 32 | for (int i = 0; i <= num; ++i) 33 | ans[i] = countBit(i); 34 | return ans; 35 | } 36 | ``` 37 | 38 | 但题目要求O(n),我们可以使用迭代的方法,我们知道左移位除了最后一个1可能丢掉,不会改变其余位的1的个数,假设f(n)表示n的二进制1的个数,则: 39 | 40 | * 若n为偶数,则f(n) = f(n >> 1). 41 | * 若n为奇数,则f(n) = f (n >> 1) + 1. 其中后面的1是由于移位丢掉的。 42 | 43 | ```c 44 | int *countBits(int num, int *size) 45 | { 46 | *size = num + 1; 47 | int* ans = (int *)malloc(sizeof(int) * *size); 48 | for (int i = 1; i <= num; ++i) 49 | ans[i] = ans[i >> 1] + (i & 1); 50 | return ans; 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /algorithms/CountingBits/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | class Solution { 4 | public: 5 | vector countBits(int num) { 6 | vector result(num + 1, 0); 7 | for (int i = 1; i <= num; ++i) 8 | result[i] = result[i >> 1] + (i & 1); 9 | return result; 10 | } 11 | }; 12 | int countBit(int n) 13 | { 14 | int sum = 0; 15 | while (n) { 16 | sum++; 17 | n &= (n - 1); 18 | } 19 | return sum; 20 | } 21 | int *countBits_bad(int num, int *size) 22 | { 23 | *size = num + 1; 24 | int* ans = (int *)malloc(sizeof(int) * *size); 25 | for (int i = 0; i <= num; ++i) 26 | ans[i] = countBit(i); 27 | return ans; 28 | } 29 | int *countBits(int num, int *size) 30 | { 31 | *size = num + 1; 32 | int* ans = (int *)malloc(sizeof(int) * *size); 33 | for (int i = 1; i <= num; ++i) 34 | ans[i] = ans[i >> 1] + (i & 1); 35 | return ans; 36 | } 37 | int main(int argc, char **argv) 38 | { 39 | int n; 40 | while (scanf("%d", &n) != EOF) { 41 | int size = 0; 42 | int *ans = countBits(n, &size); 43 | for (int i = 0; i < size; ++i) { 44 | printf("%d ", ans[i]); 45 | } 46 | printf("\n"); 47 | free(ans); 48 | } 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /algorithms/CourseSchedule/bfs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | class Solution { 9 | public: 10 | bool canFinish(int n, vector> &request) { 11 | //vector> g(n, vector(n, 0)); 12 | vector degree(n, 0); 13 | for (auto p : request) { 14 | //g[p.second][p.first] = 1; 15 | degree[p.first]++; 16 | } 17 | return topsort(request, degree); 18 | } 19 | private: 20 | /* BFS */ 21 | bool topsort(const vector> &request, vector °ree) { 22 | int n = degree.size(); 23 | vector visited(n, false); 24 | int sum = 0; 25 | while (sum < n) { // 还没有访问完 26 | int cur = findZero(degree); 27 | if (cur >= 0) { // 访问节点cur 28 | sum++; 29 | degree[cur] = -1; // 标记当前节点为已经访问状态 30 | for (auto p : request) { 31 | if (p.second == cur) 32 | degree[p.first]--; // 去掉已访问节点 33 | } 34 | } else 35 | return false; 36 | } 37 | return true; 38 | } 39 | int findZero(const vector &v) { 40 | int n = v.size(); 41 | for (int i = 0; i < n; ++i) { 42 | if (v[i] == 0) 43 | return i; 44 | } 45 | return -1; 46 | } 47 | 48 | }; 49 | int main(int argc, char **argv) 50 | { 51 | Solution solution; 52 | vector> request = {make_pair(1, 0), make_pair(2, 1), make_pair(3, 1)}; 53 | cout << solution.canFinish(4, request) << endl; 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /algorithms/CourseSchedule/dfs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | class Solution { 9 | public: 10 | bool canFinish(int n, vector> &request) { 11 | vector visited(n, 0); 12 | for (int i = 0; i < n; ++i) 13 | if (!dfs(request, visited, i)) 14 | return false; 15 | return true; 16 | } 17 | private: 18 | bool dfs(const vector> &request, vector &visited, int i) { 19 | if (visited[i] == -1) 20 | return false; 21 | if (visited[i] == 1) 22 | return true; 23 | visited[i] = -1; // -1 表示正在访问 24 | for (auto p : request) { 25 | if (p.second == i) { 26 | if (!dfs(request, visited, p.first)) 27 | return false; 28 | } 29 | } 30 | visited[i] = 1; 31 | return true; 32 | } 33 | }; 34 | int main(int argc, char **argv) 35 | { 36 | Solution solution; 37 | vector> request = {make_pair(1, 0), make_pair(2, 1), make_pair(0, 2)}; 38 | cout << solution.canFinish(3, request) << endl; 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /algorithms/CourseScheduleII/bfs.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | class Solution { 9 | public: 10 | vector findOrder(int n, vector> &request) { 11 | return topsort(n, request); 12 | } 13 | private: 14 | /* BFS */ 15 | vector topsort(int n, const vector> &request) { 16 | vector result; 17 | vector degree(n, 0); 18 | for (auto p : request) { 19 | degree[p.first]++; 20 | } 21 | while (result.size() < n) { // 还没有访问完 22 | int cur = findZero(degree); 23 | if (cur >= 0) { // 访问节点cur 24 | result.push_back(cur); 25 | degree[cur] = -1; // 标记当前节点为已经访问状态 26 | for (auto p : request) { 27 | if (p.second == cur) 28 | degree[p.first]--; // 去掉已访问节点 29 | } 30 | } else 31 | return vector(); 32 | } 33 | return result; 34 | } 35 | int findZero(const vector &v) { 36 | int n = v.size(); 37 | for (int i = 0; i < n; ++i) { 38 | if (v[i] == 0) 39 | return i; 40 | } 41 | return -1; 42 | } 43 | 44 | }; 45 | void print(vector v) { 46 | for_each(begin(v), end(v), [](int i){cout << i << ' ';}); 47 | cout << endl; 48 | } 49 | int main(int argc, char **argv) 50 | { 51 | Solution solution; 52 | vector> request = {make_pair(1, 0), make_pair(2, 0), make_pair(3, 1), make_pair(3, 2)}; 53 | print(solution.findOrder(4, request)); 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /algorithms/DecodeWays/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | static inline int isValid(char a, char b) 6 | { 7 | if (a == '1' || (a == '2' && b < '7')) 8 | return 1; 9 | return 0; 10 | } 11 | int numDecodings(char* s) 12 | { 13 | int n; 14 | if (s == NULL || (n = strlen(s)) < 1) 15 | return 0; 16 | int sum = 0; 17 | if (s[0] != '0' && s[1] != '0') 18 | sum = 1; 19 | for (int i = 1; i < n; ++i) { 20 | if (s[i] != '0' && s[i + 1] != '0') 21 | sum++; 22 | sum += isValid(s[i - 1], s[i]); 23 | } 24 | return sum; 25 | } 26 | int main(int argc, char **argv) 27 | { 28 | char buf[20]; 29 | while (scanf("%s", buf) != EOF) 30 | printf("%d\n", numDecodings(buf)); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /algorithms/DeleteNodeinaLinkedList/README.md: -------------------------------------------------------------------------------- 1 | ## Delete Node in a Linked List 2 | 3 | Write a function to delete a node (except the tail) in a singly linked list, given only access to that node. 4 | 5 | Supposed the linked list is `1 -> 2 -> 3 -> 4` and you are given the third node with value `3`, the linked list should become `1 -> 2 -> 4` after calling your function. 6 | 7 | ## Solution 8 | 9 | 给定一个单链表节点,删除该节点。 10 | 11 | 由于无法获得该节点的前驱节点,因此无法更新前驱节点的后继节点。我们可以把该节点的下一个节点的值拷贝到当前节点,转而删除该节点的下一个节点。 12 | 13 | 该题目也可以描述为: 如何在O(1)的时间删除单链表的某个节点! 14 | 15 | ```cpp 16 | void deleteNode(ListNode *node) { 17 | ListNode *p = node->next; 18 | node->val = p->val; 19 | node->next = p->next; 20 | delete p; 21 | } 22 | ``` 23 | -------------------------------------------------------------------------------- /algorithms/DivideTwoIntegers/in.txt: -------------------------------------------------------------------------------- 1 | 2147483647 1 2 | 2147483647 -1 3 | -1010369383 -2147483648 4 | -2147483648 -1 5 | -2147483648 1 6 | 1 -2147483648 7 | -------------------------------------------------------------------------------- /algorithms/DivideTwoIntegers/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int getSign(long a, long b) 7 | { 8 | if ((a < 0 && b > 0) || (a > 0 && b < 0)) 9 | return 1; 10 | return 0; 11 | } 12 | long labs(long a) 13 | { 14 | return a >= 0 ? a : -a; 15 | } 16 | int divide(int dividend, int divisor) 17 | { 18 | if (divisor == 0) { // 除数为0 19 | return dividend >= 0 ? INT_MAX : INT_MIN; 20 | } 21 | long n = dividend; // 防止溢出,当其中一个=INT_MIN 22 | long m = divisor; 23 | int sign = getSign(n, m); // 保存结果的符号 24 | n = labs(n); 25 | m = labs(m); 26 | long ans = 0; 27 | long a; // 防止 a << 1溢出 28 | long k; 29 | while (n >= m) { 30 | a = m, k = 1; 31 | while (n > (a << 1)) { 32 | a <<= 1; 33 | k <<= 1; 34 | } 35 | n -= a; 36 | ans += k; 37 | } 38 | ans = sign ? -ans : ans; 39 | if (ans > INT_MAX) 40 | return INT_MAX; 41 | if (ans < INT_MIN) 42 | return INT_MIN; 43 | return ans; 44 | } 45 | int main(int argc, char **argv) 46 | { 47 | int a,b; 48 | while (scanf("%d%d", &a, &b) != EOF) 49 | printf("%d\n", divide(a, b)); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /algorithms/EditDistance/in.txt: -------------------------------------------------------------------------------- 1 | aaa aaa 2 | bab aaa 3 | abcd defg 4 | cccccccccccccc c 5 | c cccccccccccccccc 6 | -------------------------------------------------------------------------------- /algorithms/EditDistance/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | static inline int min2(int a, int b) 5 | { 6 | return a < b ? a : b; 7 | } 8 | static inline int min3(int a, int b, int c) 9 | { 10 | return min2(min2(a, b), c); 11 | } 12 | int minDistance(char *w1, char *w2) 13 | { 14 | if (w1 == NULL || *w1 == 0) { 15 | if (w2 == NULL || *w2 == 0) 16 | return 0; 17 | else 18 | return strlen(w2); 19 | } 20 | if (w2 == NULL || *w2 == 0) 21 | return strlen(w1); 22 | const int len1 = strlen(w1); 23 | const int len2 = strlen(w2); 24 | int dp[len1 + 1][len2 + 1]; 25 | dp[0][0] = 0; 26 | for (int i = 1; i <= len1; ++i) 27 | dp[i][0] = i; 28 | for (int j = 1; j <= len2; ++j) 29 | dp[0][j] = j; 30 | for (int i = 1; i <= len1; ++i) { 31 | for (int j = 1; j <= len2; ++j) { 32 | int case1 = dp[i - 1][j] + 1; // 删除当前字符 33 | int case2 = dp[i][j - 1] + 1; 34 | int case3 = dp[i - 1][j - 1] + (w1[i - 1] == w2[j - 1] ? 0 : 1); 35 | dp[i][j] = min3(case1, case2, case3); 36 | } 37 | } 38 | return dp[len1][len2]; 39 | } 40 | int main(int argc, char **argv) 41 | { 42 | char s1[20], s2[20]; 43 | while (scanf("%s%s", s1, s2) != EOF) { 44 | printf("|%s, %s| = %d\n",s1, s2, minDistance(s1, s2)); 45 | } 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /algorithms/EvaluateReversePolishNotation/README.md: -------------------------------------------------------------------------------- 1 | ## Evaluate Reverse Polish Notation 2 | 3 | Evaluate the value of an arithmetic expression in Reverse Polish Notation. 4 | 5 | Valid operators are` +, -, *, /`. Each operand may be an integer or another expression. 6 | 7 | Some examples: 8 | ``` 9 | ["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9 10 | ["4", "13", "5", "/", "+"] -> (4 + (13 / 5)) -> 6 11 | ``` 12 | 13 | ## Solution 14 | 15 | 使用栈保存数字: 16 | 17 | * 当遇到新的数字时,压入栈 18 | * 当遇到操作符时,从栈中弹出两个数,先后弹出的数分别为第二操作数、第一操作数. 19 | * 计算两个操作数和对应运算符进行运算的值,压入栈 20 | 21 | ## Code 22 | ```java 23 | public int evalRPN(List tokens) { 24 | LinkedList repo = new LinkedList(); 25 | for (String token : tokens) { 26 | if (isOperator(token)) { 27 | String num1 = repo.pop(); 28 | String num2 = repo.pop(); 29 | int result = expr(num2, num1, token); 30 | repo.push(String.valueOf(result)); 31 | } else { 32 | repo.push(token); 33 | } 34 | } 35 | return Integer.parseInt(repo.pop()); 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /algorithms/EvaluateReversePolishNotation/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | public class Solution { 3 | public int evalRPN(List tokens) { 4 | LinkedList repo = new LinkedList(); 5 | for (String token : tokens) { 6 | if (isOperator(token)) { 7 | String num1 = repo.pop(); 8 | String num2 = repo.pop(); 9 | int result = expr(num2, num1, token); 10 | repo.push(String.valueOf(result)); 11 | } else { 12 | repo.push(token); 13 | } 14 | } 15 | return Integer.parseInt(repo.pop()); 16 | } 17 | private boolean isOperator(String s) { 18 | return s.equals("+") 19 | || s.equals("-") 20 | || s.equals("*") 21 | || s.equals("/"); 22 | } 23 | private int expr(String num1, String num2, String op) { 24 | int a = Integer.parseInt(num1); 25 | int b = Integer.parseInt(num2); 26 | switch (op) { 27 | case "+": 28 | return a + b; 29 | case "-": 30 | return a - b; 31 | case "*": 32 | return a * b; 33 | case "/": 34 | return a / b; 35 | default: 36 | throw new IllegalArgumentException(); 37 | } 38 | } 39 | public static void main(String[] args) { 40 | List s1 = Arrays.asList("2", "1", "+", "3", "*"); 41 | List s2 = Arrays.asList("4", "13", "5", "/", "+"); 42 | Solution solution = new Solution(); 43 | System.out.println(solution.evalRPN(s1)); 44 | System.out.println(solution.evalRPN(s2)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /algorithms/ExcelSheetColumnNumber/README.md: -------------------------------------------------------------------------------- 1 | ## Excel Sheet Column Number 2 | Related to question Excel Sheet Column Title 3 | 4 | Given a column title as appear in an Excel sheet, return its corresponding column number. 5 | 6 | For example: 7 | ``` 8 | A -> 1 9 | B -> 2 10 | C -> 3 11 | ... 12 | Z -> 26 13 | AA -> 27 14 | AB -> 28 15 | ``` 16 | Credits: 17 | Special thanks to @ts for adding this problem and creating all test cases. 18 | 19 | ## Solution 20 | 21 | 进制转化,比如2进制转化成10进制 22 | 23 | ## Code 24 | ```c 25 | int titleToNumber(char* s) 26 | { 27 | if (s == NULL) 28 | return 0; 29 | int result = 0; 30 | while (*s) { 31 | result *= 26; 32 | result += *s - 'A' + 1; 33 | s++; 34 | } 35 | return result; 36 | } 37 | ``` 38 | 39 | ## 扩展 40 | 41 | 逆过程[Excel Sheet Column Title](../ExcelSheetColumnTitle) 42 | -------------------------------------------------------------------------------- /algorithms/ExcelSheetColumnNumber/in.txt: -------------------------------------------------------------------------------- 1 | A 2 | B 3 | C 4 | Z 5 | AA 6 | AB 7 | -------------------------------------------------------------------------------- /algorithms/ExcelSheetColumnNumber/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int titleToNumber(char* s) 5 | { 6 | if (s == NULL) 7 | return 0; 8 | int result = 0; 9 | while (*s) { 10 | result *= 26; 11 | result += *s - 'A' + 1; 12 | s++; 13 | } 14 | return result; 15 | } 16 | int main(int argc, char **argv) 17 | { 18 | char buf[15]; 19 | while (scanf("%s", buf) != EOF) { 20 | printf("%s -> %d\n", buf, titleToNumber(buf)); 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /algorithms/ExcelSheetColumnTitle/README.md: -------------------------------------------------------------------------------- 1 | ## Excel Sheet Column Title 2 | 3 | Given a positive integer, return its corresponding column title as appear in an Excel sheet. 4 | 5 | ## Solution 6 | 7 | 进制转化,其实质就是把数字转成26进制 8 | 9 | 由于`1->A`, `2->B`, `26->Z`,即所以需要把n-1在操作 10 | 11 | ## Code 12 | ```cpp 13 | string convertToTitle(int n) { 14 | string result; 15 | while (n) { 16 | result.push_back(--n % 26 + 'A'); 17 | n /= 26; 18 | } 19 | return string(result.rbegin(), result.rend()); 20 | } 21 | ``` 22 | ## 扩展 23 | 24 | 逆过程[Excel Sheet Column Number](../ExcelSheetColumnNumber) 25 | -------------------------------------------------------------------------------- /algorithms/ExcelSheetColumnTitle/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | string convertToTitle(int n) { 9 | string result; 10 | while (n) { 11 | result.push_back(--n % 26 + 'A'); 12 | n /= 26; 13 | } 14 | return string(result.rbegin(), result.rend()); 15 | } 16 | }; 17 | int main(int argc, char **argv) 18 | { 19 | int n; 20 | Solution solution; 21 | while (scanf("%d", &n) != EOF) { 22 | cout << solution.convertToTitle(n) << endl; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /algorithms/FactorialTrailingZeroes/README.md: -------------------------------------------------------------------------------- 1 | ## Factorial Trailing Zeroes 2 | 3 | Given an integer n, return the number of trailing zeroes in n!. 4 | 5 | Note: Your solution should be in logarithmic time complexity. 6 | 7 | Credits: 8 | 9 | Special thanks to @ts for adding this problem and creating all test cases. 10 | 11 | ## Solution 12 | 13 | 自然数相乘(0 除外), 只有当因子2 和 5相乘时才会有结尾0产生,比如`20 * 5 = 2 * 5 * 2 * 5`, 有两个`2 * 5`, 因此末尾有两个0. 14 | 15 | 阶乘计算时,自然数连续相乘,只需要统计有多少`2 * 5`,即可求出多少个末尾0, 而2的个数大于5的个数,因此最后只决定于有多少个`5`. 16 | 17 | 比如`10! = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 = 2^8 * 3^4 * 5^2`,由于5的因子数为2,因此`10!`末尾有2个0 18 | 19 | 我们知道5,10,15,20产生一个5因子,即每间隔5产生一个5因子,而25产生2个5因子,即每个25又会多一个5因子,因此`25!`共可产生6个5因子。 20 | 21 | 因此要计算阶乘N的5的因子个数,先统计每隔5产生因子,其值等于`N / 5`, 接下来计算每隔25产生的因子,个数应该为`N / 25`, 而由于前面已经除了5,因此 22 | 只需要`N / 5`即可. 依次类推,直到没有5因子产生.:w 23 | 24 | ## Code 25 | ```c 26 | int trailingZeroes(int n) 27 | { 28 | if (n < 0) 29 | return 0; 30 | int sum = 0; 31 | while (n) { 32 | sum += n / 5; 33 | n /= 5; 34 | } 35 | return sum; 36 | } 37 | ``` 38 | -------------------------------------------------------------------------------- /algorithms/FactorialTrailingZeroes/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int trailingZeroes(int n) 5 | { 6 | if (n < 0) 7 | return 0; 8 | int sum = 0; 9 | while (n) { 10 | sum += n / 5; 11 | n /= 5; 12 | } 13 | return sum; 14 | } 15 | int main(int argc, char **argv) 16 | { 17 | int n; 18 | while (scanf("%d", &n) != EOF) 19 | printf("%d\n", trailingZeroes(n)); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /algorithms/FindMinimuminRotatedSortedArray/README.md: -------------------------------------------------------------------------------- 1 | ## Find Minimum in Rotated Sorted Array 2 | 3 | Suppose a sorted array is rotated at some pivot unknown to you beforehand. 4 | 5 | (i.e., `0 1 2 4 5 6 7` might become `4 5 6 7 0 1 2`). 6 | 7 | Find the minimum element. 8 | 9 | You may assume no duplicate exists in the array. 10 | 11 | ## Solution 12 | 13 | 使用二分搜索,设当前搜索范围为`[left, right]`, 则中间的值为`mid = (left + right) /2`, 则 14 | 15 | * 若`a[left] < a[right]`, 说明没有旋转,返回`a[left]`. 16 | * 若`a[mid] > a[right]`, 则结果在右边, `left = mid + 1` 17 | * 若`a[mid] < a[right]`, 则结果在左边, `right = mid` 18 | 19 | 关键注意边界为题, 什么时候用`>=`什么时候用`>`, 以及什么时候用`mid`, 什么时候用`mid + 1` 20 | 21 | ## Code 22 | ```cpp 23 | int findMin(vector &nums) { 24 | int n = nums.size(); 25 | if (n == 0) 26 | return INT_MIN; 27 | int s = 0, t = n - 1; 28 | while (s < t) { 29 | if (nums[s] < nums[t]) 30 | return nums[s]; 31 | int mid = (s + t) >> 1; 32 | if (nums[mid] > nums[t]) 33 | s = mid + 1; 34 | else 35 | t = mid; 36 | } 37 | return nums[s]; 38 | } 39 | ``` 40 | 41 | ## 扩展 42 | 43 | 1. 当有重复元素存在时,见[Find Minimum in Rotated Sorted Array II](../FindMinimuminRotatedSortedArray2) 44 | 45 | 2. [Search in Rotated Sorted Array](../SearchinRotatedSortedArray), 在旋转列表中查找某个数 46 | -------------------------------------------------------------------------------- /algorithms/FindMinimuminRotatedSortedArray/in.txt: -------------------------------------------------------------------------------- 1 | 7 2 | 1 2 3 4 5 6 7 3 | 7 4 | 7 1 2 3 4 5 6 5 | 7 6 | 6 7 1 2 3 4 5 7 | 7 8 | 5 6 7 1 2 3 4 9 | 7 10 | 4 5 6 7 1 2 3 11 | 7 12 | 3 4 5 6 7 1 2 13 | 7 14 | 2 3 4 5 6 7 1 15 | -------------------------------------------------------------------------------- /algorithms/FindMinimuminRotatedSortedArray/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | int findMin(vector &nums) { 9 | int n = nums.size(); 10 | if (n == 0) 11 | return INT_MIN; 12 | int s = 0, t = n - 1; 13 | while (s < t) { 14 | if (nums[s] < nums[t]) 15 | return nums[s]; 16 | int mid = (s + t) >> 1; 17 | if (nums[mid] > nums[t]) 18 | s = mid + 1; 19 | else 20 | t = mid; 21 | } 22 | return nums[s]; 23 | } 24 | }; 25 | int main(int argc, char **argv) 26 | { 27 | int a[20]; 28 | int n; 29 | Solution solution; 30 | while(scanf("%d", &n) != EOF) { 31 | for (int i = 0; i < n; ++i) { 32 | scanf("%d", a + i); 33 | } 34 | vector v(a, a + n); 35 | printf("%d\n", solution.findMin(v)); 36 | } 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /algorithms/FindMinimuminRotatedSortedArray2/README.md: -------------------------------------------------------------------------------- 1 | ## Find Minimum in Rotated Sorted Array II 2 | 3 | > Follow up for "Find Minimum in Rotated Sorted Array": 4 | > What if duplicates are allowed? 5 | 6 | > Would this affect the run-time complexity? How and why? 7 | 8 | Suppose a sorted array is rotated at some pivot unknown to you beforehand. 9 | 10 | (i.e., `0 1 2 4 5 6 7` might become `4 5 6 7 0 1 2`). 11 | 12 | Find the minimum element. 13 | 14 | The array may contain duplicates. 15 | 16 | ## Solution 17 | 18 | 和[Find Minimum in Rotated Sorted Array I](../FindMinimuminRotatedSortedArray) 类似,不过需要考虑`a[mid] == a[right]`的情况, 19 | 20 | 此时只需要把`right--`即可 21 | 22 | ## Code 23 | ```cpp 24 | int findMin(vector &nums) { 25 | int n = nums.size(); 26 | if (n == 0) 27 | return INT_MIN; 28 | int s = 0, t = n - 1; 29 | while (s < t) { 30 | if (nums[s] < nums[t]) 31 | return nums[s]; 32 | int mid = (s + t) >> 1; 33 | if (nums[mid] > nums[t]) { 34 | s = mid + 1; 35 | } else if (nums[mid] < nums[t]) { 36 | t = mid; 37 | } else { 38 | t--; 39 | } 40 | } 41 | return nums[s]; 42 | } 43 | ``` 44 | 45 | ## 扩展 46 | 47 | [Search in Rotated Sorted Array](../SearchinRotatedSortedArray), 从旋转列表中查找某个值 48 | 49 | [Find Minimum in Rotated Sorted Array](../FindMinimuminRotatedSortedArray) 50 | -------------------------------------------------------------------------------- /algorithms/FindMinimuminRotatedSortedArray2/in.txt: -------------------------------------------------------------------------------- 1 | 5 2 | 2 1 2 2 2 3 | 5 4 | 2 2 1 2 2 5 | 5 6 | 2 2 2 1 2 7 | 5 8 | 2 2 2 2 1 9 | 5 10 | 1 2 2 2 2 11 | -------------------------------------------------------------------------------- /algorithms/FindMinimuminRotatedSortedArray2/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | int findMin(vector &nums) { 9 | int n = nums.size(); 10 | if (n == 0) 11 | return INT_MIN; 12 | int s = 0, t = n - 1; 13 | while (s < t) { 14 | if (nums[s] < nums[t]) 15 | return nums[s]; 16 | int mid = (s + t) >> 1; 17 | if (nums[mid] > nums[t]) { 18 | s = mid + 1; 19 | } else if (nums[mid] < nums[t]) { 20 | t = mid; 21 | } else { 22 | t--; 23 | } 24 | } 25 | return nums[s]; 26 | } 27 | }; 28 | int main(int argc, char **argv) 29 | { 30 | int a[20]; 31 | int n; 32 | Solution solution; 33 | while(scanf("%d", &n) != EOF) { 34 | for (int i = 0; i < n; ++i) { 35 | scanf("%d", a + i); 36 | } 37 | vector v(a, a + n); 38 | printf("%d\n", solution.findMin(v)); 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /algorithms/FindPeakElement/in.txt: -------------------------------------------------------------------------------- 1 | 7 2 | 4 5 3 6 7 8 9 3 | -------------------------------------------------------------------------------- /algorithms/FindPeakElement/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | int findPeakElement(vector &a) { 9 | return fastFindPeakElement(a); 10 | } 11 | private: 12 | int slowFindPeakElement(vector &a) { 13 | int n = a.size(); 14 | if (n < 2 || a[0] > a[1]) 15 | return 0; 16 | if (a[n - 1] > a[n - 2]) 17 | return n - 1; 18 | for (int i = 1; i < n - 1; ++i) 19 | if (a[i] > a[i - 1] && a[i] > a[i + 1]) 20 | return i; 21 | } 22 | int midFindPeakElement(vector &a) { 23 | int n = a.size(); 24 | for (int i = 0; i < n - 1; ++i) 25 | if (a[i] > a[i + 1]) 26 | return i; 27 | return n - 1; 28 | } 29 | int fastFindPeakElement(vector &a) { 30 | int n = a.size(); 31 | int left = 0, right = n - 1; 32 | while (left < right) { 33 | int mid = (left + right) >> 1; 34 | printf("left = %d, mid = %d, right = %d\n", left, mid, right); 35 | if (a[mid] > a[mid - 1] && a[mid] > a[mid + 1]) 36 | return mid; 37 | if (a[mid] > a[mid + 1]) 38 | right = mid; 39 | else 40 | left = mid + 1; 41 | } 42 | return left; 43 | } 44 | }; 45 | int main(int argc, char **argv) 46 | { 47 | Solution solution; 48 | int a[20], n; 49 | while (scanf("%d", &n) != EOF) { 50 | for (int i = 0; i < n; ++i) 51 | scanf("%d", a + i); 52 | vector v(a, a + n); 53 | cout << solution.findPeakElement(v) << endl; 54 | } 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /algorithms/GenerateParentheses/README.md: -------------------------------------------------------------------------------- 1 | Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. 2 | 3 | For example, given n = 3, a solution set is: 4 | ``` 5 | ((())) 6 | (()()) 7 | (())() 8 | ()(()) 9 | ()()() 10 | ``` 11 | 12 | ## Solution 13 | 14 | 搜索题。使用递归实现。 15 | 16 | 设括号对为N, 已生成的字符串左括号个数为open, 还能匹配左括号个数为`n = N - open`,已生成的字符串为x。定义 17 | `generate(vector &result, string x, int open, int n)`, 则 18 | 19 | * 若`n == 0`, 说明所有的左括号用完了,把剩下的右括号追加到x中, 并把x追加到result中 20 | * 若`open == 0`, 此时由于前面没有左括号,因此不能匹配右括号,只能增加左括号, 即`generate(result, x + '(', 1, n - 1)` 21 | * 若`open > 0`,此时既可以匹配左括号又可以匹配右括号: 22 | + 匹配左括号: `generate(result, x + '(', open + 1, n - 1)` 23 | + 匹配右括号: `generate(result, x + ')', open, n)` 24 | 25 | ## Code 26 | ```cpp 27 | class Solution { 28 | public: 29 | vector generateParenthesis(int n) { 30 | vector result; 31 | if (n < 1) 32 | return result; 33 | generate(result, "", 0, n); 34 | return result; 35 | } 36 | void generate(vector &result, string value, int open, int n) { 37 | if (n == 0) { 38 | for (int i = 0; i < open; ++i) 39 | value += ')'; 40 | result.push_back(value); 41 | return; 42 | } 43 | if (open == 0) { 44 | generate(result, value + '(', 1, n - 1); 45 | } else { 46 | generate(result, value + ')', open - 1, n); 47 | generate(result, value + '(', open + 1, n - 1); 48 | } 49 | } 50 | }; 51 | ``` 52 | -------------------------------------------------------------------------------- /algorithms/GenerateParentheses/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | vector generateParenthesis(int n) { 9 | vector result; 10 | if (n < 1) 11 | return result; 12 | generate(result, "", 0, n); 13 | return result; 14 | } 15 | void generate(vector &result, string value, int open, int n) { 16 | if (n == 0) { 17 | for (int i = 0; i < open; ++i) 18 | value += ')'; 19 | result.push_back(value); 20 | return; 21 | } 22 | if (open == 0) { 23 | generate(result, value + '(', 1, n - 1); 24 | } else { 25 | generate(result, value + ')', open - 1, n); 26 | generate(result, value + '(', open + 1, n - 1); 27 | } 28 | } 29 | }; 30 | int main(int argc, char **argv) 31 | { 32 | Solution solution; 33 | auto result = solution.generateParenthesis(10); 34 | for_each(result.begin(), result.end(), [](string s){cout << s << endl;}); 35 | } 36 | -------------------------------------------------------------------------------- /algorithms/GrayCode/TLE_solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | class Solution { 9 | public: 10 | vector grayCode(int n) { 11 | vector result; 12 | vector cur; 13 | int N = 1; 14 | for (int i = 0; i < n; ++i) 15 | N <<= 1; 16 | dfs(result, cur, n, 0, N); 17 | return result; 18 | } 19 | private: 20 | void dfs(vector &result, vector cur, int n, int x, int N) { 21 | cur.push_back(x); 22 | if (N == 1) { 23 | result = vector(begin(cur), end(cur)); 24 | return; 25 | } 26 | vector next = getPossibleNext(n, x); 27 | for (auto i : next) { 28 | if (find(begin(cur), end(cur), i) == end(cur)) { 29 | dfs(result, cur, n, i, N - 1); 30 | } 31 | } 32 | } 33 | vector getPossibleNext(int n, int x) { 34 | int base = 0x1; 35 | vector result; 36 | for (int i = 0; i < n; ++i) { 37 | result.push_back(base ^ x); 38 | base <<= 1; 39 | } 40 | return result; 41 | } 42 | }; 43 | void print(vector v) 44 | { 45 | cout << "["; 46 | for_each(begin(v), end(v), [](int i){cout << i << ' ';}); 47 | cout << "]"; 48 | cout << endl; 49 | } 50 | int main(int argc, char **argv) 51 | { 52 | Solution solution; 53 | int n; 54 | while (cin >> n) { 55 | print(solution.grayCode(n)); 56 | } 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /algorithms/GrayCode/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | class Solution { 9 | public: 10 | vector grayCode(int n) { 11 | return grayCode2(n); 12 | } 13 | private: 14 | vector grayCode1(int n) { 15 | vector result; 16 | for (int i = 0; i < (1 << n); ++i) { 17 | result.push_back(i ^ (i >> 1)); 18 | } 19 | return result; 20 | } 21 | vector grayCode2(int n) { 22 | vector result; 23 | result.push_back(0); 24 | for (int i = 0; i < n; ++i) { 25 | int high = 1 << i; 26 | for (int j = result.size() - 1; j >= 0; --j) 27 | result.push_back(result[j] + high); 28 | } 29 | return result; 30 | } 31 | }; 32 | void print(vector v) 33 | { 34 | cout << "["; 35 | for_each(begin(v), end(v), [](int i){cout << i << ' ';}); 36 | cout << "]"; 37 | cout << endl; 38 | } 39 | int main(int argc, char **argv) 40 | { 41 | Solution solution; 42 | int n; 43 | while (cin >> n) { 44 | print(solution.grayCode(n)); 45 | } 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /algorithms/HappyNumber/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | bool isHappy(int n) { 9 | return isHappy1(n); 10 | } 11 | private: 12 | bool isHappy1(int n) { 13 | unordered_set s; 14 | if (n == 0) 15 | return false; 16 | while (n != 1) { 17 | s.insert(n); 18 | n = next(n); 19 | if (s.find(n) != s.end()) { 20 | return false; 21 | } 22 | } 23 | return true; 24 | } 25 | bool isHappy2(int n) { 26 | int slow = next(n); 27 | int fast = next(next(n)); 28 | while (slow != 1 && slow != fast) { 29 | slow = next(slow); 30 | fast = next(next(fast)); 31 | } 32 | return slow == 1; 33 | } 34 | int next(int n) { 35 | int ans = 0; 36 | while (n) { 37 | int mod = (n % 10); 38 | ans += (mod * mod); 39 | n /= 10; 40 | } 41 | return ans; 42 | } 43 | }; 44 | int main(int argc, char **argv) 45 | { 46 | Solution solution; 47 | int n; 48 | while (scanf("%d", &n) != EOF) { 49 | printf("%d : %d\n", n, solution.isHappy(n)); 50 | } 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /algorithms/HouseRobber/src.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | int max(int a, int b) 4 | { 5 | return a >= b ? a : b; 6 | } 7 | int rob(int num[], int n) { 8 | int df[2]; 9 | int i, result = -1; 10 | if (n == 1) 11 | return num[0]; 12 | df[0] = num[0]; 13 | df[1] = max(df[0], num[1]); 14 | result = max(df[0], df[1]); 15 | for (i = 2; i < n; ++i) { 16 | df[i % 2] = max(df[(i - 2) % 2] + num[i], df[(i - 1) % 2]); 17 | result = max(result, df[i % 2]); 18 | } 19 | return result; 20 | } 21 | int main(int argc, char **argv) 22 | { 23 | int num[] = {2, 1, 1, 2}; 24 | printf("%d\n", rob(num, 4)); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /algorithms/HouseRobberII/in.txt: -------------------------------------------------------------------------------- 1 | 3 2 | 1 2 3 3 | 4 4 | 1 2 3 4 5 | 3 6 | 1 8 3 7 | 1 8 | 1 9 | 3 10 | 3 2 1 11 | 4 12 | 4 3 2 1 13 | -------------------------------------------------------------------------------- /algorithms/HouseRobberII/src.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | static inline int max(int a, int b) 4 | { 5 | return a >= b ? a : b; 6 | } 7 | static inline int min(int a, int b) 8 | { 9 | return a <= b ? a : b; 10 | } 11 | int get(int i) 12 | { 13 | return i & 0x1; 14 | } 15 | int robWithoutCircle(int num[], int n) { 16 | int df[2]; 17 | int i, result = -1; 18 | if (n <= 0) 19 | return 0; 20 | if (n == 1) 21 | return num[0]; 22 | df[0] = num[0]; 23 | df[1] = max(df[0], num[1]); 24 | result = max(df[0], df[1]); 25 | for (i = 2; i < n; ++i) { 26 | df[get(i)] = max(df[get(i - 2)] + num[i], df[get(i - 1)]); 27 | result = max(result, df[get(i)]); 28 | } 29 | return result; 30 | } 31 | int rob(int *nums, int n) 32 | { 33 | if (nums == NULL || n <= 0) 34 | return 0; 35 | if (n == 1) 36 | return nums[0]; 37 | return max(robWithoutCircle(nums, n - 1), robWithoutCircle(nums + 1, n - 1)); 38 | } 39 | void print(int *a, int n) 40 | { 41 | for (int i = 0; i < n; ++i) 42 | printf("%d ", a[i]); 43 | printf("\n"); 44 | } 45 | int main(int argc, char **argv) 46 | { 47 | int a[20], n; 48 | while (scanf("%d", &n) != EOF) { 49 | for (int i = 0; i < n; ++i) 50 | scanf("%d", &a[i]); 51 | print(a, n); 52 | printf("result = %d\n", rob(a, n)); 53 | } 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /algorithms/ImplementQueueusingStacks/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | class Queue { 5 | private: 6 | stack first; 7 | stack second; 8 | public: 9 | bool empty(void) { 10 | return first.empty() && second.empty(); 11 | } 12 | void push(int x) { 13 | first.push(x); 14 | } 15 | int peek(void) { 16 | if (second.empty()) { 17 | channel(first, second); 18 | } 19 | return second.top(); 20 | } 21 | void pop(void) { 22 | if (second.empty()) { 23 | channel(first, second); 24 | } 25 | second.pop(); 26 | } 27 | private: 28 | void channel(stack &src, stack &dest) { 29 | while (!src.empty()) { 30 | dest.push(src.top()); 31 | src.pop(); 32 | } 33 | } 34 | }; 35 | int main(int argc, char **argv) 36 | { 37 | Queue queue; 38 | queue.push(1); 39 | queue.push(2); 40 | queue.pop(); 41 | cout << queue.peek() << endl; 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /algorithms/ImplementstrStr/README.md: -------------------------------------------------------------------------------- 1 | ## Implement strStr() 2 | 3 | Implement strStr(). 4 | 5 | Returns the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. 6 | 7 | Update (2014-11-02): 8 | The signature of the function had been updated to return the index instead of the pointer. If you still see your function signature returns a char * or String, please click the reload button to reset your code definition. 9 | 10 | ## Solution 11 | 12 | 模式匹配主要有三种方法: 13 | 14 | 1. 蛮力法,即BF算法 15 | 2. KMP算法 16 | 3. BM算法,工程应用比较多 17 | 18 | 具体算法见[由KMP算法谈到BM算法](http://blog.csdn.net/v_JULY_v/article/details/6545192) 19 | 20 | 本题使用BF算法TLE,只能使用KMP或者BM 21 | 22 | ```cpp 23 | int kmp_strStr(string s, string p) { 24 | if (p.empty()) 25 | return 0; 26 | if (s.empty()) { 27 | return -1; 28 | } 29 | int s_len = s.size(), p_len = p.size(); 30 | int next[p_len], i = 0, j = -1; 31 | next[0] = -1; 32 | while (i < p_len - 1) { 33 | if (j == -1 || p[i] == p[j]) { 34 | i++, j++; 35 | if (p[i] != p[j]) 36 | next[i] = j; 37 | else 38 | next[i] = next[j]; 39 | } else { 40 | j = next[j]; 41 | } 42 | } 43 | i = 0, j = 0; 44 | while (i < s_len && j < p_len) { 45 | if (j == -1 || s[i] == p[j]) 46 | i++, j++; 47 | else 48 | j = next[j]; 49 | } 50 | if (j == p_len) 51 | return i - j; 52 | return -1; 53 | } 54 | ``` 55 | 56 | ## 备注 57 | 58 | java中的indexOf算法使用的是BF算法... 59 | -------------------------------------------------------------------------------- /algorithms/InsertionSortList/README.md: -------------------------------------------------------------------------------- 1 | ## Insertion Sort List 2 | 3 | Sort a linked list using insertion sort. 4 | 5 | ## Solution 6 | 7 | 插入排序的思想并不复杂,关键是和数组不一样,不能向前搜索插入位置,而必须向前搜索 8 | 9 | 假设链表头部指针head,prev为处理完毕的最后一个节点,即prev之前(包括prev)的节点是已经排好序的,p为当前节点 10 | 11 | * 若`p->val >= prev->val`, 已经有序,更新prev = p 12 | * 若`p->val <= head->val`, 说明p是当前最小的值,需要插入到头部, 并更新头部指针指向p 13 | ```c 14 | prev->next = p->next; 15 | p->next = head; 16 | head = p; 17 | p = prev->next; 18 | ``` 19 | * t从头部开始遍历直到,`t->next >= p->val`, 则p插入t之后即可 20 | ```c 21 | struct ListNode *t = head; 22 | while (t->next->val < p->val) { 23 | t = t->next; 24 | } 25 | prev->next = p->next; 26 | p->next = t->next; 27 | t->next = p; 28 | p = prev->next; 29 | ``` 30 | 31 | ## Code 32 | ```c 33 | struct ListNode *insertionSortList(struct ListNode *head) 34 | { 35 | if (head == NULL) 36 | return NULL; 37 | struct ListNode *p = head->next; 38 | struct ListNode *prev = head; 39 | while (p) { 40 | if (p->val >= prev->val) { 41 | prev = p; 42 | p = p->next; 43 | continue; 44 | } 45 | if (p->val <= head->val) { 46 | prev->next = p->next; 47 | p->next = head; 48 | head = p; 49 | p = prev->next; 50 | } else { 51 | struct ListNode *t = head; 52 | while (t->next->val < p->val) { 53 | t = t->next; 54 | } 55 | prev->next = p->next; 56 | p->next = t->next; 57 | t->next = p; 58 | p = prev->next; 59 | 60 | } 61 | } 62 | return head; 63 | } 64 | ``` 65 | -------------------------------------------------------------------------------- /algorithms/InsertionSortList/in.txt: -------------------------------------------------------------------------------- 1 | 5 2 | 5 4 3 2 1 3 | 5 4 | 2 2 1 1 3 5 | 5 6 | 1 2 5 4 2 7 | -------------------------------------------------------------------------------- /algorithms/IntegertoRoman/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | class Solution { 6 | public: 7 | string intToRoman(int num) { 8 | string result; 9 | for (int i = 0; num; i++, num /= 10) { 10 | if (num % 10) { 11 | result = ROMAN_TABLE[i][num % 10 - 1] + result; 12 | } 13 | } 14 | return result; 15 | } 16 | private: 17 | const string ROMAN_TABLE[4][9] = { 18 | {"I", "II", "III", "IV", "V", "VI", "VII","VIII","IX"}, 19 | {"X", "XX", "XXX", "XL", "L","LX", "LXX","LXXX", "XC"}, 20 | {"C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}, 21 | {"M", "MM", "MMM", "", "", "", "", "", ""} 22 | }; 23 | }; 24 | int main(int argc, char **argv) 25 | { 26 | Solution solution; 27 | int n; 28 | while (scanf("%d", &n) != EOF) { 29 | printf("%d -> %s\n", n, solution.intToRoman(n).c_str()); 30 | } 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /algorithms/InterleavingString/in.txt: -------------------------------------------------------------------------------- 1 | aabcc dbbca aadbbcbcac 2 | aabcc dbbca aadbbbaccc 3 | a a aa 4 | a b ab 5 | a b ba 6 | abc def abcdef 7 | abc def defabc 8 | -------------------------------------------------------------------------------- /algorithms/InterleavingString/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | //void foo(char *s) { 5 | // cout << s << endl; 6 | //} 7 | void foo(const char *s) 8 | { 9 | cout << s << endl; 10 | } 11 | void foo(string s) { 12 | foo(s.c_str()); 13 | } 14 | int main(int argc, char **argv) 15 | { 16 | string s = "hello"; 17 | foo(s); 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /algorithms/InvertBinaryTree/README.md: -------------------------------------------------------------------------------- 1 | ## Invert Binary Tree 2 | 3 | Invert a binary tree. 4 | ``` 5 | 4 6 | / \ 7 | 2 7 8 | / \ / \ 9 | 1 3 6 9 10 | ``` 11 | to 12 | ``` 13 | 4 14 | / \ 15 | 7 2 16 | / \ / \ 17 | 9 6 3 1 18 | ``` 19 | 20 | Trivia: 21 | This problem was inspired by this original tweet by Max Howell: 22 | 23 | >> Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so fuck off. 24 | 25 | ## Solution 26 | 27 | 递归法,先逆转左孩子、右孩子,再交换左右孩子即可! 28 | -------------------------------------------------------------------------------- /algorithms/IsomorphicStrings/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #define N 256 5 | using namespace std; 6 | class Solution { 7 | public: 8 | bool isIsomorphic(string s, string t) { 9 | int map1[N] = {0}, map2[N] = {0}; 10 | int n = s.size(); 11 | if (n != t.size()) 12 | return false; 13 | for (int i = 0; i < n; ++i) { 14 | char a = s[i], b = t[i]; 15 | if (map1[a] != map2[b]) 16 | return false; 17 | if (map1[a] == 0) { 18 | map1[a] = map2[b] = i + 1; // avoid 0 19 | } 20 | } 21 | return true; 22 | } 23 | }; 24 | int main(int argc, char **argv) 25 | { 26 | string s1, s2; 27 | Solution solution; 28 | while (cin >> s1 >> s2) { 29 | cout << solution.isIsomorphic(s1, s2) << endl; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /algorithms/KthLargestElementinanArray/README.md: -------------------------------------------------------------------------------- 1 | ## Kth Largest Element in an Array 2 | 3 | Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element. 4 | 5 | For example, 6 | Given `[3,2,1,5,6,4]` and k = 2, return 5. 7 | 8 | Note: 9 | You may assume k is always valid, 1 ≤ k ≤ array's length. 10 | 11 | Credits: 12 | Special thanks to @mithmatt for adding this problem and creating all test cases. 13 | 14 | ## Solution 15 | 16 | 利用快排法的partition函数: 17 | 18 | ```cpp 19 | int partition(vector &nums, int s, int t) 20 | { 21 | int i = s, j = t; 22 | int k = nums[s]; 23 | while (i < j) { 24 | while (nums[j] <= k && i < j) --j; 25 | if (i < j) { 26 | nums[i] = nums[j]; 27 | } 28 | while (nums[i] >= k && i < j) ++i; 29 | if (i < j) { 30 | nums[j] = nums[i]; 31 | } 32 | } 33 | nums[i] = k; 34 | return i; 35 | } 36 | ``` 37 | 38 | 设返回的位置为pos,这个pos的值一定是排序后的正确顺序,因此若: 39 | 40 | * pos == k - 1, 则直接返回pos位置的值即可 41 | * 若pos < k - 1, 则在左边查找 42 | * 否则在右边查找. 43 | 44 | ```cpp 45 | int findKthLargest(vector &nums, int k) { 46 | int s = 0, t = nums.size() - 1; 47 | while (true) { 48 | int pos = partition(nums, s, t); 49 | if (pos == k - 1) 50 | return nums[pos]; 51 | if (pos > k - 1) { 52 | t = pos - 1; 53 | } else { 54 | s = pos + 1; 55 | } 56 | } 57 | return -1; 58 | } 59 | ``` 60 | -------------------------------------------------------------------------------- /algorithms/KthLargestElementinanArray/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | 8 | void print(const vector &nums) 9 | { 10 | for (auto i : nums) 11 | cout << i << " "; 12 | cout << endl; 13 | } 14 | class Solution { 15 | public: 16 | int findKthLargest(vector &nums, int k) { 17 | int s = 0, t = nums.size() - 1; 18 | while (true) { 19 | int pos = partition(nums, s, t); 20 | if (pos == k - 1) 21 | return nums[pos]; 22 | if (pos > k - 1) { 23 | t = pos - 1; 24 | } else { 25 | s = pos + 1; 26 | } 27 | } 28 | return -1; 29 | } 30 | private: 31 | int partition(vector &nums, int s, int t) 32 | { 33 | int i = s, j = t; 34 | int k = nums[s]; 35 | while (i < j) { 36 | while (nums[j] <= k && i < j) --j; 37 | nums[i] = nums[j]; 38 | while (nums[i] >= k && i < j) ++i; 39 | nums[j] = nums[i]; 40 | } 41 | nums[i] = k; 42 | return i; 43 | } 44 | }; 45 | int main(int argc, char **argv) 46 | { 47 | Solution solution; 48 | vector nums = {1,2,1,3,5,5}; 49 | print(nums); 50 | int result = solution.findKthLargest(nums, 2); 51 | printf("result = %d\n", result); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /algorithms/LRUCache/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class LRUCache{ 7 | 8 | public: 9 | LRUCache(int capacity) { 10 | this -> capacity = capacity; 11 | } 12 | int get(int key) { 13 | auto iter = keys.find(key); 14 | if (iter != keys.end()) { 15 | values.splice(values.begin(), values, iter->second); 16 | return values.front().second; 17 | } else 18 | return -1; 19 | } 20 | void set(int key, int value) { 21 | auto it = keys.find(key); 22 | if (it != keys.end()) { 23 | values.splice(values.begin(), values, it->second); 24 | values.front().second = value; 25 | } else { 26 | if (values.size() == capacity) { 27 | keys.erase(values.back().first); 28 | values.pop_back(); 29 | } 30 | values.push_front(make_pair(key, value)); 31 | keys[key] = values.begin(); 32 | } 33 | } 34 | private: 35 | list > values; 36 | unordered_map > :: iterator > keys; 37 | int capacity; 38 | }; 39 | int main(int argc, char **argv) 40 | { 41 | LRUCache lru(3); 42 | lru.set('a', 0); 43 | lru.set('a', 1); 44 | lru.set('b', 2); 45 | lru.set('c', 3); 46 | lru.set('d', 3); 47 | cout << lru.get('a') << endl; 48 | cout << lru.get('c') << endl; 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /algorithms/LargestNumber/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | class Solution { 6 | public: 7 | static bool cmp(const string &s1, const string &s2) { 8 | return s1 + s2 > s2 + s1; 9 | } 10 | string largestNumber(vector &num) { 11 | vector v; 12 | for_each(num.begin(), num.end(), [&](int i){v.push_back(to_string(i));}); 13 | sort(v.begin(), v.end(), cmp); 14 | string result; 15 | for_each(v.begin(), v.end(), [&](string s){result += s;}); 16 | if (result[0] == '0') 17 | return "0"; 18 | return result; 19 | } 20 | 21 | }; 22 | int main(int argc, char **argv) 23 | { 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /algorithms/LengthofLastWord/LengthofLastWord.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int lengthOfLastWord(const char *s) 7 | { 8 | if (!s || !*s) return 0; 9 | int len = strlen(s); 10 | int sum = 0; 11 | int i = len - 1; 12 | while (i >= 0 && !isalpha(s[i])) i--; 13 | while (isalpha(s[i])) { 14 | ++sum; 15 | i--; 16 | } 17 | return sum; 18 | } 19 | int main(int argc, char** argv) 20 | { 21 | const char* p; 22 | p = "hello world"; 23 | printf("%s, %d\n", p, lengthOfLastWord(p)); 24 | p = "a"; 25 | printf("%s, %d\n", p, lengthOfLastWord(p)); 26 | p = " "; 27 | printf("%s, %d\n", p, lengthOfLastWord(p)); 28 | 29 | if(argc>1){ 30 | p = argv[1]; 31 | printf("%s, %d\n", p, lengthOfLastWord(p)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /algorithms/LengthofLastWord/README.md: -------------------------------------------------------------------------------- 1 | ## Length of Last Word 2 | 3 | Given a string s consists of upper/lower-case alphabets and empty space characters ' ', return the length of last word in the string. 4 | 5 | If the last word does not exist, return 0. 6 | 7 | Note: A word is defined as a character sequence consists of non-space characters only. 8 | 9 | ``` 10 | For example, 11 | Given s = "Hello World", 12 | return 5. 13 | ``` 14 | 15 | ## Solution 16 | 17 | 先去掉后面的空格字符,然后从后面开始扫描直到遇到空格为止 18 | 19 | ## Code 20 | ```c 21 | int lengthOfLastWord(const char *s) 22 | { 23 | if (!s || !*s) return 0; 24 | int len = strlen(s); 25 | int sum = 0; 26 | int i = len - 1; 27 | while (i >= 0 && !isalpha(s[i])) i--; 28 | while (isalpha(s[i])) { 29 | ++sum; 30 | i--; 31 | } 32 | return sum; 33 | } 34 | ``` 35 | -------------------------------------------------------------------------------- /algorithms/LetterCombinationsofaPhoneNumber/keypad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/int32bit/leetcode/4cf8d30509f4b994b1845765807380eeffb95c73/algorithms/LetterCombinationsofaPhoneNumber/keypad.png -------------------------------------------------------------------------------- /algorithms/LetterCombinationsofaPhoneNumber/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | class Solution { 8 | public: 9 | Solution() { 10 | map['2'] = "abc"; 11 | map['3'] = "def"; 12 | map['4'] = "ghi"; 13 | map['5'] = "jkl"; 14 | map['6'] = "mno"; 15 | map['7'] = "pqrs"; 16 | map['8'] = "tuv"; 17 | map['9'] = "wxyz"; 18 | } 19 | vector letterCombinations(string digits) { 20 | vector result; 21 | if (digits.size() == 0) { 22 | return result; 23 | } 24 | for (char c : digits) { 25 | result = generate(result, c); 26 | } 27 | return result; 28 | } 29 | vector generate(vector current, char digit) { 30 | vector result; 31 | if (current.size() > 0) { 32 | for (char c : map[digit]) { 33 | for_each(current.begin(), current.end(), [&result, c](string s){result.push_back(s + c);}); 34 | } 35 | } else { 36 | for (char c : map[digit]) 37 | result.push_back(string() + c); 38 | } 39 | return result; 40 | } 41 | private: 42 | unordered_map map; 43 | }; 44 | int main(int argc, char **argv) 45 | { 46 | Solution solution; 47 | auto result = solution.letterCombinations("23"); 48 | for_each(result.begin(), result.end(), [](string s){cout << s << endl;}); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /algorithms/LinkedListCycle/README.md: -------------------------------------------------------------------------------- 1 | ## Linked List Cycle 2 | 3 | Given a linked list, determine if it has a cycle in it. 4 | 5 | Follow up: 6 | Can you solve it without using extra space? 7 | 8 | ## Solution 9 | 10 | 快慢指针法 11 | 12 | 设两个指针p, q, p每次移一个节点,q每次移动两个节点,如果`p == q`,则有环。如果p,q其一等于`NULL`,则无环 13 | 14 | 更多链表环操作,见[Linked List Cycle II](../LinkedListCycle2) 15 | 16 | ## Code 17 | ```c 18 | bool hasCycle(struct ListNode *head) { 19 | if (head == NULL) 20 | return false; 21 | struct ListNode *p = head, *q = head->next;; 22 | while (p && q) { 23 | if (p == q) 24 | return true; 25 | p = p -> next; 26 | q = q -> next; 27 | if (q == NULL) 28 | return false; 29 | q = q -> next; 30 | } 31 | } 32 | ``` 33 | -------------------------------------------------------------------------------- /algorithms/LinkedListCycle/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | struct ListNode { 5 | int val; 6 | struct ListNode *next; 7 | }; 8 | bool hasCycle(struct ListNode *head) { 9 | if (head == NULL) 10 | return false; 11 | struct ListNode *p = head, *q = head->next;; 12 | while (p && q) { 13 | if (p == q) 14 | return true; 15 | p = p -> next; 16 | q = q -> next; 17 | if (q == NULL) 18 | return false; 19 | q = q -> next; 20 | } 21 | } 22 | void mk_list(struct ListNode **head, int a[], int n) 23 | { 24 | struct ListNode *p = malloc(sizeof(*p)); 25 | *head = p; 26 | p->val = a[0]; 27 | p->next = NULL; 28 | for (int i = 1; i < n; ++i) 29 | { 30 | struct ListNode *t = malloc(sizeof(*t)); 31 | t->val = a[i]; 32 | t->next = NULL; 33 | p->next = t; 34 | p = t; 35 | } 36 | } 37 | int main(int argc, char **argv) 38 | { 39 | struct ListNode *head; 40 | int a[] = {1,2,3,4,5}; 41 | mk_list(&head, a, 5); 42 | head->next->next = head; 43 | printf("%d\n", hasCycle(head)); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /algorithms/LinkedListCycle2/README.md: -------------------------------------------------------------------------------- 1 | ## Linked List Cycle II 2 | 3 | Given a linked list, return the node where the cycle begins. If there is no cycle, return null. 4 | 5 | Follow up: 6 | Can you solve it without using extra space? 7 | 8 | ## Solution 9 | 10 | 设置两个指针fast、low,fast每次前进2步,slow每次前进1步 11 | 12 | 如果存在环,则fast必先进入环,而slow后进入环,两个指针必定相遇.否则若fast到达`NULL`,则不存在环。 13 | 14 | 假设存在环,则两个指针相遇时,slow还没有遍历完,而fast已经在环内循环了n圈`(n >= 1)`. 15 | 16 | 设slow走了s步,则fast走了2s步,fast还等于s加上在环上多转的圈数,设环长的r,则: 17 | 18 | ![](cycle.png) 19 | 20 | ``` 21 | s = LenA + x; 22 | 2s = nr + LenA + x; 23 | => 24 | 2LenA + 2x = nr + LenA + x 25 | => 26 | LenA = nr - x 27 | 28 | 因此:第一次碰撞点Pos到join的距离等于头指针到连接点join的距离 29 | 30 | 设此时p1 = head, p2 = pos = x; 每次走一步,则当p1到达join点时, 31 | p2 = x + LenA = x + nr -x = nr 32 | 即p2也到达了join点,因此p1 与 p2相遇就是join点 33 | ``` 34 | 35 | 36 | ## 求环的长度 37 | 38 | 第一次相遇时开始计数,fast和slow继续走,当第二次相遇时,fast比slow多走了一圈,即r的长度 39 | 40 | ## 求链表长度 41 | 42 | 求到head到环入口的长度+环的长度 43 | 44 | -------------------------------------------------------------------------------- /algorithms/LinkedListCycle2/cycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/int32bit/leetcode/4cf8d30509f4b994b1845765807380eeffb95c73/algorithms/LinkedListCycle2/cycle.png -------------------------------------------------------------------------------- /algorithms/LinkedListCycle2/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | struct ListNode { 5 | int val; 6 | struct ListNode *next; 7 | }; 8 | bool hasCycle(struct ListNode *head) { 9 | if (head == NULL) 10 | return false; 11 | struct ListNode *fast = head, *slow = head; 12 | while (fast && fast->next) { 13 | fast = fast->next->next; 14 | slow = slow->next; 15 | if (fast == slow) 16 | return true; 17 | } 18 | return false; 19 | } 20 | struct ListNode *detectCycle(struct ListNode *head) 21 | { 22 | if (head == NULL) 23 | return NULL; 24 | struct ListNode *fast = head, *slow = head; 25 | while (fast && fast->next) { 26 | fast = fast->next->next; 27 | slow = slow->next; 28 | if (fast == slow) { 29 | fast = head; 30 | while (fast != slow) { 31 | fast = fast->next; 32 | slow = slow->next; 33 | } 34 | return fast; 35 | } 36 | } 37 | return NULL; 38 | } 39 | void mk_list(struct ListNode **head, int a[], int n) 40 | { 41 | struct ListNode *p = malloc(sizeof(*p)); 42 | *head = p; 43 | p->val = a[0]; 44 | p->next = NULL; 45 | for (int i = 1; i < n; ++i) 46 | { 47 | struct ListNode *t = malloc(sizeof(*t)); 48 | t->val = a[i]; 49 | t->next = NULL; 50 | p->next = t; 51 | p = t; 52 | } 53 | } 54 | int main(int argc, char **argv) 55 | { 56 | struct ListNode *head; 57 | int a[] = {1,2,3,4,5}; 58 | mk_list(&head, a, 5); 59 | //head->next->next = head; 60 | printf("%d\n", hasCycle(head)); 61 | printf("%d\n", detectCycle(head)->val); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /algorithms/LongestCommonPrefix/README.md: -------------------------------------------------------------------------------- 1 | ## Longest Common Prefix 2 | 3 | Write a function to find the longest common prefix string amongst an array of strings. 4 | 5 | ## Solution 6 | 7 | 逐一比较即可 8 | ```cpp 9 | string longestCommonPrefix(vector& strs) { 10 | int n = strs.size(); 11 | if (n < 1) 12 | return ""; 13 | int m = strs[0].size(); 14 | int i,j; 15 | for (i = 0; i < m; ++i) { 16 | for (auto s : strs) { 17 | if (i >= s.size() || s[i] != strs[0][i]) 18 | return strs[0].substr(0, i); 19 | } 20 | } 21 | return strs[0]; 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /algorithms/LongestCommonPrefix/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | string longestCommonPrefix(vector& strs) { 9 | int n = strs.size(); 10 | if (n < 1) 11 | return ""; 12 | int m = strs[0].size(); 13 | int i,j; 14 | for (i = 0; i < m; ++i) { 15 | for (auto s : strs) { 16 | if (i >= s.size() || s[i] != strs[0][i]) 17 | return strs[0].substr(0, i); 18 | } 19 | } 20 | return strs[0]; 21 | } 22 | 23 | }; 24 | int main(int argc, char **argv) 25 | { 26 | Solution solution; 27 | vector s = {"abcd", "abc", "abedefg", "abcdefgh"}; 28 | cout << solution.longestCommonPrefix(s) << endl; 29 | } 30 | -------------------------------------------------------------------------------- /algorithms/LongestConsecutiveSequence/README.md: -------------------------------------------------------------------------------- 1 | ## Longest Consecutive Sequence 2 | 3 | Given an unsorted array of integers, find the length of the longest consecutive elements sequence. 4 | 5 | For example, 6 | Given `[100, 4, 200, 1, 3, 2]`, 7 | The longest consecutive elements sequence is `[1, 2, 3, 4]`. Return its length: `4`. 8 | 9 | Your algorithm should run in O(n) complexity. 10 | 11 | ## Solution 12 | 13 | 刚开始以为是DP,没有思路! 14 | 15 | 看了答案发现其实并不是很复杂,关键找对思路。。 16 | 17 | 使用map,key为数值,value为长度, 设当前遍历数组的值为i 18 | 19 | * 若i已经在map中,忽略。 20 | * 否则`left = map[i - 1] or 0, right = map[i + 1] or 0`,则`map[i] = left + right + 1`,即当前值的长度等于它左相邻和右相邻长度之和+1. 21 | * 同时需要更新边界值,即`map[i - left] = map[i], map[i + right] = map[i]`, 22 | 因为我们第一步忽略了已经存在的值,因此我们只需要维护边界值即可,而不用把中间的值同时更新. 23 | * 返回最大的map值即可 24 | 25 | 26 | ```cpp 27 | int longestConsecutive(vector &nums) { 28 | unordered_map map; 29 | int res = 0; 30 | for (int i : nums) { 31 | if (map.find(i) != map.end()) { 32 | continue; 33 | } 34 | int left = getOrElse(map, i - 1); 35 | int right = getOrElse(map, i + 1); 36 | int sum = left + right + 1; 37 | res = max(res, sum); 38 | map[i] = sum; 39 | map[i - left] = sum; 40 | map[i + right] = sum; 41 | } 42 | return res; 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /algorithms/LongestConsecutiveSequence/in.txt: -------------------------------------------------------------------------------- 1 | 21 2 | 4 0 -4 -2 2 5 2 0 -8 -8 -8 -8 -1 7 4 5 5 -4 6 6 -3 3 | 8 4 | 3 1 2 8 10 7 6 9 5 | 5 6 | 1 2 4 5 3 7 | 5 8 | 1 1 1 2 2 9 | 6 10 | 2 2 1 2 1 3 11 | -------------------------------------------------------------------------------- /algorithms/LongestConsecutiveSequence/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | using namespace std; 9 | class Solution { 10 | public: 11 | int longestConsecutive(vector &nums) { 12 | unordered_map map; 13 | int res = 0; 14 | for (int i : nums) { 15 | if (map.find(i) != map.end()) { 16 | continue; 17 | } 18 | int left = getOrElse(map, i - 1); 19 | int right = getOrElse(map, i + 1); 20 | int sum = left + right + 1; 21 | res = max(res, sum); 22 | map[i] = sum; 23 | map[i - left] = sum; 24 | map[i + right] = sum; 25 | } 26 | return res; 27 | } 28 | private: 29 | int getOrElse(unordered_map &map, int key, int defaultValue) { 30 | if (map.find(key) != map.end()) { 31 | return map[key]; 32 | } else 33 | return defaultValue; 34 | } 35 | int getOrElse(unordered_map &map, int key) { 36 | return getOrElse(map, key, 0); 37 | } 38 | }; 39 | int main(int argc, char **argv) 40 | { 41 | Solution solution; 42 | int n; 43 | while (scanf("%d", &n) != EOF) { 44 | vector nums; 45 | for (int i = 0; i < n; ++i) { 46 | int v; 47 | scanf("%d", &v); 48 | nums.push_back(v); 49 | } 50 | printf("%d\n", solution.longestConsecutive(nums)); 51 | break; 52 | } 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /algorithms/LongestSubstringWithoutRepeatingCharacters/src1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | int lengthOfLongestSubstring(string s) { 9 | vector v; 10 | unsigned int max = 0; 11 | for (size_t i = 0; i < s.size(); ++i) { 12 | auto pos = find(v.begin(), v.end(), s[i]); 13 | if (pos != v.end()) { 14 | max = max >= v.size() ? max : v.size(); 15 | v.erase(v.begin(), pos + 1); 16 | } 17 | v.push_back(s[i]); 18 | } 19 | return max >= v.size() ? max : v.size(); 20 | } 21 | }; 22 | int main(int argc, char **argv) 23 | { 24 | Solution solution; 25 | string s = "abcadef"; 26 | cout << solution.lengthOfLongestSubstring(s) << endl; 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /algorithms/LongestSubstringWithoutRepeatingCharacters/src2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int max(int a, int b) 5 | { 6 | return a >= b ? a : b; 7 | } 8 | int lengthOfLongestSubstring(char *s) { 9 | int hash[256],len = strlen(s), i; 10 | int result = 0, curLen = 0, pos = 0,maxPos; 11 | if (len < 2) 12 | return len; 13 | memset(hash, -1, sizeof(hash)); 14 | for (i = 0; i < len; ++i) { 15 | if (hash[s[i]] == -1) { 16 | curLen++; 17 | hash[s[i]] = i; 18 | } else { 19 | result = max(result, curLen); // update result 20 | maxPos = max(pos, hash[s[i]]); 21 | curLen = i - maxPos; 22 | pos = maxPos; 23 | hash[s[i]] = i; 24 | } 25 | } 26 | return result >= curLen ? result : curLen; 27 | } 28 | int main(int argc, char **argv) 29 | { 30 | char s1[] = "abba"; 31 | char s2[] = "abca"; 32 | char s3[] = "abcb"; 33 | char s4[] = "pwwkew"; 34 | char s5[] = "tmmzuxt"; 35 | char s6[] = "aa"; 36 | //printf("%d\n", lengthOfLongestSubstring(s1)); 37 | //printf("%d\n", lengthOfLongestSubstring(s2)); 38 | //printf("%d\n", lengthOfLongestSubstring(s3)); 39 | printf("%d\n", lengthOfLongestSubstring(s4)); 40 | printf("%d\n", lengthOfLongestSubstring(s5)); 41 | printf("%d\n", lengthOfLongestSubstring(s6)); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /algorithms/MajorityElement/README.md: -------------------------------------------------------------------------------- 1 | ## Majority Element 2 | 3 | Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times. 4 | 5 | You may assume that the array is non-empty and the majority element always exist in the array. 6 | 7 | ## Solution 8 | 9 | 一个数字出现数组次数的一半,即这个数字的次数超过其他数字出现次数之和 10 | 11 | 可以用一个count指针,以及当前候选数字result: 12 | 13 | * 若`a[i] == result`, 则`count++`,否则若`a[i] != result`,则`count--` 14 | * 若`count == 0`, 则更新result,即`result = a[i]` 15 | 16 | 最后result就是次数超过一半的数字 17 | 18 | ## Code 19 | ```c 20 | int majorityElement(int a[], int n) 21 | { 22 | if (n < 2) 23 | return a[0]; 24 | int result = a[0]; 25 | int count = 0; 26 | for (int i = 0; i < n; ++i) { 27 | if (a[i] == result) { 28 | ++count; 29 | } else { 30 | --count; 31 | } 32 | if (count == 0) { 33 | count = 1; 34 | result = a[i]; 35 | } 36 | } 37 | return result; 38 | } 39 | ``` 40 | -------------------------------------------------------------------------------- /algorithms/MajorityElement/in.txt: -------------------------------------------------------------------------------- 1 | 5 2 | 1 1 1 2 2 3 | 5 4 | 2 1 2 1 1 5 | 5 6 | 1 2 1 2 1 7 | 5 8 | 2 1 2 1 1 9 | 1 10 | 1 11 | 4 12 | 1 1 2 1 13 | -------------------------------------------------------------------------------- /algorithms/MajorityElement/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int majorityElement(int a[], int n) 5 | { 6 | if (n < 2) 7 | return a[0]; 8 | int result = a[0]; 9 | int count = 0; 10 | for (int i = 0; i < n; ++i) { 11 | if (a[i] == result) { 12 | ++count; 13 | } else { 14 | --count; 15 | } 16 | if (count == 0) { 17 | count = 1; 18 | result = a[i]; 19 | } 20 | } 21 | return result; 22 | } 23 | int main(int argc, char **argv) 24 | { 25 | int a[20]; 26 | int n; 27 | while (scanf("%d", &n) != EOF) { 28 | for (int i = 0; i < n; ++i) 29 | scanf("%d", a + i); 30 | printf("%d\n", majorityElement(a, n)); 31 | } 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /algorithms/MaximumDepthofBinaryTree/README.md: -------------------------------------------------------------------------------- 1 | ## Maximum Depth of Binary Tree 2 | 3 | Given a binary tree, find its maximum depth. 4 | 5 | The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 6 | 7 | ## Solution 8 | 9 | 递归,树的高度等于左子树和右子树深度大的 10 | 11 | ## Code 12 | ```c 13 | int maxDepth(struct TreeNode *root) 14 | { 15 | if (root == NULL) 16 | return 0; 17 | return max(maxDepth(root->left), maxDepth(root->right)) + 1; 18 | } 19 | ``` 20 | 21 | ## 扩展 22 | 23 | 求树的最小深度[Minimum Depth of Binary Tree](../MinimumDepthofBinaryTree) 24 | -------------------------------------------------------------------------------- /algorithms/MaximumDepthofBinaryTree/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | struct TreeNode { 5 | int val; 6 | struct TreeNode *left; 7 | struct TreeNode *right; 8 | }; 9 | static inline int max(int a, int b) 10 | { 11 | return a > b ? a : b; 12 | } 13 | int maxDepth(struct TreeNode *root) 14 | { 15 | if (root == NULL) 16 | return 0; 17 | return max(maxDepth(root->left), maxDepth(root->right)) + 1; 18 | } 19 | int main(int argc, char **argv) 20 | { 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /algorithms/MaximumProductSubarray/README.md: -------------------------------------------------------------------------------- 1 | ## Maximum Product Subarray 2 | 3 | Find the contiguous subarray within an array (containing at least one number) which has the largest product. 4 | 5 | For example, given the array `[2,3,-2,4]`, 6 | the contiguous subarray `[2,3]` has the largest product = `6`. 7 | 8 | ## Solution 9 | 10 | 设pos,neg分别保存当前的可能最大正数和最小负数,max为候选最大值。则 11 | 12 | * `a[i] == 0, pos = neg = 0` 13 | * `a[i] > 0, pos = MAX(pos * a[i], a[i]), neg = MIN(neg * a[i], a[i])`, 取`MAX,MIN`的原因是排除旧值等于0的情况 14 | * `a[i] < 0, pos = MAX(neg * a[i], a[i]), neg = MIN(pos * a[i], a[i])` 15 | * `max = MAX(max, pos)` 16 | 17 | ## Code 18 | ```cpp 19 | int maxProduct(vector& nums) { 20 | const size_t size = nums.size(); 21 | if (size < 1) 22 | return 0; 23 | if (size == 1) 24 | return nums[0]; 25 | int neg = 0, pos = 0, max = 0; 26 | for (auto i = 0; i < size; ++i) { 27 | if (nums[i] == 0) { 28 | pos = neg = 0; 29 | } else if (nums[i] > 0) { 30 | pos = MAX(pos * nums[i], nums[i]); 31 | neg = MIN(neg * nums[i], neg); 32 | } else { 33 | int old_pos = pos; 34 | int old_neg = neg; 35 | pos = MAX(old_neg * nums[i], nums[i]); 36 | neg = MIN(old_pos * nums[i], nums[i]); 37 | } 38 | max = MAX(max, pos); 39 | } 40 | return max; 41 | } 42 | ``` 43 | 44 | ## 扩展 45 | 46 | [Maximum Subarray](../MaximumSubarray): 最大连续之和 47 | -------------------------------------------------------------------------------- /algorithms/MaximumProductSubarray/in.txt: -------------------------------------------------------------------------------- 1 | 4 2 | 2 3 -2 4 3 | 5 4 | -1 -2 -3 -4 -5 5 | 5 6 | 1 -2 -3 -1 -1 7 | 5 8 | 2 2 2 2 2 9 | 4 10 | 2 3 -4 -3 11 | 5 12 | 1 2 0 2 3 13 | -------------------------------------------------------------------------------- /algorithms/MaximumProductSubarray/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ./a.out 2 | #include 3 | #include 4 | #include 5 | #define MAX(a, b) ((a) >= (b) ? (a) : (b)) 6 | #define MIN(a, b) ((a) <= (b) ? (a) : (b)) 7 | using namespace std; 8 | class Solution { 9 | public: 10 | int maxProduct(vector& nums) { 11 | const size_t size = nums.size(); 12 | if (size < 1) 13 | return 0; 14 | if (size == 1) 15 | return nums[0]; 16 | int neg = 0, pos = 0, max = 0; 17 | for (auto i = 0; i < size; ++i) { 18 | if (nums[i] == 0) { 19 | pos = neg = 0; 20 | } else if (nums[i] > 0) { 21 | pos = MAX(pos * nums[i], nums[i]); 22 | neg = MIN(neg * nums[i], neg); 23 | } else { 24 | int old_pos = pos; 25 | int old_neg = neg; 26 | pos = MAX(old_neg * nums[i], nums[i]); 27 | neg = MIN(old_pos * nums[i], nums[i]); 28 | } 29 | max = MAX(max, pos); 30 | } 31 | return max; 32 | } 33 | }; 34 | int main(int argc, char **argv) 35 | { 36 | Solution solution; 37 | int a[20]; 38 | int n; 39 | while (scanf("%d", &n) != EOF) { 40 | for (int i = 0; i < n; ++i) 41 | scanf("%d", a + i); 42 | vector v(a, a + n); 43 | printf("%d\n", solution.maxProduct(v)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /algorithms/MaximumSubarray/README.md: -------------------------------------------------------------------------------- 1 | ## Maximum Subarray 2 | 3 | Find the contiguous subarray within an array (containing at least one number) which has the largest sum. 4 | 5 | For example, given the array [−2,1,−3,4,−1,2,1,−5,4], 6 | the contiguous subarray [4,−1,2,1] has the largest sum = 6. 7 | 8 | click to show more practice. 9 | More practice: 10 | 11 | If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle. 12 | 13 | ## Solution 14 | 15 | 最大连续之和经典题 16 | 17 | ```c 18 | int maxSubArray(int *a, int n) 19 | { 20 | if (a == NULL || n <= 0) 21 | return 0; 22 | int max = a[0], sum = a[0]; 23 | for (int i = 1; i < n; ++i) { 24 | if (sum < 0) 25 | sum = a[i]; 26 | else 27 | sum += a[i]; 28 | max = MAX(max, sum); 29 | } 30 | return max; 31 | } 32 | ``` 33 | ## 扩展 34 | 35 | [Maximum Product Subarray](../MaximumProductSubarray): 最大连续之积 36 | -------------------------------------------------------------------------------- /algorithms/MaximumSubarray/in.txt: -------------------------------------------------------------------------------- 1 | 9 2 | -2 1 -3 4 -1 2 1 -5 4 3 | 5 4 | -1 -2 -3 -4 -5 5 | 5 6 | 1 -8 2 3 4 7 | -------------------------------------------------------------------------------- /algorithms/MaximumSubarray/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | static inline int MAX(int a, int b) 5 | { 6 | return a > b ? a : b; 7 | } 8 | int maxSubArray(int *a, int n) 9 | { 10 | if (a == NULL || n <= 0) 11 | return 0; 12 | int max = a[0], sum = a[0]; 13 | for (int i = 1; i < n; ++i) { 14 | if (sum < 0) 15 | sum = a[i]; 16 | else 17 | sum += a[i]; 18 | max = MAX(max, sum); 19 | } 20 | return max; 21 | } 22 | void print(int *a, int n) 23 | { 24 | for (int i = 0; i < n; ++i) 25 | printf("%d ", a[i]); 26 | printf("\n"); 27 | } 28 | int main(int argc, char **argv) 29 | { 30 | int a[20], n; 31 | memset(a, 0, sizeof(a)); 32 | while (scanf("%d", &n) != EOF) { 33 | for (int i = 0; i < n; ++i) 34 | scanf("%d", &a[i]); 35 | printf("%d\n", maxSubArray(a, n)); 36 | } 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /algorithms/MedianofTwoSortedArrays/kth.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | static inline int min(int a, int b) 5 | { 6 | return a < b ? a : b; 7 | } 8 | int getkth(int s[], int m, int l[], int n, int k) { 9 | if (m > n) 10 | return getkth(l, n, s, m, k); 11 | if (m == 0) 12 | return l[k - 1]; 13 | if (k == 1) 14 | return min(s[0], l[0]); 15 | int i = min(m, k / 2), j = min(n, k / 2); 16 | if (s[i - 1] > l[j - 1]) 17 | return getkth(s, m, l + j, n - j, k - j); 18 | else 19 | return getkth(s + i, m - i, l, n, k - i); 20 | } 21 | double getMedia(int a[], int m, int b[], int n) 22 | { 23 | if ((m + n) & 0x1) { 24 | return getkth(a, m, b, n, ((m + n) >> 1) + 1); 25 | } else 26 | return (getkth(a, m, b,n, (m + n) >> 1) + getkth(a, m, b, n, ((m + n) >> 1) + 1)) / 2.0; 27 | } 28 | int main(int argc, char **argv) 29 | { 30 | int a[] = {1,3,5,7,9}; 31 | int b[] = {2,4,6}; 32 | printf("%d\n", getkth(a, 5, b, 3, 7)); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /algorithms/MedianofTwoSortedArrays/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | static inline int min(int a, int b) 6 | { 7 | return a < b ? a : b; 8 | } 9 | int getkth(int a[], int n, int b[], int m, int k) 10 | { 11 | if (k <= 0 || k > n + m) 12 | return -1; 13 | if (n > m) 14 | return getkth(b, m, a, n, k); 15 | if (n == 0) 16 | return b[k - 1]; 17 | if (k == 1) { 18 | return min(a[0], b[0]); 19 | } 20 | int i = min(n, k / 2), j = min(m, k / 2); 21 | if (a[i - 1] > b[j - 1]) 22 | return getkth(a, n, b + j, m - j, k - j); 23 | else 24 | return getkth(a + i, n - i, b, m, k - i); 25 | } 26 | double findMedianSortedArrays(int *a, int n, int *b, int m) { 27 | if ((n + m) & 0x1) { 28 | return getkth(a, n, b, m, ((n + m) >> 1) + 1); 29 | } 30 | int left = getkth(a, n, b, m, (n + m) >> 1); 31 | int right = getkth(a, n, b, m, ((n + m) >> 1) + 1); 32 | return (left + right) / 2.0; 33 | } 34 | double getMedian(int *a, int n, int *b, int m) { 35 | return findMedianSortedArrays(a, n, b, m); 36 | } 37 | int main(int argc, char **argv) 38 | { 39 | int a[] = {1,3,5,7,9}; 40 | int b[] = {2,4,6,8,10}; 41 | printf("%lf\n", getMedian(a, 5, b, 5)); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /algorithms/MergeSortedArray/in.txt: -------------------------------------------------------------------------------- 1 | 3 3 2 | 1 3 5 3 | 2 4 6 4 | 5 | 3 0 6 | 1 2 3 7 | 8 | 0 3 9 | 1 2 3 10 | 11 | 1 5 12 | 3 13 | 1 2 4 5 6 14 | -------------------------------------------------------------------------------- /algorithms/MergeTwoSortedLists/README.md: -------------------------------------------------------------------------------- 1 | # Merge Two Sorted Lists 2 | 3 | ## Problem 4 | Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. 5 | 6 | ## Solution 7 | 8 | 简单归并操作 9 | 10 | ```c 11 | struct ListNode *mergeTwoLists(struct ListNode *l1, struct ListNode *l2) { 12 | struct ListNode *p = l1, *q = l2, *result = NULL, *k = NULL; 13 | if (l1 == NULL) 14 | return l2; 15 | if (l2 == NULL) 16 | return l1; 17 | if (p -> val <= q->val) { 18 | result = p; 19 | p = p->next; 20 | } else { 21 | result = q; 22 | q = q->next; 23 | } 24 | k = result; 25 | while (p && q) { 26 | if (p->val <= q->val) { 27 | k->next = p; 28 | p = p->next; 29 | } else { 30 | k->next = q; 31 | q = q->next; 32 | } 33 | k = k->next; 34 | } 35 | while (p) { 36 | k->next = p; 37 | p = p->next; 38 | k = k->next; 39 | } 40 | while (q) { 41 | k->next = q; 42 | q = q->next; 43 | k = k->next; 44 | } 45 | return result; 46 | } 47 | ``` 48 | ## 扩展 49 | 50 | * [Merge Two Sorted Lists](../MergeTwoSortedLists): 合并两个链表 51 | * [Merge k Sorted Lists](../MergekSortedLists): 合并K个链表 52 | * [Merge Sorted Array](../MergeSortedArray): 合并两个数组 53 | * [Sort List](../SortList): 归并排序两个链表 54 | -------------------------------------------------------------------------------- /algorithms/MergeTwoSortedLists/src.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | struct ListNode { 4 | int val; 5 | struct ListNode *next; 6 | 7 | }; 8 | struct ListNode *mergeTwoLists(struct ListNode *l1, struct ListNode *l2) { 9 | struct ListNode *p = l1, *q = l2, *result = NULL, *k = NULL; 10 | if (l1 == NULL) 11 | return l2; 12 | if (l2 == NULL) 13 | return l1; 14 | if (p -> val <= q->val) { 15 | result = p; 16 | p = p->next; 17 | } else { 18 | result = q; 19 | q = q->next; 20 | } 21 | k = result; 22 | while (p && q) { 23 | if (p->val <= q->val) { 24 | k->next = p; 25 | p = p->next; 26 | } else { 27 | k->next = q; 28 | q = q->next; 29 | } 30 | k = k->next; 31 | } 32 | while (p) { 33 | k->next = p; 34 | p = p->next; 35 | k = k->next; 36 | } 37 | while (q) { 38 | k->next = q; 39 | q = q->next; 40 | k = k->next; 41 | } 42 | return result; 43 | } 44 | int main(int argc, char **argv) 45 | { 46 | struct ListNode *l1 = NULL, *l2 = NULL; 47 | l1 = malloc(sizeof(*l1)); 48 | l1->val = 2; 49 | l1->next = malloc(sizeof(*l1)); 50 | l1->next->val = 4; 51 | l1->next->next = NULL; 52 | 53 | l2 = malloc(sizeof(*l2)); 54 | l2->val = 1; 55 | l2->next = malloc(sizeof(*l2)); 56 | l2->next->val = 3; 57 | l2->next->next = NULL; 58 | struct ListNode *result = mergeTwoLists(l1, l2); 59 | while(result) { 60 | printf("%d ", result->val); 61 | result = result->next; 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /algorithms/MergekSortedLists/solve2.cpp: -------------------------------------------------------------------------------- 1 | ListNode *mergeKLists(vector &lists) { 2 | // Begin and end of our range of elements: 3 | auto it_begin = begin(lists); 4 | auto it_end = end(lists); 5 | 6 | // Removes empty lists: 7 | it_end = remove_if(it_begin, it_end, isNull); 8 | if (it_begin == it_end) return nullptr; // All lists where empty. 9 | 10 | // Head and tail of the merged list: 11 | ListNode *head = nullptr; 12 | ListNode *tail = nullptr; 13 | 14 | // Builds a min-heap over the list of lists: 15 | make_heap(it_begin, it_end, minHeapPred); 16 | 17 | // The first element in the heap is the head of our merged list: 18 | head = tail = *it_begin; 19 | 20 | while (distance(it_begin, it_end) > 1) { 21 | 22 | // Moves the heap's front list to its back: 23 | pop_heap(it_begin, it_end, minHeapPred); 24 | 25 | // And removes one node from it: 26 | --it_end; 27 | *it_end = (*it_end)->next; 28 | 29 | // If it is not empty it inserts it back into the heap: 30 | if (*it_end) { 31 | 32 | ++it_end; 33 | push_heap(it_begin, it_end, minHeapPred); 34 | } 35 | 36 | // After the push we have our next node in front of the heap: 37 | tail->next = *it_begin; 38 | tail = tail->next; 39 | } 40 | 41 | return head; 42 | } 43 | -------------------------------------------------------------------------------- /algorithms/MinStack/README.md: -------------------------------------------------------------------------------- 1 | ## Min Stack 2 | Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. 3 | 4 | * push(x) -- Push element x onto stack. 5 | * pop() -- Removes the element on top of the stack. 6 | * top() -- Get the top element. 7 | * getMin() -- Retrieve the minimum element in the stack. 8 | 9 | ## Solution 10 | 11 | 使用两个栈实现,其中一个栈values保存值,另一个栈minValues保存最小值。 12 | 13 | * 当入栈时,如果有更小的值(x <= minValues.top()), 则把该值也压入最小值栈 14 | * 当出栈时,如果弹出的值是最小值(x == minValues.top()), 则把最小值栈也弹出一个值 15 | 16 | ```cpp 17 | class MinStack { 18 | public: 19 | void push(int x) { 20 | values.push(x); 21 | if (minValues.empty() || x <= minValues.top()) 22 | minValues.push(x); 23 | } 24 | void pop() { 25 | int x = values.top(); 26 | values.pop(); 27 | if (x == minValues.top()) 28 | minValues.pop(); 29 | 30 | } 31 | int top() const { 32 | return values.top(); 33 | } 34 | int getMin() const { 35 | return minValues.top(); 36 | } 37 | int size() const { 38 | return values.size(); 39 | } 40 | private: 41 | stack values; 42 | stack minValues; 43 | }; 44 | ``` 45 | -------------------------------------------------------------------------------- /algorithms/MinStack/minStack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class MinStack { 7 | public: 8 | void push(int x) { 9 | values.push(x); 10 | if (minValues.empty() || x <= minValues.top()) 11 | minValues.push(x); 12 | } 13 | void pop() { 14 | int x = values.top(); 15 | values.pop(); 16 | if (x == minValues.top()) 17 | minValues.pop(); 18 | 19 | } 20 | int top() const { 21 | return values.top(); 22 | } 23 | int getMin() const { 24 | return minValues.top(); 25 | } 26 | int size() const { 27 | return values.size(); 28 | } 29 | private: 30 | stack values; 31 | stack minValues; 32 | }; 33 | void test(const MinStack &stack) 34 | { 35 | printf("top = %d, min = %d\n", stack.top(), stack.getMin()); 36 | } 37 | int main(int argc, char **argv) 38 | { 39 | MinStack stack; 40 | stack.push(0); 41 | stack.push(1); 42 | stack.push(0); 43 | test(stack); 44 | stack.pop(); 45 | test(stack); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /algorithms/MinimumDepthofBinaryTree/README.md: -------------------------------------------------------------------------------- 1 | ## Minimum Depth of Binary Tree 2 | 3 | Given a binary tree, find its minimum depth. 4 | 5 | The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. 6 | 7 | ## Solution 8 | 9 | 题目不难,但犯了好几个错误: 10 | 11 | * 最小深度的概念没有弄清楚,必须是到叶子节点中最短的路径 12 | ``` 13 | 1 14 | / 15 | 3 16 | ``` 17 | 以上述的最小深度不是1而是2 18 | 19 | * 利用宏求最小值,重复计算导致超时 20 | ``` 21 | #define MIN(a, b) ((a) < (b) : (a) : (b)) 22 | 23 | MIN(minDepth(root->left), minDepth(root->right)); 24 | 25 | 展开为 26 | 27 | minDepth(root->left) < minDepth(root->right) ? minDepth(root->left) : minDepth(root->right); 28 | ``` 29 | 30 | 发现每次计算左右子树都是两倍计算量 31 | 32 | ** 因此以后尽量不要使用宏定义, 而尽量使用内联函数 ** 33 | 34 | # Code 35 | ```cpp 36 | int minDepth(struct TreeNode *root) { 37 | if (root == NULL) 38 | return 0; 39 | if (root->left && root->right) 40 | return min(minDepth(root->left), minDepth(root->right)) + 1; 41 | else if (root->left) 42 | return minDepth(root->left) + 1; 43 | else 44 | return minDepth(root->right) + 1; 45 | } 46 | ``` 47 | 48 | ## 扩展 49 | 50 | 最大深度[Maximum Depth of Binary Tree](../MaximumDepthofBinaryTree) 51 | -------------------------------------------------------------------------------- /algorithms/MinimumPathSum/in.txt: -------------------------------------------------------------------------------- 1 | 3 3 2 | 1 2 0 3 | 0 5 1 4 | 3 6 0 5 | 19 10 6 | 1 7 4 3 2 2 2 9 2 6 7 | 3 6 6 1 0 5 9 6 3 8 8 | 1 5 4 5 3 8 7 2 5 6 9 | 5 7 6 9 0 8 1 4 7 5 10 | 0 2 1 9 5 3 6 5 9 9 11 | 5 3 6 1 8 9 0 7 4 7 12 | 6 9 4 2 0 6 0 3 2 9 13 | 8 3 3 1 2 9 5 8 6 6 14 | 9 1 9 5 4 7 6 4 5 0 15 | 4 1 1 8 5 1 7 5 4 9 16 | 6 4 4 9 8 8 8 5 8 4 17 | 1 7 7 3 2 4 0 9 8 7 18 | 1 4 0 3 5 5 4 2 2 1 19 | 3 0 5 8 0 3 6 0 0 5 20 | 7 2 4 6 5 7 0 7 8 1 21 | 7 9 5 7 4 0 5 1 4 9 22 | 2 8 0 9 8 2 5 6 2 5 23 | 3 9 9 8 6 4 7 8 4 5 24 | 9 1 6 5 0 3 5 5 4 0 25 | -------------------------------------------------------------------------------- /algorithms/MultiplyStrings/in.txt: -------------------------------------------------------------------------------- 1 | 0 1000 2 | 1000 0 3 | 1 111 4 | 111 1 5 | 9 999 6 | 999 9 7 | 999 999 8 | 1001 1000 9 | 1000 1001 10 | -------------------------------------------------------------------------------- /algorithms/NextPermutation/README.md: -------------------------------------------------------------------------------- 1 | ## Next Permutation 2 | 3 | Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. 4 | 5 | If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order). 6 | 7 | The replacement must be in-place, do not allocate extra memory. 8 | 9 | Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column. 10 | ``` 11 | 1,2,3 → 1,3,2 12 | 3,2,1 → 1,2,3 13 | 1,1,5 → 1,5,1 14 | ``` 15 | 16 | ## Solution 17 | 18 | 算法见[July字符串全排列](https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/01.06.md) 19 | 20 | 这里需要注意的是有相同的数字出现,注意循环的边界条件 21 | 22 | ## Code 23 | ```c 24 | void nextPermutation(int num[], int n) 25 | { 26 | int i, j; 27 | for (i = n - 2; i >= 0 && num[i] >= num[i + 1]; --i); // 注意边界条件num[i] >= num[i + 1] 28 | if (i < 0) { 29 | reverse(num, 0, n - 1); 30 | return; 31 | } 32 | for (j = n - 1; j > i && num[j] <= num[i]; --j); // 注意边界条件num[j] <= num[i]; 33 | swap(&num[i], &num[j]); 34 | reverse(num, i + 1, n - 1); 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /algorithms/NextPermutation/nextPermutation.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | void swap(int *a, int *b) 4 | { 5 | *a ^= *b; 6 | *b ^= *a; 7 | *a ^= *b; 8 | } 9 | void reverse(int *a, int s, int t) 10 | { 11 | int i = s, j = t; 12 | while (i < j) { 13 | swap(&a[i], &a[j]); 14 | ++i, --j; 15 | } 16 | } 17 | void nextPermutation(int num[], int n) 18 | { 19 | int i, j; 20 | for (i = n - 2; i >= 0 && num[i] >= num[i + 1]; --i); 21 | if (i < 0) { 22 | reverse(num, 0, n - 1); 23 | return; 24 | } 25 | for (j = n - 1; j > i && num[j] <= num[i]; --j); 26 | swap(&num[i], &num[j]); 27 | reverse(num, i + 1, n - 1); 28 | } 29 | void print(int *a, int n) 30 | { 31 | for (int i = 0; i < n; ++i) 32 | printf("%d ", a[i]); 33 | printf("\n"); 34 | } 35 | int main(int argc, char **argv) 36 | { 37 | int d[] = {1,1}; 38 | nextPermutation(d, 2); 39 | print(d, 2); 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /algorithms/Numberof1Bits/README.md: -------------------------------------------------------------------------------- 1 | ## Number of 1 Bits 2 | Write a function that takes an unsigned integer and returns the number of ’1' bits it has (also known as the Hamming weight). 3 | 4 | For example, the 32-bit integer ’11' has binary representation 00000000000000000000000000001011, so the function should return 3. 5 | 6 | Credits: 7 | Special thanks to @ts for adding this problem and creating all test cases. 8 | 9 | # Solution 10 | 11 | 一个数x与x-1的与运算,就是把最低位的1置0。即 `x & (x - 1)`会把最低位的1置0。 12 | 13 | # Coding 14 | ```c 15 | int hammingWeight(uint32_t n) 16 | { 17 | int sum = 0; 18 | while (n) { 19 | ++sum; 20 | n &= (n - 1); 21 | } 22 | return sum; 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /algorithms/Numberof1Bits/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | typedef unsigned int uint32_t; 4 | int hammingWeight(uint32_t n) 5 | { 6 | int sum = 0; 7 | while (n) { 8 | ++sum; 9 | n &= (n - 1); 10 | } 11 | return sum; 12 | } 13 | int main(int argc, char **argv) 14 | { 15 | uint32_t n; 16 | while (scanf("%u", &n) != EOF) { 17 | printf("%d\n", hammingWeight(n)); 18 | } 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /algorithms/NumberofIslands/README.md: -------------------------------------------------------------------------------- 1 | ## Number of Islands 2 | 3 | Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. 4 | ``` 5 | Example 1: 6 | 7 | 11110 8 | 11010 9 | 11000 10 | 00000 11 | Answer: 1 12 | 13 | Example 2: 14 | 15 | 11000 16 | 11000 17 | 00100 18 | 00011 19 | Answer: 3 20 | ``` 21 | 22 | ## Solution 23 | 24 | 当遇到1时,把所有相邻的1置0,利用搜索思想. 25 | 26 | 最开始想到BFS,内存溢出,改成DFS采用递归的方式AC 27 | 28 | ## Code 29 | ```cpp 30 | int numIslands(vector> &grid) { 31 | int result = 0; 32 | int n = grid.size(); 33 | if (n == 0) 34 | return 0; 35 | int m = grid[0].size(); 36 | for (auto i = 0; i < n; ++i) { 37 | for (auto j = 0; j < m; ++j) { 38 | if (grid[i][j] == '1') { 39 | result++; 40 | clear(grid, i, j); 41 | } 42 | } 43 | } 44 | return result; 45 | } 46 | void clear(vector> &grid, int i, int j) { 47 | int n = grid.size(); 48 | int m = grid[0].size(); 49 | if (i < 0 || j < 0 || i >= n || j >= m || grid[i][j] == '0') 50 | return; 51 | grid[i][j] = '0'; 52 | clear(grid, i - 1, j); 53 | clear(grid, i + 1, j); 54 | clear(grid, i, j - 1); 55 | clear(grid, i, j + 1); 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /algorithms/PalindromeLinkedList/README.md: -------------------------------------------------------------------------------- 1 | ## Palindrome Linked List 2 | 3 | Given a singly linked list, determine if it is a palindrome. 4 | 5 | Follow up: 6 | Could you do it in O(n) time and O(1) space? 7 | 8 | ## Solution 9 | 10 | 找到中间节点,然后原地逆转右半部分,比如左半部分和右半部分是否相等 11 | 12 | 首先实现找到中间节点,使用快慢指针: 13 | 14 | ```cpp 15 | ListNode *getMiddleNode(ListNode *head) { 16 | if (head == nullptr) 17 | return nullptr; 18 | ListNode *slow = head, *fast = head; 19 | while (fast && fast->next) { 20 | fast = fast->next->next; 21 | slow = slow->next; 22 | } 23 | return slow; 24 | } 25 | ``` 26 | 27 | 逆转链表: 28 | 29 | ```cpp 30 | ListNode *reverse(ListNode *head) { 31 | if (head == nullptr || head->next == nullptr) 32 | return head; 33 | ListNode *prev = nullptr; 34 | ListNode *p = head; 35 | while (p) { 36 | ListNode *q = p->next; 37 | p->next = prev; 38 | prev = p; 39 | p = q; 40 | } 41 | return prev; 42 | } 43 | ``` 44 | 45 | 最后结果: 46 | 47 | ```cpp 48 | bool isPalindrome(ListNode *head) { 49 | /* 空节点和单节点 */ 50 | if (head == nullptr || head->next == nullptr) 51 | return true; 52 | ListNode *mid = getMiddleNode(head); 53 | ListNode *h1 = head; 54 | ListNode *h2 = reverse(mid->next); 55 | while(h1 && h2) { 56 | if (h1->val != h2->val) 57 | return false; 58 | h1 = h1->next; 59 | h2 = h2->next; 60 | } 61 | return true; 62 | 63 | } 64 | ``` 65 | -------------------------------------------------------------------------------- /algorithms/PalindromeNumber/README.md: -------------------------------------------------------------------------------- 1 | ## Palindrome Number 2 | 3 | Determine whether an integer is a palindrome. Do this without extra space. 4 | 5 | click to show spoilers. 6 | 7 | Some hints: 8 | 9 | * Could negative integers be palindromes? (ie, -1) 10 | 11 | * If you are thinking of converting the integer to string, note the restriction of using extra space. 12 | 13 | * 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? 14 | 15 | **There is a more generic way of solving this problem.** 16 | 17 | ## Solution 18 | 19 | 提示已经说了, 可以转化成字符串,即使用`sprintf(buf, "%d", x)`,然后判断,但需要额外空间 20 | 21 | 或者把的各位逆转,比如`123 -> 321`,然后判断二者是否相等,但这样需要考虑是否有溢出情况 22 | 23 | 其实可以直接判断,即从最高位、最低位逐一比较,比如1234321,最高位从百万位的1开始向右扫描,最低位从个位的1开始向左扫描, 24 | 逐一判断是否相等。 25 | 26 | 关键在于如何x取得各位,即最高位high和最低位low。设x=1234321 27 | 28 | 1. 最低位容易`low = x % 10 = 1234321 % 10 = 1`; 29 | 2. 最高位就是除以N = 10n-1,n为x的位数,等于7, 即`high = x / 1000000 = 1`; 30 | 3. 显然若`low != high` 返回`false`,否则`low == high`, 此时要把x的最高位和最低位去掉,得到23432.方法是:去掉最高位x %= N, 然后去掉最低位 x /= 10. 31 | 4. 回到1,直到x=0. 32 | 33 | ## Code 34 | ```c 35 | bool isPalindrome(int x) 36 | { 37 | if (x < 0) 38 | return false; 39 | int len = 1; 40 | for (; x / len >= 10; len *= 10); 41 | while (x) { 42 | int high = x / len; 43 | int low = x % 10; 44 | if (low != high) 45 | return false; 46 | x = (x % len) / 10; 47 | len /= 100; 48 | } 49 | return true; 50 | } 51 | ``` 52 | -------------------------------------------------------------------------------- /algorithms/PalindromeNumber/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | bool isPalindrome(int x) 5 | { 6 | if (x < 0) 7 | return false; 8 | int len = 1; 9 | for (; x / len >= 10; len *= 10); 10 | while (x) { 11 | int high = x / len; 12 | int low = x % 10; 13 | if (low != high) 14 | return false; 15 | x = (x % len) / 10; 16 | len /= 100; 17 | } 18 | return true; 19 | } 20 | int main(int argc, char **argv) 21 | { 22 | int x; 23 | while (scanf("%d", &x) != EOF) 24 | printf("%d\n", isPalindrome(x)); 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /algorithms/PartitionList/in.txt: -------------------------------------------------------------------------------- 1 | 5 5 2 | 1 2 3 4 5 3 | 6 3 4 | 6 5 4 3 2 1 5 | 6 3 6 | 1 2 3 4 5 6 7 | 6 3 8 | 1 4 3 2 5 2 9 | 6 8 10 | 1 2 3 4 5 6 11 | 6 8 12 | 6 5 4 3 2 1 13 | 5 1 14 | 1 2 3 4 5 15 | 5 0 16 | 1 2 3 4 5 17 | 5 6 18 | 1 2 3 4 5 19 | -------------------------------------------------------------------------------- /algorithms/PascalsTriangle/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | class Solution { 9 | public: 10 | vector> generate(int n) { 11 | vector> result; 12 | for (int i = 0; i < n; ++i) { 13 | result.push_back(vector(i + 1, 0)); 14 | result[i][0] = result[i][i] = 1; 15 | for (int j = 1; j < i; ++j) { 16 | result[i][j] = result[i - 1][j - 1] + result[i - 1][j]; 17 | } 18 | } 19 | return result; 20 | } 21 | }; 22 | void print(vector> v) { 23 | for (auto i : v) { 24 | for_each(begin(i), end(i), [](int i){cout << i << ' ';}); 25 | cout << endl; 26 | } 27 | } 28 | int main(int argc, char **argv) 29 | { 30 | Solution solution; 31 | int n; 32 | while (scanf("%d", &n) != EOF) { 33 | print(solution.generate(n)); 34 | } 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /algorithms/PathSum/README.md: -------------------------------------------------------------------------------- 1 | ## Path Sum 2 | 3 | Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. 4 | 5 | For example: 6 | Given the below binary tree and `sum = 22`, 7 | ``` 8 | 5 9 | / \ 10 | 4 8 11 | / / \ 12 | 11 13 4 13 | / \ \ 14 | 7 2 1 15 | ``` 16 | return true, as there exist a root-to-leaf path `5->4->11->2` which sum is 22. 17 | 18 | ## Solution 19 | 20 | 递归题 21 | 22 | * 如果p是叶子节点,则若`p的值等于sum`,`return true`, 否则`return false` 23 | * 若p不是叶子节点,则一定存在孩子节点,左孩子或者右孩子满足其中一个和为`sum - p->val`即可,即 24 | `return hasPath(p->left, sum - p->val) || hasPath(p->right, sum - p->right)` 25 | 26 | ## Code 27 | ```c 28 | bool hasPathSum(struct TreeNode *root, int sum) { 29 | if (root == NULL) 30 | return false; 31 | if (root->left == NULL && root->right == NULL) 32 | return root->val == sum; 33 | if (!root->left || !hasPathSum(root->left, sum - root->val)) { 34 | return hasPathSum(root->right, sum - root->val); 35 | } 36 | return true; 37 | } 38 | ``` 39 | 40 | ## 扩展 41 | 42 | 见[Path Sum II](../PathSum2). 43 | -------------------------------------------------------------------------------- /algorithms/PathSum2/README.md: -------------------------------------------------------------------------------- 1 | ## Path Sum II 2 | 3 | Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. 4 | 5 | For example: 6 | Given the below binary tree and `sum = 22`, 7 | ``` 8 | 5 9 | / \ 10 | 4 8 11 | / / \ 12 | 11 13 4 13 | / \ / \ 14 | 7 2 5 1 15 | ``` 16 | return 17 | ``` 18 | [ 19 | [5,4,11,2], 20 | [5,8,4,5] 21 | ] 22 | ``` 23 | 24 | 这题和[Path Sum I](../PathSum)一样使用前序遍历的方法,不过遍历的同时需要保存当前的值。 25 | 26 | 设当前访问的节点为p,已访问的节点保存于cur, 结果集result, 目标值sum 27 | 28 | * 若p是空节点,直接返回 29 | * p值压入cur,`sum -= p->val` 30 | * 若p是叶子节点,并且`sum == 0`, 把cur压入result结果集中 31 | * 否则p不是叶子节点,递归探测左孩子、右孩子. 32 | 33 | ## Code 34 | ```cpp 35 | void pathSum(vector> &result, vector cur, TreeNode *root, int sum) { 36 | if (root == NULL) 37 | return; 38 | cur.push_back(root->val); 39 | sum -= root->val; 40 | if (isLeft(root) && sum == 0) { 41 | result.push_back(cur); 42 | return; 43 | } 44 | pathSum(result, cur, root->left, sum); 45 | pathSum(result, cur, root->right, sum); 46 | } 47 | ``` 48 | -------------------------------------------------------------------------------- /algorithms/PermutationSequence/README.md: -------------------------------------------------------------------------------- 1 | ## Permutation Sequence 2 | 3 | The set [1,2,3,…,n] contains a total of n! unique permutations. 4 | 5 | By listing and labeling all of the permutations in order, 6 | We get the following sequence (ie, for n = 3): 7 | ``` 8 | "123" 9 | "132" 10 | "213" 11 | "231" 12 | "312" 13 | "321" 14 | ``` 15 | Given n and k, return the kth permutation sequence. 16 | 17 | **Note: Given n will be between 1 and 9 inclusive.** 18 | 19 | ## Solution 20 | 21 | 求康托展开式,具体算法见[康托展开算法](https://github.com/krystism/algorithms/tree/master/cantor) 22 | 23 | 由于是求第k个排列,而康托展开求的是根据比它小的数量,因此需要k减一 24 | 25 | ## Code 26 | 27 | ```c 28 | char *listRemove(char *s, int i) 29 | { 30 | int n = strlen(s), j; 31 | for (j = i; j < n - 1; ++j) 32 | s[j] = s[j + 1]; 33 | s[j] = 0; 34 | return s; 35 | } 36 | char *getPermutation(int n, int k) { 37 | char *ans = malloc(sizeof(char) * (n + 1)); 38 | char *nums = malloc(sizeof(char) * n); 39 | const int FAC[] = {1,1,2,6,24,120,720,5040,40320,362880}; 40 | for (int i = 0; i < n; ++i) 41 | nums[i] = '0' + i + 1; 42 | k--; 43 | int cur = 0; 44 | for (int i = n - 1; i > 0; --i) { 45 | int index = k / FAC[i]; 46 | k %= FAC[i]; 47 | ans[cur++] = nums[index]; 48 | listRemove(nums, index); 49 | } 50 | ans[cur++] = nums[0]; 51 | ans[cur] = 0; 52 | free(nums); 53 | return ans; 54 | } 55 | ``` 56 | -------------------------------------------------------------------------------- /algorithms/PermutationSequence/permutationSequence.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | char *listRemove(char *s, int i) 5 | { 6 | int n = strlen(s), j; 7 | for (j = i; j < n - 1; ++j) 8 | s[j] = s[j + 1]; 9 | s[j] = 0; 10 | return s; 11 | } 12 | char *getPermutation(int n, int k) { 13 | char *ans = malloc(sizeof(char) * (n + 1)); 14 | char *nums = malloc(sizeof(char) * n); 15 | const int FAC[] = {1,1,2,6,24,120,720,5040,40320,362880}; 16 | for (int i = 0; i < n; ++i) 17 | nums[i] = '0' + i + 1; 18 | k--; 19 | int cur = 0; 20 | for (int i = n - 1; i > 0; --i) { 21 | int index = k / FAC[i]; 22 | k %= FAC[i]; 23 | ans[cur++] = nums[index]; 24 | listRemove(nums, index); 25 | } 26 | ans[cur++] = nums[0]; 27 | ans[cur] = 0; 28 | free(nums); 29 | return ans; 30 | } 31 | int main(int argc, char **argv) 32 | { 33 | for (int i = 1; i <= 6; ++i) 34 | printf("%s\n", getPermutation(3, i)); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /algorithms/Permutations/README.md: -------------------------------------------------------------------------------- 1 | ## Permutations 2 | 3 | Given a collection of numbers, return all possible permutations. 4 | 5 | For example, 6 | [1,2,3] have the following permutations: 7 | [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], and [3,2,1]. 8 | 9 | ## Solution 10 | 11 | 全排列, [从一个排列求下一个排列算法](https://github.com/krystism/algorithms/tree/master/permutation) 12 | 13 | ## Code 14 | ```cpp 15 | class Solution { 16 | public: 17 | vector > permute(vector &num) { 18 | vector> ans; 19 | sort(num.begin(), num.end()); 20 | do { 21 | vector v(num.begin(), num.end()); 22 | ans.push_back(v); 23 | } while(next(num)); 24 | return ans; 25 | } 26 | private: 27 | bool next(vector &v) { 28 | size_t n = v.size(); 29 | int i; 30 | for (i = n - 2; i >= 0 && v[i] >= v[i + 1]; --i); 31 | if (i < 0) { 32 | reverse(v.begin(), v.end()); 33 | return false; 34 | } 35 | int j; 36 | for (j = n - 1; j > i && v[j] <= v[i]; --j); 37 | swap(v[i], v[j]); 38 | reverse(v.begin() + i + 1, v.end()); 39 | return true; 40 | } 41 | 42 | }; 43 | ``` 44 | -------------------------------------------------------------------------------- /algorithms/Permutations/permutations.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | void print(vector v) 7 | { 8 | for (auto i : v) 9 | printf("%d ", i); 10 | printf("\n"); 11 | } 12 | class Solution { 13 | public: 14 | vector > permute(vector &num) { 15 | vector> ans; 16 | sort(num.begin(), num.end()); 17 | do { 18 | vector v(num.begin(), num.end()); 19 | ans.push_back(v); 20 | } while(next(num)); 21 | return ans; 22 | } 23 | private: 24 | bool next(vector &v) { 25 | size_t n = v.size(); 26 | int i; 27 | for (i = n - 2; i >= 0 && v[i] >= v[i + 1]; --i); 28 | if (i < 0) { 29 | reverse(v.begin(), v.end()); 30 | return false; 31 | } 32 | int j; 33 | for (j = n - 1; j > i && v[j] <= v[i]; --j); 34 | swap(v[i], v[j]); 35 | reverse(v.begin() + i + 1, v.end()); 36 | return true; 37 | } 38 | 39 | }; 40 | int main(int argc, char **argv) 41 | { 42 | Solution solution; 43 | vector num = {1,2,3, 4, 5}; 44 | vector> ans = solution.permute(num); 45 | for (auto i : ans) 46 | print(i); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /algorithms/Permutations2/README.md: -------------------------------------------------------------------------------- 1 | ## Permutations II 2 | 3 | Given a collection of numbers that might contain duplicates, return all possible unique permutations. 4 | 5 | For example, 6 | `[1,1,2]` have the following unique permutations: 7 | `[1,1,2]`, `[1,2,1]`, and `[2,1,1]`. 8 | 9 | ## Solution 10 | 11 | 全排列, [从一个排列求下一个排列算法](https://github.com/krystism/algorithms/tree/master/permutation) 12 | 13 | ## Code 14 | ```cpp 15 | class Solution { 16 | public: 17 | vector > permuteUnique(vector &num) { 18 | vector> ans; 19 | sort(num.begin(), num.end()); 20 | do { 21 | vector v(num.begin(), num.end()); 22 | ans.push_back(v); 23 | } while(next(num)); 24 | return ans; 25 | } 26 | private: 27 | bool next(vector &v) { 28 | size_t n = v.size(); 29 | int i; 30 | for (i = n - 2; i >= 0 && v[i] >= v[i + 1]; --i); 31 | if (i < 0) { 32 | reverse(v.begin(), v.end()); 33 | return false; 34 | } 35 | int j; 36 | for (j = n - 1; j > i && v[j] <= v[i]; --j); 37 | swap(v[i], v[j]); 38 | reverse(v.begin() + i + 1, v.end()); 39 | return true; 40 | } 41 | 42 | }; 43 | ``` 44 | -------------------------------------------------------------------------------- /algorithms/PlusOne/README.md: -------------------------------------------------------------------------------- 1 | ## Plus One 2 | 3 | Given a non-negative number represented as an array of digits, plus one to the number. 4 | 5 | The digits are stored such that the most significant digit is at the head of the list. 6 | 7 | ## Solution 8 | 9 | 直接从最后开始,处理进位 10 | ```cpp 11 | vector plusOne(vector &digits) { 12 | int i = digits.size() - 1; 13 | if (i < 0) { 14 | digits.push_back(1); 15 | return digits; 16 | } 17 | bool carry = true; 18 | while (i >= 0 && carry) { 19 | digits[i] += 1; 20 | if (digits[i] > 9) { 21 | digits[i] -= 10; 22 | carry = true; 23 | } else { 24 | carry = false; 25 | } 26 | i--; 27 | } 28 | if (carry) { 29 | digits.insert(digits.begin(), 1); 30 | } 31 | return digits; 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /algorithms/PlusOne/in.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 9 3 | 2 4 | 9 9 5 | 3 6 | 1 0 0 7 | 4 8 | 1 1 1 1 9 | 4 10 | 1 2 9 9 11 | -------------------------------------------------------------------------------- /algorithms/PlusOne/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | vector plusOne(vector &digits) { 9 | int i = digits.size() - 1; 10 | if (i < 0) { 11 | digits.push_back(1); 12 | return digits; 13 | } 14 | bool carry = true; 15 | while (i >= 0 && carry) { 16 | digits[i] += 1; 17 | if (digits[i] > 9) { 18 | digits[i] -= 10; 19 | carry = true; 20 | } else { 21 | carry = false; 22 | } 23 | i--; 24 | } 25 | if (carry) { 26 | digits.insert(digits.begin(), 1); 27 | } 28 | return digits; 29 | } 30 | }; 31 | int main(int argc, char **argv) 32 | { 33 | int n; 34 | vector v; 35 | Solution solution; 36 | while (cin >> n) { 37 | v.clear(); 38 | for (int i = 0; i < n; ++i) { 39 | int value; 40 | cin >> value; 41 | v.push_back(value); 42 | } 43 | for_each(v.begin(), v.end(), [](int i){cout << i;}); 44 | cout << " + 1 = "; 45 | auto result = solution.plusOne(v); 46 | for_each(result.begin(), result.end(), [](int i){cout << i;}); 47 | cout << endl; 48 | } 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /algorithms/Pow/in.txt: -------------------------------------------------------------------------------- 1 | 1.00000, -2147483648 2 | -------------------------------------------------------------------------------- /algorithms/Pow/pow.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | const double ERROR = 1e-8; 8 | int doubleEQ(double x, double y) 9 | { 10 | return fabs(x - y) < ERROR; 11 | } 12 | double myPow(double x, int n) 13 | { 14 | if (n == 0) { 15 | return 1; 16 | } 17 | if (n == 1) 18 | return x; 19 | if (n == -1) { 20 | if (fabs(x - 0) < ERROR) { // x位0 1/0 没有意义 21 | return INT_MAX; 22 | } 23 | return 1.0 / x; 24 | } 25 | if (doubleEQ(x, 0)){ 26 | return 0; 27 | } 28 | if (doubleEQ(x, 1)) { 29 | return 1; 30 | } 31 | if (doubleEQ(x, -1)) { 32 | if ((n & 0x1)) 33 | return -1; 34 | else return 1; 35 | } 36 | if ((n & 0x1)) { 37 | int mid = (n - 1) / 2; 38 | double half = myPow(x, mid); 39 | return half * half * x; 40 | } else { 41 | double half = myPow(x, n / 2); 42 | return half * half; 43 | } 44 | } 45 | int main(int argc, char **argv) 46 | { 47 | double x; 48 | int n; 49 | while (scanf("%lf%d", &x, &n)) { 50 | printf("%lf\n", myPow(x, n)); 51 | } 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /algorithms/PowerofTwo/README.md: -------------------------------------------------------------------------------- 1 | ## Power of Two 2 | 3 | Given an integer, write a function to determine if it is a power of two. 4 | 5 | Credits: 6 | Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases. 7 | 8 | ## Solution 9 | 10 | 位运算,一个数是2的幂,则它的二进制1的个数等于1 11 | 12 | 求一个数二进制的1的个数的方法是不断地`n &= (n - 1)`,直到n为0 13 | 14 | 考虑以下两种情况: 15 | 16 | * `n == 0`, 此时`n & (n - 1) == 0`, 但不是2的幂 17 | * `n=-2147483648`,此时二进制1的个数也等于1,但它不是2的幂 18 | 19 | 综合可以得出:只要`n <= 0`, 就一定不是2的幂。 20 | 21 | 因此最后解决方案为: 22 | 23 | ```c 24 | bool isPowerOfTwo(int n) 25 | { 26 | if (n <= 0) 27 | return false; 28 | return !(n & (n - 1)); 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /algorithms/PowerofTwo/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | bool isPowerOfTwo(int n) 5 | { 6 | if (n <= 0) 7 | return false; 8 | return !(n & (n - 1)); 9 | } 10 | int main(int argc, char **argv) 11 | { 12 | int n; 13 | while (scanf("%d", &n) != EOF) { 14 | printf("%d\n", isPowerOfTwo(n)); 15 | } 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /algorithms/RegularExpressionMatching/in.txt: -------------------------------------------------------------------------------- 1 | aa a 2 | aa aa 3 | aaa aa 4 | aa a* 5 | aa .* 6 | ab .* 7 | aab c*a*b 8 | e a*b*c*d*e 9 | ab .*c 10 | ab .*ab 11 | aabc .*a 12 | -------------------------------------------------------------------------------- /algorithms/RegularExpressionMatching/match.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | bool isMatch(char *s,char *p) 7 | { 8 | if (*p == '\0') // p为空 9 | return *s == '\0'; 10 | if (*(p + 1) == '\0' || *(p + 1) != '*') { 11 | if (*s == '\0' || (*p != '.' && *s != *p)) 12 | return false; 13 | return isMatch(s + 1, p + 1); 14 | } 15 | int i = -1, len = strlen(s); 16 | while (i < len && (i < 0 || *p == '.' || *(s + i) == *p)) { 17 | if (isMatch(s + i + 1, p + 2)) 18 | return true; 19 | i++; 20 | } 21 | return false; 22 | } 23 | int main(int argc, char **argv) 24 | { 25 | char a[20], p[20]; 26 | while (scanf("%s%s", a, p) != EOF) { 27 | if (isMatch(a, p)) 28 | printf("%s %s -> true\n", a, p); 29 | else 30 | printf("%s %s -> false\n",a, p); 31 | } 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /algorithms/RemoveDuplicatesfromSortedArray/README.md: -------------------------------------------------------------------------------- 1 | ## Remove Duplicates from Sorted Array 2 | Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length. 3 | 4 | Do not allocate extra space for another array, you must do this in place with constant memory. 5 | 6 | For example, 7 | ``` 8 | Given input array A = [1,1,2], 9 | 10 | Your function should return length = 2, and A is now [1,2]. 11 | ``` 12 | 13 | ## Solution 14 | ```c 15 | int removeDuplicates(int a[], int n) { 16 | int i, j; 17 | if (n == 0) 18 | return 0; 19 | for (i = 1, j = 0; i < n; ++i) { 20 | if (a[i] != a[i - 1]) { 21 | a[++j] = a[i]; 22 | } 23 | } 24 | return j + 1; 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /algorithms/RemoveDuplicatesfromSortedArray/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | int removeDuplicates(int a[], int n) { 3 | int i, j; 4 | if (n == 0) 5 | return 0; 6 | for (i = 1, j = 0; i < n; ++i) { 7 | if (a[i] != a[i - 1]) { 8 | a[++j] = a[i]; 9 | } 10 | } 11 | return j + 1; 12 | } 13 | void print(int a[], int n) 14 | { 15 | for (int i = 0; i < n; ++i) 16 | printf("%d ", a[i]); 17 | printf("\n"); 18 | } 19 | int main(int argc, char **argv) 20 | { 21 | int a[] = {1,1,1,2,2,3}; 22 | int n = removeDuplicates(a, 0); 23 | print(a, n); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /algorithms/RemoveDuplicatesfromSortedList/README.md: -------------------------------------------------------------------------------- 1 | ## Remove Duplicates from Sorted List 2 | 3 | Given a sorted linked list, delete all duplicates such that each element appear only once. 4 | 5 | For example, 6 | Given `1->1->2`, return `1->2`. 7 | Given `1->1->2->3->3`, return `1->2->3`. 8 | 9 | ## Solution 10 | 11 | 设p指向当前节点,初始化为`p = head`, `q = p->next`, 则: 12 | 13 | * 若q为null,则说明已到达尾部节点,直接返回 14 | * 若`q->val != p->val`, 更新p节点, `p = p->next` 15 | * 否则删除q节点,即`p->next = p->next->next; free(q)` 16 | 17 | ```c 18 | struct ListNode* deleteDuplicates(struct ListNode *head) 19 | { 20 | struct ListNode *p = head; 21 | while (p) { 22 | struct ListNode *q = p->next; 23 | if (q && p->val == q->val) { 24 | p->next = p->next->next; 25 | free(q); 26 | } else 27 | p = p->next; 28 | } 29 | return head; 30 | } 31 | ``` 32 | 33 | ## 扩展 34 | 35 | 删除所有的重复节点[Remove Duplicates from Sorted List II](../RemoveDuplicatesfromSortedList2) 36 | -------------------------------------------------------------------------------- /algorithms/RemoveElement/README.md: -------------------------------------------------------------------------------- 1 | ## Remove Element 2 | 3 | Given an array and a value, remove all instances of that value in place and return the new length. 4 | 5 | The order of elements can be changed. It doesn't matter what you leave beyond the new length. 6 | 7 | ## Solution 8 | 遍历数组,并逐一原地拷贝不等于key的元素 9 | ```cpp 10 | int removeElement(int a[], int n, int key) 11 | { 12 | int k = 0; 13 | for (int i = 0; i < n; ++i) { 14 | if (a[i] != key) 15 | a[k++] = a[i]; 16 | } 17 | return k; 18 | } 19 | ``` 20 | -------------------------------------------------------------------------------- /algorithms/RemoveElement/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int removeElement(int a[], int n, int key) 5 | { 6 | int k = 0; 7 | for (int i = 0; i < n; ++i) { 8 | if (a[i] != key) 9 | a[k++] = a[i]; 10 | } 11 | return k; 12 | } 13 | int main(int argc, char **argv) 14 | { 15 | int a[] = {1,2,3,2,3,2,1,6,2}; 16 | int n = removeElement(a, 9, 2); 17 | for (int i = 0; i < n; ++i) 18 | printf("%d ", a[i]); 19 | printf("\n"); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /algorithms/RemoveLinkedListElements/README.md: -------------------------------------------------------------------------------- 1 | ## Remove Linked List Elements 2 | 3 | Remove all elements from a linked list of integers that have value val. 4 | 5 | Example 6 | ``` 7 | Given: 1 --> 2 --> 6 --> 3 --> 4 --> 5 --> 6, val = 6 8 | Return: 1 --> 2 --> 3 --> 4 --> 5 9 | ``` 10 | 11 | Credits: 12 | Special thanks to @mithmatt for adding this problem and creating all test cases. 13 | 14 | ## Solution 15 | 16 | * 先处理头部,如果头部就是要删除的值,直接让头部指向下一个节点,并释放原来的头部 17 | ```c 18 | while (head && head->val == val) { 19 | struct ListNode *q = p->next; 20 | free(head); 21 | head = q; 22 | } 23 | ``` 24 | * 处理非头部节点,此时无需更新头部,只需要遍历等于删除值的节点即可。为了便于删除操作,判断后一个节点,若后一个节点值为删除值,则只需要删除后一个节点即可,否则指向下一个节点 25 | ```c 26 | struct ListNode *p = head; 27 | while (p) { 28 | struct ListNode *q = p->next; 29 | if (q && q->val == val) { 30 | p->next = q->next; 31 | free(q); 32 | } else { 33 | p = p->next; 34 | } 35 | } 36 | ``` 37 | 38 | ## Code 39 | ```c 40 | struct ListNode *removeElements(struct ListNode *head, int val) 41 | { 42 | struct ListNode *p =head; 43 | while (p && p->val == val) { 44 | struct ListNode *q = p->next; 45 | free(p); 46 | p = q; 47 | head = q; 48 | } 49 | while (p) { 50 | struct ListNode *q = p->next; 51 | if (q && q->val == val) { 52 | p->next = q->next; 53 | free(q); 54 | } else { 55 | p = p->next; 56 | } 57 | } 58 | return head; 59 | } 60 | ``` 61 | -------------------------------------------------------------------------------- /algorithms/RemoveLinkedListElements/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | struct ListNode { 5 | int val; 6 | struct ListNode *next; 7 | }; 8 | struct ListNode *removeElements(struct ListNode *head, int val) 9 | { 10 | struct ListNode *p =head; 11 | while (p && p->val == val) { 12 | struct ListNode *q = p->next; 13 | free(p); 14 | p = q; 15 | head = q; 16 | } 17 | while (p) { 18 | struct ListNode *q = p->next; 19 | if (q && q->val == val) { 20 | p->next = q->next; 21 | free(q); 22 | } else { 23 | p = p->next; 24 | } 25 | } 26 | return head; 27 | } 28 | void print(struct ListNode *head) 29 | { 30 | struct ListNode *p = head; 31 | if (p == NULL) { 32 | printf("NULL\n"); 33 | return; 34 | } 35 | while (p) { 36 | printf("%d ", p->val); 37 | p = p->next; 38 | } 39 | printf("\n"); 40 | } 41 | struct ListNode * mk_list(struct ListNode **ha, int a[], int n) 42 | { 43 | struct ListNode *p = malloc(sizeof(*p)); 44 | p->val = a[0]; 45 | p->next = NULL; 46 | *ha = p; 47 | for (int i = 1; i < n; ++i) { 48 | struct ListNode *q = malloc(sizeof(*q)); 49 | q->val = a[i]; 50 | q->next = NULL; 51 | p->next = q; 52 | p = q; 53 | } 54 | return p; 55 | } 56 | int main(int argc, char **argv) 57 | { 58 | struct ListNode *head; 59 | int a[] = {1,2,2,1}; 60 | mk_list(&head, a, 4); 61 | print(head); 62 | head = removeElements(head, 2); 63 | print(head); 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /algorithms/RemoveNthNodeFromEndofList/README.md: -------------------------------------------------------------------------------- 1 | ## Remove Nth Node From End of List 2 | 3 | Given a linked list, remove the nth node from the end of list and return its head. 4 | 5 | For example, 6 | ``` 7 | Given linked list: 1->2->3->4->5, and n = 2. 8 | 9 | After removing the second node from the end, the linked list becomes 1->2->3->5. 10 | ``` 11 | Note: 12 | 13 | * Given n will always be valid. 14 | * Try to do this in one pass. 15 | 16 | ## Solution 17 | 18 | 要求只遍历一趟,只需要让两个指针p, q,p先走n步,然后p,q一起走,直到p到达链表结尾,此时q就是需要删除的节点. 19 | -------------------------------------------------------------------------------- /algorithms/ReorderList/in.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 1 3 | 2 4 | 1 2 5 | 3 6 | 1 2 3 7 | 4 8 | 1 2 3 4 9 | 5 10 | 1 2 3 4 5 11 | 6 12 | 1 2 3 4 5 6 13 | -------------------------------------------------------------------------------- /algorithms/ReverseBits/README.md: -------------------------------------------------------------------------------- 1 | ## Reverse Bits 2 | 3 | Reverse bits of a given 32 bits unsigned integer. 4 | 5 | For example, given input `43261596` (represented in binary as `00000010100101000001111010011100`), return `964176192` (represented in binary as `00111001011110000010100101000000`). 6 | 7 | Follow up: 8 | If this function is called many times, how would you optimize it? 9 | 10 | Related problem: Reverse Integer 11 | 12 | Credits: 13 | Special thanks to @ts for adding this problem and creating all test cases. 14 | 15 | ## Solution 16 | 17 | 位运算 18 | 19 | ## Code 20 | ```c 21 | uint32_t reverseBits(uint32_t n) { 22 | uint32_t m = 0; 23 | for (int i = 0; i < 31; ++i) { 24 | m |= (n & 0x1); 25 | m <<= 1; 26 | n >>= 1; 27 | } 28 | return m | (n & 0x1); 29 | } 30 | ``` 31 | -------------------------------------------------------------------------------- /algorithms/ReverseBits/in.txt: -------------------------------------------------------------------------------- 1 | 43261596 2 | 1 3 | 0 4 | 268435456 5 | -------------------------------------------------------------------------------- /algorithms/ReverseBits/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | uint32_t reverseBits(uint32_t n) { 5 | uint32_t m = 0; 6 | for (int i = 0; i < 31; ++i) { 7 | m |= (n & 0x1); 8 | m <<= 1; 9 | n >>= 1; 10 | } 11 | return m | (n & 0x1); 12 | } 13 | int main(int argc, char **argv) 14 | { 15 | uint32_t i; 16 | while (scanf("%u", &i) != EOF) { 17 | printf("%x = %x\n", i, reverseBits(i)); 18 | } 19 | return 0; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /algorithms/ReverseInteger/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int reverse(int x) 5 | { 6 | int sign = 0, ans = 0; 7 | const int BOUND = INT_MAX / 10; 8 | if (x == -2147483648) 9 | return 0; 10 | if (x < 0) { 11 | x = -x; 12 | sign = 1; 13 | } 14 | while (x) { 15 | ans *= 10; 16 | ans += x % 10; 17 | x /= 10; 18 | if (ans >= BOUND) 19 | break; 20 | } 21 | if (x == 0) 22 | return sign ? -ans : ans; 23 | if (ans > BOUND) // 此时乘以10,无论如何都要溢出 24 | return 0; 25 | if (sign && x == 8) // 刚好是最大的负数,其实这种情况不可能出现 26 | return -2147483648; 27 | if (x > 7) // ans已经等于INT_MAX / 10,如果个位大于7溢出. 28 | return 0; 29 | ans *= 10; 30 | ans += x; // 此时一定是2147483641 31 | return sign ? -ans : ans; 32 | } 33 | int main(int argc, char **argv) 34 | { 35 | int x; 36 | printf("%d\n", INT_MAX); 37 | while(scanf("%d", &x) != EOF) 38 | printf("%d\n", reverse(x)); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /algorithms/ReverseInteger/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int reverse(int x) 5 | { 6 | int sign = 0, ans = 0; 7 | if (x < 0) { 8 | x = -x; 9 | sign = 1; 10 | } 11 | while (x) { 12 | ans *= 10; 13 | ans += x % 10; 14 | x /= 10; 15 | } 16 | return sign ? -ans : ans; 17 | } 18 | int main(int argc, char **argv) 19 | { 20 | printf("%d\n", INT_MAX); 21 | } 22 | -------------------------------------------------------------------------------- /algorithms/ReverseLinkedList/README.md: -------------------------------------------------------------------------------- 1 | ## Reverse Linked List 2 | 3 | Reverse a singly linked list. 4 | 5 | click to show more hints. 6 | Hint: 7 | 8 | A linked list can be reversed either iteratively or recursively. Could you implement both? 9 | 10 | ## Solution 11 | 12 | 迭代法: 13 | 14 | ```cpp 15 | ListNode *reverseIteratively(ListNode *head) { 16 | if (!head || !head->next) 17 | return head; 18 | ListNode *prev = nullptr, *p = head; 19 | while (p) { 20 | ListNode *q = p->next; 21 | p->next = prev; 22 | prev = p; 23 | p = q; 24 | } 25 | return prev; 26 | } 27 | ``` 28 | 29 | 递归法,注意更新head指针: 30 | 31 | ```cpp 32 | ListNode *reverseRecursively(ListNode *&head, ListNode *p) { 33 | if (!p|| !p->next) { 34 | head = p; 35 | return head; 36 | } 37 | reverseRecursively(head, p->next)->next = p; 38 | p->next = nullptr; 39 | return p; 40 | } 41 | ``` 42 | 43 | ## 扩展 44 | 45 | [Reverse Linked List II](../ReverseLinkedListII): 逆转指定的区间 46 | -------------------------------------------------------------------------------- /algorithms/ReverseLinkedListII/README.md: -------------------------------------------------------------------------------- 1 | ## Reverse Linked List II 2 | 3 | Reverse a linked list from position m to n. Do it in-place and in one-pass. 4 | 5 | For example: 6 | Given `1->2->3->4->5->NULL`, `m = 2` and `n = 4`, 7 | 8 | return `1->4->3->2->5->NULL`. 9 | 10 | Note: 11 | Given `m, n` satisfy the following condition: 12 | `1 ≤ m ≤ n ≤` length of list. 13 | 14 | ## Solution 15 | 16 | 先实现给定start和end逆转: 17 | 18 | ```cpp 19 | void reverse(ListNode *start, ListNode *end) { 20 | if (!start || !start->next) 21 | return; 22 | ListNode *pre = nullptr; 23 | ListNode *p = start; 24 | while (p && pre != end) { 25 | ListNode *q = p->next; 26 | p->next = pre; 27 | pre = p; 28 | p = q; 29 | } 30 | start->next = p; // 注意最后需要更新start为end的next节点 31 | } 32 | ``` 33 | 34 | 然后只需要定位这个两个指针即可 35 | 36 | ```cpp 37 | ListNode *start = head; 38 | ListNode *end = head; 39 | ListNode *prev = nullptr; // 保存前一个节点,因为reverse后需要指向end节点 40 | while (--m) { 41 | prev = start; 42 | start = start->next; 43 | end = end->next; 44 | n--; 45 | } 46 | while (--n) { 47 | end = end->next; 48 | } 49 | ``` 50 | 51 | 调用`reverse(start, end)`即可 52 | 53 | 最后如果start是head节点,则需要更新head为end节点,否则更新prev节点指向end 54 | 55 | ```cpp 56 | if (prev) 57 | prev->next = end; 58 | else 59 | head = end; 60 | ``` 61 | 62 | ## 扩展 63 | 64 | [Reverse Linked List](../ReverseLinkedList): 逆转整个链表,实现了递归法和迭代法 65 | -------------------------------------------------------------------------------- /algorithms/RomantoInteger/README.md: -------------------------------------------------------------------------------- 1 | ## Roman to Integer 2 | 3 | Given a roman numeral, convert it to an integer. 4 | 5 | Input is guaranteed to be within the range from 1 to 3999. 6 | 7 | ## Solution 8 | 9 | 罗马数字转换参考[12 Integer to Roman](../IntegertoRoman),我们首先建立一个静态表: 10 | 11 | ```cpp 12 | unordered_map ROMAN_TABLE = { 13 | {'I', 1}, 14 | {'V', 5}, 15 | {'X', 10}, 16 | {'L', 50}, 17 | {'C', 100}, 18 | {'D', 500}, 19 | {'M', 1000} 20 | }; 21 | ``` 22 | 23 | 由转化规则可知: 24 | 25 | * 当罗马数字当前值比前面值大时,需要减去前面的值,比如IV,前面时1,后面时5,需要减去前面的值,结果为4,因此左减至多一位,因此不会出现减两位数的情况。 26 | * 当当前值比前面的小时,需要加上当前的值。比如VI, 当前为1,前面为5,则结果为6。 27 | 28 | ```cpp 29 | int romanToInt(string s) { 30 | int pre = ROMAN_TABLE[s[0]]; 31 | int sum = pre; 32 | for (int i = 1; i < s.size(); ++i) { 33 | int cur = ROMAN_TABLE[s[i]]; 34 | sum += cur; 35 | if (cur > pre) { 36 | sum -= 2 * pre; // 原来是+,需要转化为-,因此减去两倍 37 | } 38 | pre = cur; 39 | } 40 | return sum; 41 | } 42 | ``` 43 | 44 | ## 参考 45 | 46 | 1. [12 Integer to Roman](../IntegertoRoman) 47 | -------------------------------------------------------------------------------- /algorithms/RomantoInteger/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | class Solution { 6 | public: 7 | int romanToInt(string s) { 8 | int pre = ROMAN_TABLE[s[0]]; 9 | int sum = pre; 10 | for (int i = 1; i < s.size(); ++i) { 11 | int cur = ROMAN_TABLE[s[i]]; 12 | sum += cur; 13 | if (cur > pre) { 14 | sum -= 2 * pre; // 原来是+,需要转化为-,因此减去两倍 15 | } 16 | pre = cur; 17 | } 18 | return sum; 19 | } 20 | private: 21 | unordered_map ROMAN_TABLE = { 22 | {'I', 1}, 23 | {'V', 5}, 24 | {'X', 10}, 25 | {'L', 50}, 26 | {'C', 100}, 27 | {'D', 500}, 28 | {'M', 1000} 29 | }; 30 | }; 31 | int main(int argc, char **argv) 32 | { 33 | Solution solution; 34 | string s; 35 | while (cin >> s) { 36 | cout << solution.romanToInt(s) << endl; 37 | } 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /algorithms/RotateArray/README.md: -------------------------------------------------------------------------------- 1 | ## Rotate Array 2 | 3 | Rotate an array of n elements to the right by k steps. 4 | 5 | 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]`. 6 | 7 | Note: 8 | Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem. 9 | 10 | Hint: 11 | 12 | Could you do it in-place with O(1) extra space? 13 | 14 | Related problem: Reverse Words in a String II 15 | 16 | ## Solution 17 | 18 | [列表旋转算法](https://github.com/krystism/algorithms/tree/master/rotate) 19 | 20 | ## Code 21 | ```c 22 | void swap(int *a, int *b) 23 | { 24 | if (a == NULL || b == NULL || a == b) 25 | return; 26 | *a ^= *b; 27 | *b ^= *a; 28 | *a ^= *b; 29 | } 30 | void reverse(int a[], int s, int t) 31 | { 32 | int i = s, j = t; 33 | while (i < j) 34 | { 35 | swap(&a[i++], &a[j--]); 36 | } 37 | } 38 | void rotate(int a[], int n, int k) 39 | { 40 | k %= n; 41 | reverse(a, 0, n - 1); 42 | reverse(a, 0, k - 1); 43 | reverse(a, k, n - 1); 44 | } 45 | ``` 46 | -------------------------------------------------------------------------------- /algorithms/RotateArray/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void swap(int *a, int *b) 6 | { 7 | if (a == NULL || b == NULL || a == b) 8 | return; 9 | *a ^= *b; 10 | *b ^= *a; 11 | *a ^= *b; 12 | } 13 | void reverse(int a[], int s, int t) 14 | { 15 | int i = s, j = t; 16 | while (i < j) 17 | { 18 | swap(&a[i++], &a[j--]); 19 | } 20 | } 21 | void rotate(int a[], int n, int k) 22 | { 23 | k %= n; 24 | reverse(a, 0, n - 1); 25 | reverse(a, 0, k - 1); 26 | reverse(a, k, n - 1); 27 | } 28 | int main(int argc, char **argv) 29 | { 30 | int a[] = {1,2,3,4,5,6,7}; 31 | rotate(a, 7, 3); 32 | for (int i = 0; i < 7; ++i) 33 | { 34 | printf("%d ", a[i]); 35 | } 36 | printf("\n"); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /algorithms/SameTree/README.md: -------------------------------------------------------------------------------- 1 | ## Same Tree 2 | 3 | Given two binary trees, write a function to check if they are equal or not. 4 | 5 | Two binary trees are considered equal if they are structurally identical and the nodes have the same value. 6 | 7 | ## Solution 8 | 9 | 递归 10 | 11 | ## Code 12 | ```c 13 | bool isSameTree(struct TreeNode *p, struct TreeNode *q) { 14 | if (p == NULL) 15 | return q == NULL; 16 | if (q == NULL) 17 | return false; 18 | if (p->val != q->val) 19 | return false; 20 | return isSameTree(p->left, q->left) && isSameTree(p->right, q->right); 21 | } 22 | ``` 23 | -------------------------------------------------------------------------------- /algorithms/SameTree/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | struct TreeNode { 6 | int val; 7 | struct TreeNode *left; 8 | struct TreeNode *right; 9 | }; 10 | bool isSameTree(struct TreeNode *p, struct TreeNode *q) { 11 | if (p == NULL) 12 | return q == NULL; 13 | if (q == NULL) 14 | return false; 15 | if (p->val != q->val) 16 | return false; 17 | return isSameTree(p->left, q->left) && isSameTree(p->right, q->right); 18 | } 19 | int main(int argc, char **argv) 20 | { 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /algorithms/SearchInsertPosition/README.md: -------------------------------------------------------------------------------- 1 | ## Search Insert Position 2 | 3 | Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order. 4 | 5 | You may assume no duplicates in the array. 6 | 7 | Here are few examples. 8 | ``` 9 | [1,3,5,6], 5 → 2 10 | [1,3,5,6], 2 → 1 11 | [1,3,5,6], 7 → 4 12 | [1,3,5,6], 0 → 0 13 | ``` 14 | 15 | ## Solution 16 | 17 | 二分搜索,若没有找到,则最后s == t, s即是需要插入的位置 18 | 19 | ## Code 20 | ```c 21 | int searchIndex(int A[], int n, int target) 22 | { 23 | if (A == NULL || n < 1) 24 | return 0; 25 | int s = 0, t = n - 1; 26 | while (s <= t) { 27 | int mid = (s + t) >> 1; 28 | if (A[mid] == target) 29 | return mid; 30 | if (A[mid] > target) { 31 | t = mid - 1; 32 | } else { 33 | s = mid + 1; 34 | } 35 | } 36 | return s; 37 | } 38 | ``` 39 | -------------------------------------------------------------------------------- /algorithms/SearchInsertPosition/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int searchInsert(int A[], int n, int target) 6 | { 7 | if (A == NULL || n < 1) 8 | return 0; 9 | int s = 0, t = n - 1; 10 | while (s <= t) { 11 | int mid = (s + t) >> 1; 12 | if (A[mid] == target) 13 | return mid; 14 | if (A[mid] > target) { 15 | t = mid - 1; 16 | } else { 17 | s = mid + 1; 18 | } 19 | } 20 | return s; 21 | } 22 | int main(int argc, char **argv) 23 | { 24 | int a[] = {1,3,5,6}; 25 | printf("%d\n", searchIndex(a, 4, 5)); 26 | printf("%d\n", searchIndex(a,4, 2)); 27 | printf("%d\n", searchIndex(a,4, 7)); 28 | printf("%d\n", searchIndex(a,4, 0)); 29 | printf("%d\n", searchIndex(a,4, 3)); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /algorithms/Searcha2DMatrix/in.txt: -------------------------------------------------------------------------------- 1 | 3 4 30 2 | 1 3 5 7 3 | 10 11 16 20 4 | 23 30 34 50 5 | 6 | 1 2 2 7 | 1 3 8 | -------------------------------------------------------------------------------- /algorithms/SearchforaRange/in.txt: -------------------------------------------------------------------------------- 1 | 5 8 2 | 1 2 3 4 8 3 | 5 8 4 | 1 8 8 8 10 5 | -------------------------------------------------------------------------------- /algorithms/SearchinRotatedSortedArray/in.txt: -------------------------------------------------------------------------------- 1 | 5 2 2 | 1 2 3 4 5 3 | -------------------------------------------------------------------------------- /algorithms/SearchinRotatedSortedArray/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int binarySearch(int *a, int s, int t, int key) 5 | { 6 | while (s <= t) { 7 | int mid = s + ((t - s) >> 1); 8 | if (a[mid] == key) 9 | return mid; 10 | if (a[mid] > key) 11 | t = mid - 1; 12 | else 13 | s = mid + 1; 14 | } 15 | return -1; 16 | } 17 | int search(int *a, int n, int key) 18 | { 19 | int s = 0, t = n - 1; 20 | while (s <= t) { 21 | if (a[s] < a[t]) 22 | return binarySearch(a, s, t, key); 23 | int mid = s + ((t - s) >> 1); 24 | //printf("s = %d, t = %d, mid = %d\n", s, t, mid); 25 | if (a[mid] == key) 26 | return mid; 27 | if (a[mid] < a[t]) { 28 | if (a[mid] < key && key <= a[t]) 29 | return binarySearch(a, mid + 1, t, key); 30 | else 31 | t = mid - 1; 32 | } else { // a[mid] > a[t] 33 | if (a[s] <= key && key < a[mid]) // 若key 在s和mid之间 34 | return binarySearch(a, s, mid - 1, key); 35 | else 36 | s = mid + 1; 37 | } 38 | } 39 | return -1; 40 | } 41 | void print(int *a, int n) 42 | { 43 | for (int i = 0; i < n; ++i) 44 | printf("%d ", a[i]); 45 | printf("\n"); 46 | } 47 | int main(int argc, char **argv) 48 | { 49 | int a[] = {4,5,6,7,8,1,2,3}; 50 | print(a, 8); 51 | printf("%d:%d\n", 8, search(a, 8, 8)); 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /algorithms/SingleNumber/README.md: -------------------------------------------------------------------------------- 1 | ## Single Number 2 | 3 | Given an array of integers, every element appears twice except for one. Find that single one. 4 | 5 | Note: 6 | Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory? 7 | 8 | ## Solution 9 | 10 | 使用异或位运算,相同的数字必然相互抵消,剩下只有一个数字的 11 | 12 | ## Code 13 | ```c 14 | int singleNumber(int a[], int n) 15 | { 16 | int result = 0; 17 | for (int i = 0; i < n; ++i) 18 | result ^= a[i]; 19 | return result; 20 | } 21 | ``` 22 | -------------------------------------------------------------------------------- /algorithms/SingleNumber/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int singleNumber(int a[], int n) 5 | { 6 | int result = 0; 7 | for (int i = 0; i < n; ++i) 8 | result ^= a[i]; 9 | return result; 10 | } 11 | int main(int argc, char **argv) 12 | { 13 | int a[] = {1,1,2,3,3,4,5,4,5}; 14 | printf("%d\n", singleNumber(a, 9)); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /algorithms/SortColors/README.md: -------------------------------------------------------------------------------- 1 | ## Sort Colors 2 | 3 | Given an array with n objects colored red, white or blue, sort them so that objects of the same color are adjacent, with the colors in the order red, white and blue. 4 | 5 | Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. 6 | 7 | Note: 8 | You are not suppose to use the library's sort function for this problem. 9 | 10 | 11 | Follow up: 12 | A rather straight forward solution is a two-pass algorithm using counting sort. 13 | First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's. 14 | 15 | Could you come up with an one-pass algorithm using only constant space? 16 | 17 | ## Solution 18 | 19 | 由于数字在一定范围以内,首先排除常规的排序算法。 20 | 21 | 显然可以使用计数排序,分别统计0,1,2的次数,然后逐一拷贝即可,时间复杂度O(n),空间复杂度O(1) 22 | 23 | 24 | 但以上方法,显然需要2趟,能不能1趟就搞定呢? 25 | 26 | 27 | 显然如果所有的0和2都排好了,那1自然也排好了。我们使用两个指针zero, two分别指向0,2的位置,当扫描数组a[i]等于0时,交换a[i]和a[zero]位置, 28 | 同时更新zero指针。同理当a[i] == 2时,交换a[two]和a[i],并更新two。 29 | 30 | ## Code 31 | ```c 32 | void sortColors(int a[], int n) 33 | { 34 | if (a == NULL || n == 1) 35 | return; 36 | int zero = 0, two = n - 1; 37 | for (int i = 0; i <= two; ++i) { 38 | if (a[i] == 0) { 39 | swap(&a[i], &a[zero++]); 40 | } 41 | if (a[i] == 2) { 42 | swap(&a[i--], &a[two--]); 43 | } 44 | } 45 | } 46 | ``` 47 | -------------------------------------------------------------------------------- /algorithms/SortColors/sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void swap(int *a, int *b) 7 | { 8 | if (a == NULL || b == NULL || a == b) 9 | return; 10 | *a ^= *b; 11 | *b ^= *a; 12 | *a ^= *b; 13 | } 14 | void sortColors(int a[], int n) 15 | { 16 | if (a == NULL || n == 1) 17 | return; 18 | int zero = 0, two = n - 1; 19 | for (int i = 0; i <= two; ++i) { 20 | if (a[i] == 0) { 21 | swap(&a[i], &a[zero++]); 22 | } 23 | if (a[i] == 2) { 24 | swap(&a[i--], &a[two--]); 25 | } 26 | } 27 | } 28 | void print(int a[], int n) 29 | { 30 | assert(a != NULL); 31 | assert(n > 0); 32 | for (int i = 0; i < n; ++i) 33 | printf("%d ", a[i]); 34 | printf("\n"); 35 | } 36 | int main(int argc, char **argv) 37 | { 38 | int a[10] = {0,2,1,2,2}; 39 | print(a, 5); 40 | sortColors(a, 5); 41 | print(a, 5); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /algorithms/SortList/in.txt: -------------------------------------------------------------------------------- 1 | 5 2 | 5 4 3 2 1 3 | 5 4 | 1 2 3 5 4 5 | 5 6 | 1 2 3 4 5 7 | 1 8 | 1 9 | 5 10 | 2 1 4 3 5 11 | -------------------------------------------------------------------------------- /algorithms/SortList/solve.cpp: -------------------------------------------------------------------------------- 1 | list.cpp -------------------------------------------------------------------------------- /algorithms/Sqrt/in.txt: -------------------------------------------------------------------------------- 1 | 2147395599 2 | -------------------------------------------------------------------------------- /algorithms/Sqrt/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int mySqrt1(int x) { 8 | if (x == 0) 9 | return 0; 10 | int left = 1, right = x; 11 | int ans = 0;; 12 | while (left < right) { 13 | //int mid = (left >> 1) + (right >> 1); 1/2 + 1/2 = 0 14 | //int mid = (left + right) >> 1; overflow 15 | //printf("left = %d, right = %d\n", left, right); 16 | int mid = left + ((right - left) >> 1); 17 | if (mid == left || mid == x / mid) 18 | return mid; 19 | if (mid < x / mid) { 20 | left = mid; 21 | } else { 22 | right = mid; 23 | } 24 | 25 | } 26 | return left; 27 | } 28 | int mySqrt2(int x) 29 | { 30 | long ans = 0; 31 | long bit = 1L << 16; 32 | while (bit) { 33 | ans |= bit; 34 | if (ans * ans > x) 35 | ans ^= bit; 36 | bit >>= 1; 37 | } 38 | return ans; 39 | } 40 | int mySqrt3(int x) 41 | { 42 | if (x == 0) 43 | return 0; 44 | int i; 45 | for (i = 1; i < x / 2; ++i) 46 | if (i > x / i) 47 | break; 48 | return i - 1; 49 | } 50 | bool test(int x) 51 | { 52 | int r1 = mySqrt1(x); 53 | int r2 = mySqrt2(x); 54 | int r3 = mySqrt3(x); 55 | printf("test %d\n", x); 56 | if (r1 != r3) { 57 | printf("%d->%d : %d\n", x, r1, r3); 58 | return false; 59 | } 60 | return true; 61 | } 62 | int main(int argc, char **argv) 63 | { 64 | for (int i = 0; i <= INT_MAX; ++i) 65 | test(i); 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /algorithms/StringtoInteger/atoi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | int myAtoi(char *str) 7 | { 8 | const int BOUND = INT_MAX / 10; 9 | if (str == NULL || strlen(str) == 0) 10 | return 0; 11 | int len = strlen(str); 12 | int i = 0; 13 | while (isblank(str[i])) ++i; // 去掉前导空白符 14 | int sign = 0; 15 | // 是否存在 + - 字符 16 | if (str[i] == '-') { 17 | sign = 1; 18 | ++i; 19 | } else if (str[i] == '+') { 20 | sign = 0; 21 | ++i; 22 | } 23 | int ans = 0; 24 | while (isdigit(str[i])) { 25 | ans *= 10; 26 | ans += (str[i] - '0'); 27 | i++; 28 | // 可能溢出,必须额外预先处理 29 | if (ans >= BOUND) 30 | break; 31 | } 32 | if (i == len || !isdigit(str[i])) //字符串结束或者遇到非数字字符 33 | return sign ? -ans : ans; 34 | int last = str[i] - '0'; 35 | // 比BOUND大,或者后面还有至少两个数字,一定溢出 36 | if (ans > BOUND || (i + 1 < len && isdigit(str[i + 1]))) { 37 | return sign ? -2147483648 : 2147483647; 38 | } 39 | if (last > 7) { 40 | if (sign && last == 8) // 最小负数,需要单独处理 41 | return -2147483648; 42 | return sign ? -2147483648 : 2147483647; 43 | } 44 | // 一定是-2147483647 ~ 2147483647范围的数字了 45 | ans *= 10; 46 | ans += last; 47 | return sign ? -ans : ans; 48 | } 49 | int main(int argc, char **argv) 50 | { 51 | char str[20]; 52 | while (scanf("%s", str) != EOF) { 53 | printf("%d\n", myAtoi(str)); 54 | } 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /algorithms/StringtoInteger/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char **argv) 6 | { 7 | char s[100]; 8 | while (scanf("%s", s) != EOF) { 9 | printf("%d\n", atoi(s)); 10 | } 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /algorithms/SubsetsII/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | using namespace std; 8 | class Solution { 9 | public: 10 | vector> subsets(vector &nums) { 11 | return subsets_iterative(nums); 12 | } 13 | private: 14 | vector> subsets_iterative(vector &nums) { 15 | vector> result(1, vector()); 16 | sort(begin(nums), end(nums)); 17 | int n = nums.size(); 18 | int m = 0; 19 | for (int i = 0; i < n; ++i) { 20 | int j = i > 0 && nums[i] == nums[i - 1] ? m : 0; 21 | m = result.size(); 22 | for (; j < m; ++j) { 23 | result.push_back(result[j]); 24 | result.back().push_back(nums[i]); 25 | } 26 | } 27 | return result; 28 | } 29 | }; 30 | void print(vector> nums) 31 | { 32 | for (auto v : nums) { 33 | cout << "["; 34 | for_each(begin(v), end(v), [](int i){cout << i << ",";}); 35 | cout << "]"; 36 | cout << endl; 37 | } 38 | } 39 | int main(int argc, char **argv) 40 | { 41 | Solution solution; 42 | vector nums = {1,2,2}; 43 | print(solution.subsets(nums)); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /algorithms/SummaryRanges/README.md: -------------------------------------------------------------------------------- 1 | ## Summary Ranges 2 | 3 | Given a sorted integer array without duplicates, return the summary of its ranges. 4 | 5 | For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"]. 6 | 7 | Credits: 8 | Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases. 9 | 10 | ## Solution 11 | 12 | 直接遍历数组即可 13 | 14 | ```cpp 15 | vector summaryRanges(vector &nums) { 16 | vector result; 17 | int n = nums.size(); 18 | if (n == 0) { 19 | return result; 20 | } 21 | int s = nums[0], t; 22 | bool update = false; 23 | int i; 24 | for (i = 1; i < n; ++i) { 25 | if (nums[i] == nums[i - 1] + 1) { 26 | update = true; 27 | t = nums[i]; 28 | } else { 29 | if (update) { 30 | result.push_back(to_string(s) + "->" + to_string(t)); 31 | s = nums[i]; 32 | update = false; 33 | } else { 34 | result.push_back(to_string(s)); 35 | s = nums[i]; 36 | } 37 | } 38 | } 39 | // last update 40 | if (update) { 41 | result.push_back(to_string(s) + "->" + to_string(nums[n - 1])); 42 | } else { 43 | result.push_back(to_string(nums[n - 1])); 44 | } 45 | return result; 46 | } 47 | ``` 48 | -------------------------------------------------------------------------------- /algorithms/SummaryRanges/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | class Solution { 8 | public: 9 | vector summaryRanges(vector &nums) { 10 | vector result; 11 | int n = nums.size(); 12 | if (n == 0) { 13 | return result; 14 | } 15 | int s = nums[0], t; 16 | bool update = false; 17 | int i; 18 | for (i = 1; i < n; ++i) { 19 | if (nums[i] == nums[i - 1] + 1) { 20 | update = true; 21 | t = nums[i]; 22 | } else { 23 | if (update) { 24 | result.push_back(to_string(s) + "->" + to_string(t)); 25 | s = nums[i]; 26 | update = false; 27 | } else { 28 | result.push_back(to_string(s)); 29 | s = nums[i]; 30 | } 31 | } 32 | } 33 | if (update) { 34 | result.push_back(to_string(s) + "->" + to_string(nums[n - 1])); 35 | } else { 36 | result.push_back(to_string(nums[n - 1])); 37 | } 38 | return result; 39 | } 40 | }; 41 | int main(int argc, char **argv) 42 | { 43 | Solution solution; 44 | vector nums = {0,5,9}; 45 | auto result = solution.summaryRanges(nums); 46 | for_each(begin(result), end(result), [](string s) {cout << s << endl;}); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /algorithms/SwapNodesinPairs/README.md: -------------------------------------------------------------------------------- 1 | ## Swap Nodes in Pairs 2 | 3 | Given a linked list, swap every two adjacent nodes and return its head. 4 | 5 | For example, 6 | ``` 7 | Given 1->2->3->4, you should return the list as 2->1->4->3. 8 | ``` 9 | 10 | Your algorithm should use only constant space. You may not modify the values in the list, only nodes itself can be changed. 11 | 12 | ## Solution 13 | 14 | 用三个指针p, q, pre, p指向当前节点,初始化为head,q指向p的下一个节点,pre指向上次完成的节点,初始化null 15 | 16 | 交换p,q,同时需要修改pre的下一个节点(之前指向p,由于p和q交换位置,需要修改指向q): 17 | 18 | ```cpp 19 | while (p && p->next) { 20 | ListNode *q = p->next; 21 | p->next = q->next; 22 | q->next = p; 23 | if (pre) 24 | pre->next = q; 25 | pre = p; 26 | p = p->next; 27 | } 28 | ``` 29 | 30 | 同时需要注意更新head指针。完整代码: 31 | 32 | ```cpp 33 | ListNode *swapPairs(ListNode *head) { 34 | if (head == nullptr || head->next == nullptr) 35 | return head; 36 | ListNode *p = head; 37 | head = p->next; 38 | ListNode *pre = nullptr; 39 | while (p && p->next) { 40 | ListNode *q = p->next; 41 | p->next = q->next; 42 | q->next = p; 43 | if (pre) 44 | pre->next = q; 45 | pre = p; 46 | p = p->next; 47 | } 48 | return head; 49 | } 50 | ``` 51 | 52 | ## 扩展 53 | 54 | [Reverse Nodes in k-Group](../ReverseNodesink-Group) 55 | -------------------------------------------------------------------------------- /algorithms/SymmetricTree/README.md: -------------------------------------------------------------------------------- 1 | ## Symmetric Tree 2 | 3 | Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). 4 | 5 | For example, this binary tree is symmetric: 6 | ``` 7 | 1 8 | / \ 9 | 2 2 10 | / \ / \ 11 | 3 4 4 3 12 | ``` 13 | But the following is not: 14 | ``` 15 | 1 16 | / \ 17 | 2 2 18 | \ \ 19 | 3 3 20 | ``` 21 | Note: 22 | 23 | * Bonus points if you could solve it both recursively and iteratively. 24 | 25 | * confused what `"{1,#,2,3}"` means? > read more on how binary tree is serialized on OJ. 26 | 27 | ## Solution 28 | 29 | 对称树,即根据根节点划分的两个子树是轴对称的。左子树和右子树分别比较即可: 30 | 31 | * 左节点和右节点的值相等。 32 | * 左节点的左孩子和右节点的右孩子对称,并且左节点的右孩子和右节点的左孩子对称 33 | 34 | 满足以上两个条件即是对称树 35 | 36 | ## Code 37 | ```c 38 | bool isLeftRightSymmetric(struct TreeNode *left, struct TreeNode *right) 39 | { 40 | if (left == NULL) 41 | return right == NULL; 42 | if (right == NULL) 43 | return false; 44 | return left->val == right->val 45 | && isLeftRightSymmetric(left->left, right->right) 46 | && isLeftRightSymmetric(left->right,right->left); 47 | } 48 | bool isSymmetric(struct TreeNode *root) { 49 | if (root == NULL) 50 | return true; 51 | return isLeftRightSymmetric(root->left, root->right); 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /algorithms/SymmetricTree/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | struct TreeNode { 6 | int val; 7 | struct TreeNode *left; 8 | struct TreeNode *right; 9 | }; 10 | bool isLeftRightSymmetric(struct TreeNode *left, struct TreeNode *right) 11 | { 12 | if (left == NULL) 13 | return right == NULL; 14 | if (right == NULL) 15 | return false; 16 | return left->val == right->val 17 | && isLeftRightSymmetric(left->left, right->right) 18 | && isLeftRightSymmetric(left->right,right->left); 19 | } 20 | bool isSymmetric(struct TreeNode *root) { 21 | if (root == NULL) 22 | return true; 23 | return isLeftRightSymmetric(root->left, root->right); 24 | } 25 | struct TreeNode *mk_node(int val) 26 | { 27 | struct TreeNode *p = malloc(sizeof(*p)); 28 | p->val = val; 29 | p->left = p->right = NULL; 30 | return p; 31 | } 32 | struct TreeNode* mk_children(struct TreeNode *root, int left, int right) 33 | { 34 | assert(root != NULL); 35 | root -> left = mk_node(left); 36 | root -> right = mk_node(right); 37 | return root; 38 | } 39 | int main(int argc, char **argv) 40 | { 41 | struct TreeNode *root = mk_node(1); 42 | mk_children(root, 2, 2); 43 | mk_children(root->left, 3, 4); 44 | mk_children(root->right, 4, 3); 45 | printf("%d\n", isSymmetric(root)); 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /algorithms/Template/list/list.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | struct ListNode { 5 | int val; 6 | struct ListNode *next; 7 | }; 8 | int getLength(struct ListNode *head) 9 | { 10 | int len = 0; 11 | struct ListNode *p = head; 12 | while (p) { 13 | ++len; 14 | p = p->next; 15 | } 16 | return len; 17 | } 18 | void print(struct ListNode *head) 19 | { 20 | if (head == NULL) { 21 | printf("NULL\n"); 22 | return; 23 | } 24 | struct ListNode *p = head; 25 | while (p) { 26 | printf("%d ", p->val); 27 | p = p->next; 28 | } 29 | printf("\n"); 30 | } 31 | struct ListNode * mk_list(struct ListNode **ha, int a[], int n) 32 | { 33 | struct ListNode *p = malloc(sizeof(*p)); 34 | p->val = a[0]; 35 | p->next = NULL; 36 | *ha = p; 37 | for (int i = 1; i < n; ++i) { 38 | struct ListNode *q = malloc(sizeof(*q)); 39 | q->val = a[i]; 40 | q->next = NULL; 41 | p->next = q; 42 | p = q; 43 | } 44 | return p; 45 | } 46 | void free_list(struct ListNode *head) 47 | { 48 | struct ListNode *p = head; 49 | while (p) { 50 | struct ListNode *q = p->next; 51 | free(p); 52 | p = q; 53 | } 54 | } 55 | int main(int argc, char **argv) 56 | { 57 | struct ListNode *head = NULL; 58 | int a[] = {}; 59 | mk_list(&head, a, 0); 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /algorithms/Template/list/list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | #include 8 | struct ListNode { 9 | int val; 10 | ListNode *next; 11 | ListNode(int x): val(x), next(nullptr) {} 12 | }; 13 | class Solution { 14 | public: 15 | 16 | }; 17 | int getLength(ListNode *head) 18 | { 19 | int len = 0; 20 | ListNode *p = head; 21 | while (p) { 22 | ++len; 23 | p = p->next; 24 | } 25 | return len; 26 | } 27 | void print(ListNode *head) 28 | { 29 | if (head == nullptr) { 30 | printf("NULL\n"); 31 | return; 32 | } 33 | struct ListNode *p = head; 34 | while (p) { 35 | printf("%d ", p->val); 36 | p = p->next; 37 | } 38 | printf("\n"); 39 | } 40 | ListNode * mk_list(ListNode **ha, int a[], int n) 41 | { 42 | if (n < 1) 43 | return nullptr; 44 | ListNode *p = new ListNode(a[0]); 45 | *ha = p; 46 | for (int i = 1; i < n; ++i) { 47 | ListNode *q = new ListNode(a[i]); 48 | p->next = q; 49 | p = q; 50 | } 51 | return p; 52 | } 53 | void free_list(struct ListNode *head) 54 | { 55 | struct ListNode *p = head; 56 | while (p) { 57 | struct ListNode *q = p->next; 58 | delete p; 59 | p = q; 60 | } 61 | } 62 | int main(int argc, char **argv) 63 | { 64 | struct ListNode *head = NULL; 65 | int a[] = {1, 2, 3}; 66 | mk_list(&head, a, 3); 67 | print(head); 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /algorithms/Template/tree/tree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | struct TreeNode { 8 | int val; 9 | TreeNode *left; 10 | TreeNode *right; 11 | TreeNode(int x) : val(x), left(nullptr), right(nullptr){} 12 | }; 13 | class Solution { 14 | public: 15 | }; 16 | TreeNode *mk_node(int val) 17 | { 18 | return new TreeNode(val); 19 | } 20 | TreeNode *mk_child(TreeNode *root, TreeNode *left, TreeNode *right) 21 | { 22 | root->left = left; 23 | root->right = right; 24 | return root; 25 | } 26 | TreeNode *mk_child(TreeNode *root, int left, int right) 27 | { 28 | return mk_child(root, new TreeNode(left), new TreeNode(right)); 29 | } 30 | TreeNode *mk_child(int root, int left, int right) 31 | { 32 | return mk_child(new TreeNode(root), new TreeNode(left), new TreeNode(right)); 33 | } 34 | int main(int argc, char **argv) 35 | { 36 | Solution solution; 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /algorithms/TwoSum/README.md: -------------------------------------------------------------------------------- 1 | # Two Sum 2 | 3 | ## Problem 4 | Given an array of integers, find two numbers such that they add up to a specific target number. 5 | 6 | The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based. 7 | 8 | You may assume that each input would have exactly one solution. 9 | 10 | Input: numbers={2, 7, 11, 15}, target=9 11 | Output: index1=1, index2=2 12 | 13 | ## Solution 1 14 | 15 | 暴力枚举法,时间复杂度O(n2),时间复杂度O(1) 16 | 17 | ## Solution 2 18 | 19 | 假设数组为2 7 11 15, target 为9, 则用9减数组的元素得到一个新的数组7 2 -2 -6,则只需要查找数组中的元素是否在新的数组中出现即可判断是否存在满足条件的两个数。 20 | 21 | 比如2和7 在新的数组中也存在,所以2和7即满足条件。 22 | 23 | 题目要求找到满足条件的索引,只需要用一个map,key为target-a[i],value为index。当遍历数组a[i],若a[i]在map keyset中,则说明i和map[a[i]]即是解。 24 | 25 | ```c 26 | vector twoSum(vector &numbers, int target) { 27 | map m; 28 | vector result; 29 | for (size_t i = 0; i < numbers.size(); ++i) { 30 | if (m.find(numbers[i]) == m.end()) { 31 | m[target - numbers[i]] = i; 32 | } else { 33 | result.push_back(m[numbers[i]] + 1); // index from 1, not 0 34 | result.push_back(i + 1); // index from 1 35 | } 36 | } 37 | return result; 38 | } 39 | ``` 40 | 时间复杂度为O(n), 空间复杂度O(n). 41 | -------------------------------------------------------------------------------- /algorithms/TwoSum/src.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | vector twoSum(vector &numbers, int target) { 9 | map m; 10 | vector result; 11 | for (size_t i = 0; i < numbers.size(); ++i) { 12 | if (m.find(numbers[i]) == m.end()) { 13 | m[target - numbers[i]] = i; 14 | } else { 15 | result.push_back(m[numbers[i]] + 1); // index from 1, not 0 16 | result.push_back(i + 1); // index from 1 17 | } 18 | } 19 | return result; 20 | } 21 | }; 22 | int main(int argc, char **argv) 23 | { 24 | Solution solution; 25 | vector numbers = {2,7,11,15}; 26 | auto result = solution.twoSum(numbers, 9); 27 | printf("%d\n%d\n", result[0], result[1]); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /algorithms/UniqueBinarySearchTrees/README.md: -------------------------------------------------------------------------------- 1 | ## Unique Binary Search Trees 2 | Given n, how many structurally unique BST's (binary search trees) that store values 1...n? 3 | 4 | For example, 5 | 6 | Given n = 3, there are a total of 5 unique BST's. 7 | ``` 8 | 1 3 3 2 1 9 | \ / / / \ \ 10 | 3 2 1 1 3 2 11 | / / \ \ 12 | 2 1 2 3 13 | ``` 14 | 15 | ## Solution 16 | 17 | 首先n为0时,树的个数为0,即空树,n为1时,树的个数为1,即单节点树 18 | 19 | 假设根节点固定,则`以该根组成的树的个数 = 左子树个数 * 右子树个数`。 20 | 21 | 当数组为 1, 2, 3, ..., n 时,基于以下原则的构建的BST树具有唯一性:以i为根节点的树,其左子树由 [1, i-1] 构成,其右子树由 [i+1, n] 构成。即以i为根节点的树的总数等于numTrees(i - 1) * numTrees(n - i) 22 | 23 | 因此要求f(n),只要迭代即可: 24 | 25 | ```c 26 | for (int i = 2; i <= n; ++i) { 27 | for (int j = 1; j <= i; ++j) { /* 分别以j为根 */ 28 | f[i] += f[j - 1] * f[i - j]; 29 | } 30 | } 31 | ``` 32 | 33 | ## Code 34 | int numTrees(int n) 35 | { 36 | int dp[n + 1]; 37 | memset(dp, 0, sizeof(dp)); 38 | dp[0] = 1; 39 | dp[1] = 1; 40 | for (int i = 2; i <= n; ++i) { 41 | for (int j = 1; j <= i; ++j) { 42 | dp[i] += dp[j - 1] * dp[i - j]; 43 | } 44 | } 45 | return dp[n]; 46 | } 47 | -------------------------------------------------------------------------------- /algorithms/UniqueBinarySearchTrees/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | int numTrees(int n) 5 | { 6 | int dp[n + 1]; 7 | memset(dp, 0, sizeof(dp)); 8 | dp[0] = 1; 9 | dp[1] = 1; 10 | for (int i = 2; i <= n; ++i) { 11 | for (int j = 1; j <= i; ++j) { 12 | dp[i] += dp[j - 1] * dp[i - j]; 13 | } 14 | } 15 | return dp[n]; 16 | } 17 | int main(int argc, char **argv) 18 | { 19 | int n; 20 | while (scanf("%d", &n) != EOF) 21 | printf("numTrees(%d) = %d\n", n, numTrees(n)); 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /algorithms/ValidAnagram/README.md: -------------------------------------------------------------------------------- 1 | ## Valid Anagram 2 | 3 | Given two strings s and t, write a function to determine if t is an anagram of s. 4 | 5 | For example, 6 | `s = "anagram"`, `t = "nagaram"`, return `true`. 7 | `s = "rat"`, `t = "car"`, return `false`. 8 | 9 | Note: 10 | *You may assume the string contains only lowercase alphabets.* 11 | 12 | ## Solution 13 | 14 | * 如果两个字符串长度不一样,返回`false`。 15 | * 两个字符串所有出现字符以及数量相同,返回`true`。使用hash表首先存储第一个字符串的字符个数,然后遍历第二个字符串,每出现一个字符,对应hash表计数-1,若出现负数,则返回`false`。 16 | 17 | ```c 18 | bool isAnagram(char *s, char *t) 19 | { 20 | int len1 = strlen(s), len2 = strlen(t); 21 | if (len1 != len2) 22 | return false; 23 | int table[26] = {0}; 24 | for (int i = 0; i < len1; ++i) 25 | table[s[i] - 'a']++; 26 | for (int i = 0; i < len2; ++i) { 27 | if (table[t[i] - 'a'] <= 0) 28 | return false; 29 | table[t[i] - 'a']--; 30 | } 31 | return true; 32 | } 33 | ``` 34 | -------------------------------------------------------------------------------- /algorithms/ValidAnagram/in.txt: -------------------------------------------------------------------------------- 1 | anagram nagaram 2 | rat car 3 | -------------------------------------------------------------------------------- /algorithms/ValidAnagram/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | bool isAnagram(char *s, char *t) 5 | { 6 | int len1 = strlen(s), len2 = strlen(t); 7 | if (len1 != len2) 8 | return false; 9 | int table[26] = {0}; 10 | for (int i = 0; i < len1; ++i) 11 | table[s[i] - 'a']++; 12 | for (int i = 0; i < len2; ++i) { 13 | if (table[t[i] - 'a'] <= 0) 14 | return false; 15 | table[t[i] - 'a']--; 16 | } 17 | return true; 18 | } 19 | int main(int argc, char **argv) 20 | { 21 | char s[20], t[20]; 22 | while (scanf("%s%s", s, t) != EOF) { 23 | printf("%d\n", isAnagram(s, t)); 24 | } 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /algorithms/ValidNumber/in.txt: -------------------------------------------------------------------------------- 1 | 0 2 | 0.1 3 | abc 4 | 1 a 5 | 2e10 6 | 4e+ 7 | .-4 8 | .0 9 | 46.e-3 10 | 46.e3 11 | .e1 12 | -------------------------------------------------------------------------------- /algorithms/ValidNumber/test.c: -------------------------------------------------------------------------------- 1 | #include 2 | int main(int argc, char **argv) 3 | { 4 | double f1 = -1e1; // Valid 5 | //double f2 = -1e0.2; Invalid 6 | double f3 = -.3; // Valid 7 | //double f3 = .; // Invalid 8 | f1 = 9.; 9 | f1 = 4e+; 10 | f1 = 46.e3; 11 | f1 = 47.0123e123; 12 | f1 = 1.e-12; 13 | f1 = 1.2123e-12; 14 | f1 = .e123 // Invalid; 15 | f1 = 1.e0001 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /algorithms/ValidPalindrome/README.md: -------------------------------------------------------------------------------- 1 | ## Valid Palindrome 2 | 3 | Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. 4 | 5 | For example, 6 | `"A man, a plan, a canal: Panama"` is a palindrome. 7 | `"race a car"` is not a palindrome. 8 | 9 | Note: 10 | 11 | * Have you consider that the string might be empty? This is a good question to ask during an interview. 12 | 13 | * For the purpose of this problem, we define empty string as valid palindrome. 14 | 15 | ## Solution 16 | 17 | 直接前后比较即可 18 | ```cpp 19 | class Solution { 20 | public: 21 | bool isPalindrome(string s) { 22 | int n = s.size(); 23 | if (n == 0) 24 | return true; 25 | int left = next(s, -1); 26 | int right = prev(s, n); 27 | for (int i = next(s, -1), j = prev(s, n); i < j; i = next(s, i), j = prev(s, j)) { 28 | if (!equals(s[i], s[j])) 29 | return false; 30 | } 31 | return true; 32 | } 33 | private: 34 | int next(const string &s, int i) { 35 | i++; 36 | while (!isalnum(s[i])) i++; 37 | return i; 38 | } 39 | int prev(const string &s, int j) { 40 | j--; 41 | while (!isalnum(s[j])) j--; 42 | return j; 43 | } 44 | bool equals(char a, char b) { 45 | a = tolower(a); 46 | b = tolower(b); 47 | return a == b; 48 | } 49 | }; 50 | ``` 51 | -------------------------------------------------------------------------------- /algorithms/ValidPalindrome/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | bool isPalindrome(string s) { 9 | int n = s.size(); 10 | if (n == 0) 11 | return true; 12 | int left = next(s, -1); 13 | int right = prev(s, n); 14 | for (int i = next(s, -1), j = prev(s, n); i < j; i = next(s, i), j = prev(s, j)) { 15 | if (!equals(s[i], s[j])) 16 | return false; 17 | } 18 | return true; 19 | } 20 | private: 21 | int next(const string &s, int i) { 22 | i++; 23 | while (!isalnum(s[i])) i++; 24 | return i; 25 | } 26 | int prev(const string &s, int j) { 27 | j--; 28 | while (!isalnum(s[j])) j--; 29 | return j; 30 | } 31 | bool equals(char a, char b) { 32 | a = tolower(a); 33 | b = tolower(b); 34 | return a == b; 35 | } 36 | }; 37 | int main(int argc, char **argv) 38 | { 39 | Solution solution; 40 | string s1 = "A man, a plan, a canal: Panama"; 41 | string s2 = "race a car"; 42 | string s3 = "1a2"; 43 | cout << solution.isPalindrome(s1) << endl; 44 | cout << solution.isPalindrome(s2) << endl; 45 | cout << solution.isPalindrome(s3) << endl; 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /algorithms/ValidParentheses/README.md: -------------------------------------------------------------------------------- 1 | ## Valid Parentheses 2 | 3 | Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. 4 | 5 | The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not. 6 | 7 | ## Solution 8 | 9 | 栈的基本应用 10 | 11 | ## Code 12 | ```c 13 | bool isLeft(char c) 14 | { 15 | return c == '(' || c == '[' || c == '{'; 16 | } 17 | bool isMatch(char a, char b) 18 | { 19 | return (a == '(' && b == ')') 20 | || (a == '[' && b == ']') 21 | || (a == '{' && b == '}'); 22 | } 23 | bool isValid(char *s) 24 | { 25 | int len = strlen(s); 26 | char *stack = malloc(sizeof(char) * len); 27 | int pos = -1; 28 | for (int i = 0; i < len; ++i) { 29 | if (isLeft(s[i])) { 30 | stack[++pos] = s[i]; 31 | } else { 32 | if (isMatch(stack[pos], s[i])) { 33 | --pos; 34 | } else { 35 | return false; 36 | } 37 | } 38 | } 39 | free(stack); 40 | return pos == -1; 41 | } 42 | ``` 43 | -------------------------------------------------------------------------------- /algorithms/ValidParentheses/in.txt: -------------------------------------------------------------------------------- 1 | () 2 | ()[]{} 3 | (] 4 | ([)] 5 | -------------------------------------------------------------------------------- /algorithms/ValidParentheses/solve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | bool isLeft(char c) 6 | { 7 | return c == '(' || c == '[' || c == '{'; 8 | } 9 | bool isMatch(char a, char b) 10 | { 11 | return (a == '(' && b == ')') 12 | || (a == '[' && b == ']') 13 | || (a == '{' && b == '}'); 14 | } 15 | bool isValid(char *s) 16 | { 17 | int len = strlen(s); 18 | char *stack = malloc(sizeof(char) * len); 19 | int pos = -1; 20 | for (int i = 0; i < len; ++i) { 21 | if (isLeft(s[i])) { 22 | stack[++pos] = s[i]; 23 | } else { 24 | if (isMatch(stack[pos], s[i])) { 25 | --pos; 26 | } else { 27 | return false; 28 | } 29 | } 30 | } 31 | free(stack); 32 | return pos == -1; 33 | } 34 | int main(int argc, char **argv) 35 | { 36 | char s[20]; 37 | printf("%d\n", isValid("")); 38 | while (scanf("%s", s) != EOF) 39 | printf("%d\n", isValid(s)); 40 | return true; 41 | } 42 | -------------------------------------------------------------------------------- /algorithms/ValidSudoku/in.txt: -------------------------------------------------------------------------------- 1 | .87654321 2 | 2........ 3 | 2........ 4 | 4........ 5 | 5........ 6 | 6........ 7 | 7........ 8 | 8........ 9 | 9........ 10 | -------------------------------------------------------------------------------- /algorithms/WordBreak/README.md: -------------------------------------------------------------------------------- 1 | ## Word Break 2 | 3 | Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separated sequence of one or more dictionary words. 4 | 5 | For example, given 6 | s = `"leetcode"`, 7 | dict = `["leet", "code"]`. 8 | 9 | Return true because `"leetcode"` can be segmented as `"leet code"`. 10 | 11 | ## Solution 12 | 13 | 类似DP思想: 14 | 15 | 使用dp[i]表示前面i个字符(0 ~ i - 1)是否可以break, 显然dp[i]取决于i之前是否可以break,并且`dp[0] = true`,即 16 | 17 | ``` 18 | for j from 0 to 1 19 | if dp[j] && s[i:j] in dict 20 | dp[i] = true 21 | break 22 | ``` 23 | 24 | 于是实现代码为: 25 | 26 | ```cpp 27 | bool wordBreak(string s, const unordered_set &dict) { 28 | int n = s.size(); 29 | vector canBreak(n + 1, false); 30 | canBreak[0] = true; 31 | for (int i = 1; i <= n; ++i) { 32 | for (int j = 0; j < i; ++j) { 33 | if (canBreak[j] && dict.find(s.substr(j, i - j)) != dict.end()) { 34 | canBreak[i] = true; 35 | break; 36 | } 37 | } 38 | } 39 | return canBreak[n]; 40 | } 41 | ``` 42 | 43 | ## 扩展 44 | 45 | [Word Break II](../WordBreakII): 打印所有的结果 46 | -------------------------------------------------------------------------------- /algorithms/WordBreak/solve.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | using namespace std; 6 | class Solution { 7 | public: 8 | bool wordBreak(string s, const unordered_set &dict) { 9 | int n = s.size(); 10 | vector canBreak(n + 1, false); 11 | canBreak[0] = true; 12 | for (int i = 1; i <= n; ++i) { 13 | for (int j = 0; j < i; ++j) { 14 | if (canBreak[j] && dict.find(s.substr(j, i - j)) != dict.end()) { 15 | canBreak[i] = true; 16 | break; 17 | } 18 | } 19 | } 20 | return canBreak[n]; 21 | } 22 | }; 23 | int main(int argc, char **argv) 24 | { 25 | Solution solution; 26 | string s = "leetcode"; 27 | unordered_set dict = {"leet", "code"}; 28 | cout << solution.wordBreak(s, dict) << endl; 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /database/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/int32bit/leetcode/4cf8d30509f4b994b1845765807380eeffb95c73/database/.gitkeep -------------------------------------------------------------------------------- /database/CombineTwoTables/solve.sql: -------------------------------------------------------------------------------- 1 | use leetcode; 2 | create table if not exists Person(PersonId int,FirstName varchar(20),LastName varchar(20)); 3 | create table if not exists Address(AddressId int, PersonId int, City varchar(20), State varchar(20)); 4 | select FirstName, LastName, City, State from Person left join Address on Person.PersonId = Address.PersonId; 5 | -------------------------------------------------------------------------------- /database/ConsecutiveNumbers/when.sql: -------------------------------------------------------------------------------- 1 | use leetcode; 2 | select Num, 3 | case 4 | when Num % 2 = 0 then "Even" 5 | when Num % 2 = 1 then "Odd" 6 | end Numtype 7 | from Logs; 8 | 9 | select Num from ( 10 | SELECT 11 | Num, 12 | CASE 13 | WHEN @prevNum = Num THEN @count := @count + 1 14 | WHEN @prevNum := Num THEN @count := 1 15 | END n 16 | FROM Logs, (select @prevNum := NULL) initPrevNum, (select @count := 1) initCount 17 | ) as result where result.n >= 3; 18 | /* 19 | SELECT * FROM ( 20 | SELECT 21 | `Num`, 22 | CASE 23 | WHEN @prevNum = `Num` THEN @count := @count + 1 24 | WHEN @prevNum := `Num` THEN @count := 1 25 | END n 26 | FROM `Logs`, (select @prevNum := NULL) r, (select @count := 1) s 27 | ) a; 28 | 29 | */ 30 | -------------------------------------------------------------------------------- /database/CustomersWhoNeverOrder/README.md: -------------------------------------------------------------------------------- 1 | # Customers Who Never Order 2 | 3 | ## Problem 4 | 5 | Suppose that a website contains two tables, the `Customers` table and the `Orders` table. Write a SQL query to find all customers who never order anything. 6 | 7 | Table: `Customers`. 8 | ``` 9 | +----+-------+ 10 | | Id | Name | 11 | +----+-------+ 12 | | 1 | Joe | 13 | | 2 | Henry | 14 | | 3 | Sam | 15 | | 4 | Max | 16 | +----+-------+ 17 | ``` 18 | Table: `Orders`. 19 | ``` 20 | +----+------------+ 21 | | Id | CustomerId | 22 | +----+------------+ 23 | | 1 | 3 | 24 | | 2 | 1 | 25 | +----+------------+ 26 | ``` 27 | Using the above tables as example, return the following: 28 | ``` 29 | +-----------+ 30 | | Customers | 31 | +-----------+ 32 | | Henry | 33 | | Max | 34 | +-----------+ 35 | ``` 36 | 37 | ## Solution 38 | 39 | 直接使用exists语句查询 40 | 41 | ## Code 42 | ```sql 43 | select c.Name as Customers 44 | from Customers as c 45 | where not exists (select o.Id from Orders as o where c.Id = o.CustomerId); 46 | ``` 47 | 48 | ## exists语句 49 | 50 | `exists`语句后面接一个`select`子查询,但实际并不返回任何数据,只返回是否有数据,存在返回`true`,否则`false`. 51 | -------------------------------------------------------------------------------- /database/CustomersWhoNeverOrder/solve.sql: -------------------------------------------------------------------------------- 1 | use leetcode; 2 | drop table if exists Customers; 3 | create table Customers(Id int, Name varchar(20)); 4 | insert into Customers values (1, "Joe"), (2, "Henry"), (3,"Sam"),(4,"Max"); 5 | 6 | drop table if exists Orders; 7 | create table Orders(Id int, CustomerId int); 8 | insert into Orders values (1,3),(2,1); 9 | 10 | select c.Name as Customers 11 | from Customers as c 12 | where not exists (select o.Id from Orders as o where c.Id = o.CustomerId); 13 | -------------------------------------------------------------------------------- /database/DeleteDuplicateEmails/solve.sql: -------------------------------------------------------------------------------- 1 | use leetcode; 2 | drop table if exists Person; 3 | create table Person(id int, Email varchar(20)); 4 | insert into Person values (1, "a"),(2, "a"),(3,"b"),(4,"b"),(5,"b"), (6, "c"); 5 | /* 6 | delete p from Person as p where p.Id not in (select Id from (select min(Person.Id) as Id from Person group by Person.Email) as NewPerson); 7 | */ 8 | /* 9 | delete p1 from Person p1, Person p2 where p1.Email = p2.Email and p1.Id > p2.Id; 10 | */ 11 | select * from Person; 12 | -------------------------------------------------------------------------------- /database/DepartmentHighestSalary/solve.sql: -------------------------------------------------------------------------------- 1 | use leetcode; 2 | drop table if exists Employee; 3 | create table Employee(Id int, Name varchar(20), Salary int, DepartmentId int); 4 | insert into Employee values 5 | (1, "Joe", 70000, 1), 6 | (2, "Henry", 80000, 2), 7 | (3,"Sam", 60000, 2), 8 | (4,"Max", 90000, 1); 9 | 10 | drop table if exists Department; 11 | create table Department(Id int, Name varchar(20)); 12 | insert into Department values 13 | (1,"IT"), 14 | (2,"Sales"); 15 | 16 | select DepartmentId, max(Salary) as max from Employee group by DepartmentId; 17 | /* 18 | select d.Name as Department, e1.Name as Employee, e1.Salary as Salary 19 | from Employee as e1 20 | join (select DepartmentId, max(Salary) as max from Employee group by DepartmentId) as t 21 | on e1.DepartmentId = t.DepartmentId 22 | join Department as d 23 | on e1.DepartmentId = d.Id 24 | where e1.Salary = max; 25 | */ 26 | 27 | /* 28 | select d.Name as Department, e.Name as Employee, max(e.Salary) as Salary 29 | from Employee as e 30 | join Department as d on e.DepartmentId = d.Id 31 | group by e.DepartmentId; 32 | */ 33 | -------------------------------------------------------------------------------- /database/DepartmentTopThreeSalaries/solve.sql: -------------------------------------------------------------------------------- 1 | use leetcode; 2 | drop table if exists Employee; 3 | create table Employee(Id int, Name varchar(20), Salary int, DepartmentId int); 4 | insert into Employee values 5 | (1, "Joe", 70000, 1), 6 | (2, "Henry", 80000, 2), 7 | (3,"Sam", 60000, 2), 8 | (4,"Max", 90000, 1), 9 | (5, "Janet", 69000, 1), 10 | (6, "Randy", 85000, 1); 11 | 12 | drop table if exists Department; 13 | create table Department(Id int, Name varchar(20)); 14 | insert into Department values 15 | (1,"IT"), 16 | (2,"Sales"); 17 | 18 | select top(Salary) from Employee group by DepartmentId; 19 | -------------------------------------------------------------------------------- /database/DuplicateEmails/README.md: -------------------------------------------------------------------------------- 1 | # Duplicate Emails 2 | 3 | ## Problem 4 | 5 | Write a SQL query to find all duplicate emails in a table named `Person`. 6 | ``` 7 | +----+---------+ 8 | | Id | Email | 9 | +----+---------+ 10 | | 1 | a@b.com | 11 | | 2 | c@d.com | 12 | | 3 | a@b.com | 13 | +----+---------+ 14 | ``` 15 | For example, your query should return the following for the above table: 16 | ``` 17 | +---------+ 18 | | Email | 19 | +---------+ 20 | | a@b.com | 21 | +---------+ 22 | ``` 23 | Note: All emails are in lowercase. 24 | 25 | ## Solution 1 26 | 27 | 直接使用子查询 28 | 29 | ## Code 30 | ```sql 31 | select Email 32 | from (select Email, count(*) count from Person group by Email) as e 33 | where e.count > 1; 34 | ``` 35 | 36 | ## Solution 2 37 | 38 | 分组过滤 39 | 40 | ## Code 41 | ```sql 42 | select Email 43 | from Person group by Email 44 | having count(Email) > 1; 45 | ``` 46 | -------------------------------------------------------------------------------- /database/DuplicateEmails/duplicateEmails.sql: -------------------------------------------------------------------------------- 1 | use leetcode; 2 | drop table if exists Person; 3 | create table Person(Id int, Email varchar(20)); 4 | insert into Person values(1, "a@b.com"); 5 | insert into Person values(2, "c@d.com"); 6 | insert into Person values(3, "a@b.com"); 7 | /* 8 | select Email from (select Email, count(*) count from Person group by Email) as e where e.count > 1; 9 | */ 10 | select Email from Person group by Email having count(Email) > 1; 11 | -------------------------------------------------------------------------------- /database/EmployeesEarningMoreThanTheirManagers/README.md: -------------------------------------------------------------------------------- 1 | # Employees Earning More Than Their Managers 2 | 3 | ## Problem 4 | 5 | The `Employee` table holds all employees including their managers. Every employee has an `Id`, and there is also a column for the `manager Id`. 6 | ``` 7 | +----+-------+--------+-----------+ 8 | | Id | Name | Salary | ManagerId | 9 | +----+-------+--------+-----------+ 10 | | 1 | Joe | 70000 | 3 | 11 | | 2 | Henry | 80000 | 4 | 12 | | 3 | Sam | 60000 | NULL | 13 | | 4 | Max | 90000 | NULL | 14 | +----+-------+--------+-----------+ 15 | ``` 16 | Given the `Employee` table, write a SQL query that finds out employees who earn more than their managers. For the above table, Joe is the only employee who earns more than his manager. 17 | ``` 18 | +----------+ 19 | | Employee | 20 | +----------+ 21 | | Joe | 22 | +----------+ 23 | ``` 24 | 25 | ## Solution 1: 相关子查询 26 | 27 | ```sql 28 | select e1.Name as Employee from Employee2 as e1 29 | where e1.ManagerId is not NULL 30 | and e1.Salary > (select Salary from Employee2 where Id=e1.ManagerId); 31 | ``` 32 | 33 | 结果超时,原因是相关子查询效率非常低,应该尽量避免 34 | 35 | ## Solution 2: 内连接 36 | 37 | ```sql 38 | select e1.Name as Employee from Employee2 as e1 39 | join Employee2 as e2 40 | on e1.ManagerId = e2.Id and e1.Salary > e2.Salary 41 | where e1.ManagerId is not NULL; 42 | ``` 43 | 44 | 结果顺利通过。 45 | -------------------------------------------------------------------------------- /database/EmployeesEarningMoreThanTheirManagers/employeesEarningMoreThanTheirManagers.sql: -------------------------------------------------------------------------------- 1 | use leetcode; 2 | create table if not exists Employee2(Id int, Name varchar(20), Salary int, ManagerId int default NULL); 3 | /* 4 | insert into Employee2 values(1, "Joe", 70000, 3); 5 | insert into Employee2 values(2, "Henry", 80000, 4); 6 | insert into Employee2 values(3, "Sam", 60000, NULL); 7 | insert into Employee2 values(4, "Max", 90000, NULL); 8 | */ 9 | /* 10 | select e1.Name as Employee from Employee2 as e1 11 | where e1.ManagerId is not NULL 12 | and e1.Salary > (select Salary from Employee2 where Id=e1.ManagerId); 13 | */ 14 | select e1.Name as Employee from Employee2 as e1 15 | join Employee2 as e2 16 | on e1.ManagerId = e2.Id and e1.Salary > e2.Salary 17 | where e1.ManagerId is not NULL; 18 | -------------------------------------------------------------------------------- /database/NthHighestSalary/functions.sql: -------------------------------------------------------------------------------- 1 | use leetcode; 2 | delimiter $$ /* 由于函数里要使用分号分隔符,这里要定义另一个分隔符 */ 3 | 4 | create procedure simpleproc(OUT count int) 5 | begin 6 | select count(*) into count from Employee; 7 | end$$ 8 | 9 | delimiter ; 10 | /* 使用call调用过程 */ 11 | call simpleproc(@a); 12 | /* 输出变量a的值 */ 13 | 14 | select @a; 15 | -------------------------------------------------------------------------------- /database/NthHighestSalary/solve.sql: -------------------------------------------------------------------------------- 1 | use leetcode; 2 | drop table if exists Employee; 3 | create table Employee(Id int, Salary int); 4 | /* 5 | insert into Employee values (1, 300),(2,200),(3,100),(4,500),(5,700),(6,400); 6 | */ 7 | insert into Employee values (1, 200),(2,200); 8 | delimiter $$ 9 | drop function if exists getNthHighestSalary $$ 10 | CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT 11 | BEGIN 12 | declare x int; 13 | set N = N - 1; 14 | set x = (select distinct Salary from Employee order by Salary desc limit N, 1); 15 | if isnull(x) 16 | then 17 | return null; 18 | else 19 | return x; 20 | end if; 21 | END$$ 22 | delimiter ; 23 | select getNthHighestSalary(2); 24 | -------------------------------------------------------------------------------- /database/RankScores/solve.sql: -------------------------------------------------------------------------------- 1 | use leetcode; 2 | create table if not exists Scores(Id int, Score decimal(7, 2)); 3 | /* 4 | insert into Scores values(1, 3.50); 5 | insert into Scores values(2, 3.65); 6 | insert into Scores values(3, 4.00); 7 | insert into Scores values(4, 3.85); 8 | insert into Scores values(5, 4.00); 9 | insert into Scores values(6, 3.65); 10 | */ 11 | select Scores.Score as Score, COUNT(*) as Rank 12 | from Scores 13 | join (select distinct Score from Scores) Ranking 14 | on Scores.Score <= Ranking.Score 15 | group by Scores.Id 16 | order by Scores.Score desc; 17 | /* 18 | select Scores.Score , Ranking.Score 19 | from Scores 20 | join (select distinct Score from Scores) Ranking 21 | on Scores.Score <= Ranking.Score 22 | order by Scores.Score desc; 23 | */ 24 | -------------------------------------------------------------------------------- /database/RisingTemperature/README.md: -------------------------------------------------------------------------------- 1 | ## Rising Temperature 2 | 3 | Given a `Weather` table, write a SQL query to find all dates' `Id`s with higher temperature compared to its previous (yesterday's) dates. 4 | ``` 5 | +---------+------------+------------------+ 6 | | Id(INT) | Date(DATE) | Temperature(INT) | 7 | +---------+------------+------------------+ 8 | | 1 | 2015-01-01 | 10 | 9 | | 2 | 2015-01-02 | 25 | 10 | | 3 | 2015-01-03 | 20 | 11 | | 4 | 2015-01-04 | 30 | 12 | +---------+------------+------------------+ 13 | ``` 14 | For example, return the following Ids for the above `Weather` table: 15 | ``` 16 | +----+ 17 | | Id | 18 | +----+ 19 | | 2 | 20 | | 4 | 21 | +----+ 22 | ``` 23 | 24 | ## Solution 25 | 26 | 自连接查询,需要注意日期的比较,mysql中使用`TO_DAYS`转化,否则是字符串比较。 27 | 28 | ## Code 29 | 30 | ```sql 31 | select w1.Id from Weather w1, Weather w2 32 | where TO_DAYS(w1.DATE) = TO_DAYS(w2.DATE) + 1 33 | and w1.Temperature > w2.Temperature; 34 | ``` 35 | -------------------------------------------------------------------------------- /database/RisingTemperature/solve.sql: -------------------------------------------------------------------------------- 1 | use leetcode; 2 | drop table if exists Weather; 3 | create table Weather(Id INT, Date DATE, Temperature INT); 4 | insert into Weather values 5 | (1, Date("2015-01-01"), 10), 6 | (2, Date("2015-01-02"), 25), 7 | (3, Date("2015-01-03"), 20), 8 | (4, Date("2015-01-04"), 30); 9 | select w1.Id from Weather w1, Weather w2 where TO_DAYS(w1.DATE) = TO_DAYS(w2.DATE) + 1 and w1.Temperature > w2.Temperature; 10 | -------------------------------------------------------------------------------- /database/SecondHighestSalary/README.md: -------------------------------------------------------------------------------- 1 | # Second Highest Salary 2 | 3 | ## Problem 4 | Write a SQL query to get the second highest salary from the Employee table. 5 | ``` 6 | +----+--------+ 7 | | Id | Salary | 8 | +----+--------+ 9 | | 1 | 100 | 10 | | 2 | 200 | 11 | | 3 | 300 | 12 | +----+--------+ 13 | ``` 14 | For example, given the above Employee table, the second highest salary is 200. If there is no second highest salary, then the query should return null. 15 | 16 | ## Solution 1 17 | 18 | 可以使用子查询的方式,即 19 | 20 | ```sql 21 | select max(Salary) as SecondHighestSalary from Employee where Salary < (select max(Salary) from Employee); 22 | ``` 23 | 24 | 这种方式更通用,但使用了子查询(不相关子查询),效率会低点。 25 | 26 | ## Solution 2 27 | 28 | 使用mysql特有`LIMIT` 和 `IFNULL`语法,下面简单介绍下: 29 | 30 | ### LIMIT 31 | 32 | LIMIT可以限制select语句的输出行数,可以有一个参数或者两个参数。 33 | 34 | 如果只有一个参数,则表示限制的最大行数,如果不足最大行数,则输出所有行。 35 | 36 | 如果两个参数,前一个参数表示与第一行的偏移量,偏移量为0表示从第一行开始输出,第二个参数表示最大行数。如果偏移量超出行数范围,输出为空 37 | 38 | 39 | ### IFNULL 40 | 41 | 两个参数,如果第一个参数为空集合,则输出第二个参数。 42 | 43 | 综合以上两个函数,可以实现为: 44 | 45 | ```sql 46 | select ifnull((select distinct Salary from Employee order by Salary desc limit 1,1), null) as SecondHighestSalary; 47 | ``` 48 | -------------------------------------------------------------------------------- /database/SecondHighestSalary/solve.sql: -------------------------------------------------------------------------------- 1 | use leetcode; 2 | create table if not exists Employee(Id int, Salary int); 3 | /* 4 | insert into Employee values(1, 100); 5 | insert into Employee values(2, 200); 6 | insert into Employee values(3, 300); 7 | */ 8 | /* 9 | select max(Salary) as SecondHighestSalary from Employee where Salary < (select max(Salary) from Employee); 10 | */ 11 | select ifnull((select distinct Salary from Employee order by Salary desc limit 1,1), null) as SecondHighestSalary; 12 | -------------------------------------------------------------------------------- /shell/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/int32bit/leetcode/4cf8d30509f4b994b1845765807380eeffb95c73/shell/.gitkeep -------------------------------------------------------------------------------- /shell/TenthLine/README.md: -------------------------------------------------------------------------------- 1 | # Tenth Line 2 | 3 | ## Problem 4 | 5 | How would you print just the 10th line of a file? 6 | 7 | For example, assume that `file.txt` has the following content: 8 | ``` 9 | Line 1 10 | Line 2 11 | Line 3 12 | Line 4 13 | Line 5 14 | Line 6 15 | Line 7 16 | Line 8 17 | Line 9 18 | Line 10 19 | ``` 20 | Your script should output the tenth line, which is: 21 | ``` 22 | Line 10 23 | ``` 24 | 25 | ## Solution 26 | 27 | 直接使用sed搞定 28 | 29 | ## Code 30 | ```bash 31 | #!/bin/bash 32 | sed -n '10p' file.txt 33 | ``` 34 | -------------------------------------------------------------------------------- /shell/TenthLine/file.txt: -------------------------------------------------------------------------------- 1 | Line 1 2 | Line 2 3 | Line 3 4 | Line 4 5 | Line 5 6 | Line 6 7 | Line 7 8 | Line 8 9 | Line 9 10 | Line 10 11 | -------------------------------------------------------------------------------- /shell/TenthLine/tenthLine.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sed -n '10p' file.txt 3 | -------------------------------------------------------------------------------- /shell/TransposeFile/README.md: -------------------------------------------------------------------------------- 1 | # Transpose File 2 | 3 | ## Problem 4 | 5 | Given a text file `file.txt`, transpose its content. 6 | 7 | You may assume that each row has the same number of columns and each field is separated by the ' ' character. 8 | 9 | For example, if file.txt has the following content: 10 | ``` 11 | name age 12 | alice 21 13 | ryan 30 14 | ``` 15 | Output the following: 16 | ``` 17 | name alice ryan 18 | age 21 30 19 | ``` 20 | 21 | ## Solution 22 | 23 | 使用awk解决,使用一个数组保存每列的值,每读取一行,把每列追加到对应的列内容上。 24 | 25 | ## Code 26 | 27 | ``` 28 | #!/bin/bash 29 | awk ' 30 | { 31 | for (i = 1; i <= NF; i++) { 32 | if (NR == 1) { 33 | result[i] = $i; 34 | } else { 35 | result[i] = result[i] " " $i 36 | } 37 | } 38 | } 39 | END { 40 | for (i = 1; result[i] != ""; i++) { 41 | print result[i]; 42 | } 43 | }' file.txt 44 | ``` 45 | -------------------------------------------------------------------------------- /shell/TransposeFile/file.txt: -------------------------------------------------------------------------------- 1 | name age 2 | alice 21 3 | ryan 30 4 | -------------------------------------------------------------------------------- /shell/TransposeFile/transposeFile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | file='file.txt' 3 | len=$(awk 'FNR==1{print NF}' $file) 4 | for i in $(seq 1 $len) 5 | do 6 | cat $file | cut -d' ' -f $i | tr '\n' ' ' | sed 's/ $//g' 7 | echo 8 | done 9 | -------------------------------------------------------------------------------- /shell/TransposeFile/transposeFile2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | awk ' 3 | { 4 | for (i = 1; i <= NF; i++) { 5 | if (NR == 1) { 6 | result[i] = $i; 7 | } else { 8 | result[i] = result[i] " " $i 9 | } 10 | } 11 | } 12 | END { 13 | for (i = 1; result[i] != ""; i++) { 14 | print result[i]; 15 | } 16 | }' file.txt 17 | -------------------------------------------------------------------------------- /shell/ValidPhoneNumbers/README.md: -------------------------------------------------------------------------------- 1 | # Valid Phone Numbers 2 | 3 | ## Problem 4 | 5 | Given a text file `file.txt` that contains list of phone numbers (one per line), write a one liner bash script to print all valid phone numbers. 6 | 7 | You may assume that a valid phone number must appear in one of the following two formats: (xxx) xxx-xxxx or xxx-xxx-xxxx. (x means a digit) 8 | 9 | You may also assume each line in the text file must not contain leading or trailing white spaces. 10 | 11 | For example, assume that `file.txt` has the following content: 12 | ``` 13 | 987-123-4567 14 | 123 456 7890 15 | (123) 456-7890 16 | ``` 17 | Your script should output the following valid phone numbers: 18 | ``` 19 | 987-123-4567 20 | (123) 456-7890 21 | ``` 22 | 23 | ## Solution 24 | 25 | 直接`grep`实现,使用-P选项,使用`perl`正则表达式。 26 | 27 | ## Code 28 | 29 | ```bash 30 | #!/bin/bash 31 | grep -P '(^(\d{3}-){2}\d{4}$)|(^\(\d{3}\) \d{3}-\d{4}$)' file.txt 32 | ``` 33 | -------------------------------------------------------------------------------- /shell/ValidPhoneNumbers/file.txt: -------------------------------------------------------------------------------- 1 | 987-123-4567 2 | 123 456 7890 3 | (123) 456-7890 4 | 0(001) 345-0000 5 | -------------------------------------------------------------------------------- /shell/ValidPhoneNumbers/validPhoneNumbers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | grep -P '(^(\d{3}-){2}\d{4}$)|(^\(\d{3}\) \d{3}-\d{4}$)' file.txt 3 | -------------------------------------------------------------------------------- /shell/WordFrequency/README.md: -------------------------------------------------------------------------------- 1 | # Word Frequency 2 | 3 | ## Problem 4 | 5 | Write a bash script to calculate the frequency of each word in a text file words.txt. 6 | 7 | For simplicity sake, you may assume: 8 | 9 | * words.txt contains only lowercase characters and space ' ' characters. 10 | * Each word must consist of lowercase characters only. 11 | * Words are separated by one or more whitespace characters. 12 | 13 | For example, assume that `words.txt` has the following content: 14 | ``` 15 | the day is sunny the the 16 | the sunny is is 17 | ``` 18 | Your script should output the following, sorted by descending frequency: 19 | ``` 20 | the 4 21 | is 3 22 | sunny 2 23 | day 1 24 | ``` 25 | 26 | ## Solution 27 | 28 | 可以使用[关联数组实现](https://github.com/krystism/notes/blob/master/linux/wordCount.md) 29 | 30 | 后面需要按频数降序排序可以使用`sort`实现 31 | 32 | * -n 表示按照数值排序,而不是默认的字典排序 33 | * -t & -k 其中-t指定字段分隔符,-k表示排序的字段 34 | * -r 表示降序。 35 | 36 | 代码为: 37 | ```bash 38 | #!/bin/bash 39 | declare -A count 40 | for word in $(cat words.txt) 41 | do 42 | let count[$word]++ 43 | done 44 | (for word in ${!count[@]} 45 | do 46 | printf "%s %d\n" $word ${count[$word]} 47 | done) | sort -n -r -t ' ' -k 2 48 | ``` 49 | -------------------------------------------------------------------------------- /shell/WordFrequency/wordFrequency.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | declare -A count 3 | for word in $(cat words.txt) 4 | do 5 | let count[$word]++ 6 | done 7 | (for word in ${!count[@]} 8 | do 9 | printf "%s %d\n" $word ${count[$word]} 10 | done) | sort -n -r -t ' ' -k 2 11 | -------------------------------------------------------------------------------- /shell/WordFrequency/words.txt: -------------------------------------------------------------------------------- 1 | the day is sunny the the 2 | the sunny is is 3 | --------------------------------------------------------------------------------