├── .gitignore ├── README.md ├── SwordToOffer ├── countDigitOne.java ├── countDigitOne.md ├── exist.java ├── exist.md ├── fib.java ├── fib.md ├── findNthDigit.java ├── findNthDigit.md ├── findNumberIn2DArray.java ├── findNumberIn2DArray.md ├── findRepeatNumber.java ├── findRepeatNumber.md ├── firstUniqChar.java ├── firstUniqChar.md ├── getIntersectionNode.java ├── getIntersectionNode.md ├── isStraight.java ├── isStraight.md ├── lowestCommonAncestor.java ├── lowestCommonAncestor.md ├── lowestCommonAncestor2.java ├── lowestCommonAncestor2.md ├── replaceSpace.java ├── replaceSpace.md ├── reverseLeftWords.java ├── reverseLeftWords.md ├── reversePrint.java └── reversePrint.md ├── WeekContest ├── CustomStack.java ├── CustomStack.md ├── UndergroundSystem.java ├── UndergroundSystem.md ├── balanceBST.java ├── balanceBST.md ├── buildArray.java ├── buildArray.md ├── countTriplets.java ├── countTriplets.md ├── createTargetArray.java ├── createTargetArray.md ├── destCity.java ├── destCity.md ├── displayTable.java ├── displayTable.md ├── entityParser.java ├── entityParser.md ├── findDiagonalOrder2.java ├── findDiagonalOrder2.md ├── findLucky.java ├── findLucky.md ├── frogPosition.java ├── frogPosition.md ├── generateTheString.java ├── generateTheString.md ├── getTriggerTime.java ├── getTriggerTime.md ├── kLengthApart.java ├── kLengthApart.md ├── longestSubarray.java ├── longestSubarray.md ├── luckyNumbers.java ├── luckyNumbers.md ├── maxScore.java ├── maxScore.md ├── maxScore2.java ├── maxScore2.md ├── minCount.java ├── minCount.md ├── minNumberOfFrogs.java ├── minNumberOfFrogs.md ├── minSubsequence.java ├── minSubsequence.md ├── minTime.java ├── minTime.md ├── numOfMinutes.java ├── numOfMinutes.md ├── numSteps.java ├── numSteps.md ├── numTeams.java ├── numTeams.md ├── numTimesAllBlue.java ├── numTimesAllBlue.md ├── numWays.java ├── numWays.md ├── processQueries.java ├── processQueries.md ├── reformat.java ├── reformat.md ├── stringMatching.java ├── stringMatching.md ├── sumFourDivisors.java └── sumFourDivisors.md ├── easy ├── ArrayAndMatrix │ ├── canThreePartsEqualSum.java │ ├── canThreePartsEqualSum.md │ ├── containsDuplicate.java │ ├── containsDuplicate.md │ ├── distributeCandies.java │ ├── distributeCandies.md │ ├── findErrorNums.java │ ├── findErrorNums645.md │ ├── findLHS.java │ ├── findLHS.jpg │ ├── findLHS.md │ ├── findMaxConsecutiveOnes.java │ ├── findMaxConsecutiveOnes485.md │ ├── findShortestSubArray.java │ ├── findShortestSubArray.md │ ├── hasGroupsSizeX.java │ ├── hasGroupsSizeX.md │ ├── isToeplitzMatrix.java │ ├── isToeplitzMatrix.md │ ├── matrixReshape.java │ ├── matrixReshape.md │ ├── merge88.java │ ├── merge88.md │ ├── moveZeroes.java │ ├── moveZeroes.md │ ├── removeDuplicates.java │ ├── removeDuplicates.md │ ├── removeDuplicates图示.png │ ├── removeElement.java │ ├── removeElement.md │ ├── rotate.java │ ├── rotate.md │ ├── surfaceArea.java │ ├── surfaceArea.md │ └── surfaceArea图示.png ├── BinarySearch │ ├── findTheDistanceValue.java │ ├── findTheDistanceValue.md │ ├── findTheDistanceValue图示.png │ ├── mySqrt.java │ ├── mySqrt.md │ ├── mySqrt图示.png │ ├── nextGreatestLetter.java │ ├── nextGreatestLetter.md │ ├── searchInsert.java │ ├── searchInsert.md │ └── searchInsert图示.png ├── BitOperation │ ├── findComplement.java │ ├── findComplement.md │ ├── getSum.java │ ├── getSum.md │ ├── hammingDistance.java │ ├── hammingDistance.md │ ├── hammingWeight.java │ ├── hammingWeight.md │ ├── hasAlternatingBits.java │ ├── hasAlternatingBits.md │ ├── isPowerOfFour.java │ ├── isPowerOfFour.md │ ├── isPowerOfTwo.java │ ├── isPowerOfTwo.md │ ├── missingNumber.java │ ├── missingNumber.md │ ├── reverseBits.java │ ├── reverseBits.md │ ├── singleNumber.java │ └── singleNumber.md ├── DP │ ├── climbStairs.java │ ├── climbStairs.md │ ├── massage.java │ ├── massage.md │ ├── maxSubArray.java │ ├── maxSubArray.md │ ├── rob198.java │ └── rob198.md ├── LinkedList │ ├── ListNode.java │ ├── deleteDuplicates.java │ ├── deleteDuplicates.jpg │ ├── deleteDuplicates.md │ ├── deleteNode.java │ ├── deleteNode.md │ ├── getIntersectionNode.java │ ├── getIntersectionNode.md │ ├── hasCycle.java │ ├── hasCycle.md │ ├── isPalindrome.java │ ├── isPalindrome.md │ ├── isPalindrome1.jpg │ ├── isPalindrome2.jpg │ ├── mergeTwoLists.java │ ├── mergeTwoLists.jpg │ ├── mergeTwoLists.md │ ├── middleNode.java │ ├── middleNode.jpg │ ├── middleNode.md │ ├── removeElements.java │ ├── removeElements.md │ ├── reverseList.java │ ├── reverseList.jpg │ └── reverseList.md ├── Sort │ ├── getLeastNumbers.java │ ├── getLeastNumbers.md │ ├── intersect350.java │ ├── intersect350.md │ ├── intersection349.java │ ├── intersection349.md │ ├── majorityElement.java │ └── majorityElement.md ├── StackAndQueue │ ├── MinStack155.java │ ├── MinStack155.md │ ├── MyQueue232.java │ ├── MyQueue232.jpg │ ├── MyQueue232.md │ ├── MyStack225.1.jpg │ ├── MyStack225.2.jpg │ ├── MyStack225.java │ ├── MyStack225.md │ ├── getLeastNumbers.java │ ├── getLeastNumbers.md │ ├── isValid20.java │ └── isValid20.md ├── String │ ├── canConstruct.java │ ├── canConstruct.md │ ├── compressString.java │ ├── compressString.md │ ├── countBinarySubstrings.java │ ├── countBinarySubstrings.md │ ├── countCharacters.java │ ├── countCharacters.md │ ├── gcdOfStrings.java │ ├── gcdOfStrings.md │ ├── isAnagram.java │ ├── isAnagram.md │ ├── isIsomorphic.java │ ├── isIsomorphic.md │ ├── isPalindrome.java │ ├── isPalindrome.md │ ├── lengthOfLastWord.java │ ├── lengthOfLastWord.md │ ├── longestPalindrome.java │ ├── longestPalindrome.md │ ├── sortString.java │ └── sortString.md ├── Tree │ ├── averageOfLevels.java │ ├── averageOfLevels.md │ ├── binaryTreePaths.java │ ├── binaryTreePaths.md │ ├── convertBST.java │ ├── convertBST.md │ ├── diameterOfBinaryTree543.java │ ├── diameterOfBinaryTree543.md │ ├── findMode.java │ ├── findMode.md │ ├── findSecondMinimumValue.java │ ├── findSecondMinimumValue.md │ ├── findTarget.java │ ├── findTarget.md │ ├── hasPathSum112.java │ ├── hasPathSum112.md │ ├── invertTree.java │ ├── invertTree.md │ ├── isBalanced110.java │ ├── isBalanced110.md │ ├── isSameTree100.java │ ├── isSameTree100.md │ ├── isSubtree.java │ ├── isSubtree.md │ ├── isSymmetric.java │ ├── isSymmetric.md │ ├── longestUnivaluePath.java │ ├── longestUnivaluePath.md │ ├── lowestCommonAncestor.java │ ├── lowestCommonAncestor.md │ ├── maxDepth106.java │ ├── maxDepth106.md │ ├── mergeTrees.java │ ├── mergeTrees.md │ ├── minDepth.java │ ├── minDepth.md │ ├── pathSum437.java │ ├── pathSum437.md │ ├── sortedArrayToBST.java │ ├── sortedArrayToBST.md │ ├── sumOfLeftLeaves404.java │ ├── sumOfLeftLeaves404.md │ ├── trimBST.java │ └── trimBST.md ├── TwoPoint │ ├── findContinuousSequence.java │ ├── findContinuousSequence.md │ ├── isHappy.java │ ├── isHappy.md │ ├── reverseVowels.java │ ├── reverseVowels.md │ ├── twoSum167.java │ ├── twoSum167.md │ ├── validPalindrome.java │ └── validPalindrome.md └── other │ ├── TwoSum.java │ ├── TwoSum.md │ ├── isRectangleOverlap.java │ ├── isRectangleOverlap.md │ ├── isRectangleOverlap图示.png │ ├── judgeSquareSum633.java │ ├── judgeSquareSum633.md │ ├── numRookCaptures.java │ ├── numRookCaptures.md │ ├── orangesRotting.java │ └── orangesRotting.md ├── hard └── Greedy │ ├── jump.java │ ├── jump.md │ └── jump图示.png └── medium ├── ArrayAndMatrix ├── arrayNesting.java ├── arrayNesting565.md ├── checkSubarraySum.java ├── checkSubarraySum.md ├── constructArray.java ├── constructArray.md ├── kthSmallest.java ├── kthSmallest.md ├── kthSmallest图示.png ├── longestWPI.java ├── longestWPI.md ├── maxChunksToSorted.java ├── maxChunksToSorted.md ├── maxChunksToSorted图示.png ├── nextPermutation.java ├── nextPermutation.md ├── searchMatrix.java ├── searchMatrix.md └── searchMatrix图示.png ├── BFSorDFS ├── findCircleNum.java ├── findCircleNum.md ├── ladderLength.java ├── ladderLength.md ├── ladderLength.png ├── maxDistance.java ├── maxDistance.md ├── pacificAtlantic.java ├── pacificAtlantic.md ├── shortestPathBinaryMatrix.java ├── shortestPathBinaryMatrix.md ├── updateMatrix.java └── updateMatrix.md ├── BackTracking ├── combinationSum.java ├── combinationSum.md ├── combinationSum2.java ├── combinationSum2.md ├── combinationSum3.java ├── combinationSum3.md ├── combine77.java ├── combine77.md ├── exist.java ├── exist.md ├── findSubsequences491.java ├── findSubsequences491.md ├── generateParenthesis.java ├── generateParenthesis.md ├── letterCombinations17.java ├── letterCombinations17.md ├── maxAreaOfIsland.java ├── maxAreaOfIsland.md ├── numIslands.java ├── numIslands.md ├── partition131.java ├── partition131.md ├── permute46.java ├── permute46.md ├── permuteUnique47.java ├── permuteUnique47.md ├── restoreIpAddresses.java ├── restoreIpAddresses.md ├── solve130.java ├── solve130.md ├── subsets78.java ├── subsets78.md ├── subsetsWithDup90.java └── subsetsWithDup90.md ├── BinarySearch ├── findDuplicate.java ├── findDuplicate.md ├── singleNonDuplicate.java └── singleNonDuplicate.md ├── BitOperation ├── singleNumber260.java └── singleNumber260.md ├── DP ├── maxProduct.java ├── maxProduct.md ├── minPathSum64.java ├── minPathSum64.md ├── rob213.java ├── rob213.md ├── rob337.java ├── rob337.md ├── uniquePaths62.java ├── uniquePaths62.md ├── uniquePathsWithObstacles.md └── uniquePathsWithObstacles63.java ├── LinkedList ├── addTwoNumbers.java ├── addTwoNumbers.md ├── deleteDuplicates82.java ├── deleteDuplicates82.jpg ├── deleteDuplicates82.md ├── oddEvenList.java ├── oddEvenList.jpg ├── oddEvenList.md ├── removeNthFromEnd.java ├── removeNthFromEnd.md ├── rotateRight.java ├── rotateRight.md ├── rotateRight图示.png ├── splitListToParts.java ├── splitListToParts.jpg ├── splitListToParts.md ├── swapPairs.java ├── swapPairs.md └── swapPairs图示.png ├── Sort ├── findKthLargest.java ├── findKthLargest.md ├── frequencySort.java ├── frequencySort.md ├── sortColors.java ├── sortColors.md ├── topKFrequent.java └── topKFrequent.md ├── StackAndQueue ├── dailyTemperatures739.java ├── dailyTemperatures739.md ├── nextGreaterElements.java └── nextGreaterElements503.md ├── String ├── countSubstrings647.java ├── countSubstrings647.md ├── longestPalindrome5.java ├── longestPalindrome5.md └── longestPalindrome5图示.png ├── Tree ├── generateTrees95.java ├── generateTrees95.md ├── inorderTraversal.java ├── inorderTraversal.md ├── kthSmallest.java ├── kthSmallest.md ├── lowestCommonAncestor.java ├── lowestCommonAncestor.md ├── numTrees96.java ├── numTrees96.md ├── pathSum113.java └── pathSum113.md └── TwoPoint ├── maxArea.md └── minSubArrayLen.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | -------------------------------------------------------------------------------- /SwordToOffer/countDigitOne.java: -------------------------------------------------------------------------------- 1 | package SwordToOffer; 2 | 3 | /** 4 | * @Time : 2020年5月5日20:11:25 5 | * @Author : yyw@ustc 6 | * @E-mail : yang0@mail.ustc.edu.cn 7 | * @Github : https://github.com/ustcyyw 8 | * @desc : 已总结 9 | */ 10 | 11 | /** 12 | * 输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。 13 | * 例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。 14 | *
15 | * 示例 1: 16 | * 输入:n = 12 17 | * 输出:5 18 | *
19 | * 示例 2: 20 | * 输入:n = 13 21 | * 输出:6 22 | * 23 | *
24 | * 限制: 25 | * 1 <= n < 2^31 26 | *
27 | * 来源:力扣(LeetCode) 28 | * 链接:https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof 29 | */ 30 | public class countDigitOne { 31 | private static int[] count = {0, 1, 20, 300, 4000, 50000, 600000, 7000000, 80000000, 900000000}; 32 | 33 | /** 34 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户 35 | * 内存消耗 :36.6 MB, 在所有 Java 提交中击败了100.00%的用户 36 | */ 37 | public int countDigitOne(int n) { 38 | int res = 0, index = 0, pow = 1, pre = 0; 39 | while (n != 0) { 40 | int num = n % 10; 41 | if (num == 1) { 42 | res += pre + 1 + count[index]; 43 | } else if (num > 1) { 44 | res += pow + num * count[index]; 45 | } 46 | pre = pre + num * pow; 47 | pow *= 10; 48 | index++; 49 | n /= 10; 50 | } 51 | return res; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /SwordToOffer/countDigitOne.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/SwordToOffer/countDigitOne.md -------------------------------------------------------------------------------- /SwordToOffer/exist.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/SwordToOffer/exist.md -------------------------------------------------------------------------------- /SwordToOffer/fib.java: -------------------------------------------------------------------------------- 1 | package SwordToOffer; 2 | 3 | /** 4 | * @Time : 2020年4月14日11:22:35 5 | * @Author : yyw@ustc 6 | * @E-mail : yang0@mail.ustc.edu.cn 7 | * @Github : https://github.com/ustcyyw 8 | * @desc : 9 | */ 10 | 11 | /** 12 | * 写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下: 13 | * F(0) = 0, F(1) = 1 14 | * F(N) = F(N - 1) + F(N - 2), 其中 N > 1. 15 | * 斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。 16 | * 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。 17 | * 18 | * 示例 1: 19 | * 输入:n = 2 20 | * 输出:1 21 | * 22 | * 示例 2: 23 | * 输入:n = 5 24 | * 输出:5 25 | * 26 | * 来源:力扣(LeetCode) 27 | * 链接:https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof 28 | */ 29 | public class fib { 30 | /** 31 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户 32 | * 内存消耗 :36.5 MB, 在所有 Java 提交中击败了100.00%的用户 33 | */ 34 | public int fib(int n) { 35 | if(n == 0) 36 | return 0; 37 | int[] result = new int[n + 1]; 38 | result[1] = 1; 39 | for(int i = 2; i <= n; i++) 40 | result[i] = (result[i - 2] + result[i - 1]) % 1000000007; 41 | return result[n]; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /SwordToOffer/fib.md: -------------------------------------------------------------------------------- 1 | # 面试题10- I. 斐波那契数列 2 | 3 | ### 原题 4 | 写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下: 5 | F(0) = 0, F(1) = 1 6 | F(N) = F(N - 1) + F(N - 2), 其中 N > 1. 7 | 斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。 8 | 9 | 答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。 10 | 11 | 示例 1: 12 | 输入:n = 2 13 | 输出:1 14 | 15 | 示例 2: 16 | 输入:n = 5 17 | 输出:5 18 | 19 | 提示: 20 | 0 <= n <= 100 21 | 注意:本题与主站 509 题相同:https://leetcode-cn.com/problems/fibonacci-number/ 22 | 23 | 来源:力扣(LeetCode) 24 | [链接](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof):https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof 25 | 26 | ### 解法:DP 27 | 28 | ```java 29 | public int fib(int n) { 30 | if(n == 0) 31 | return 0; 32 | int[] result = new int[n + 1]; 33 | result[1] = 1; 34 | for(int i = 2; i <= n; i++) 35 | result[i] = (result[i - 2] + result[i - 1]) % 1000000007; 36 | return result[n]; 37 | } 38 | ``` 39 | 40 | 思路分析: 41 | 42 | * 初学时候肯定都把斐波那契数列用递归来做,但是递归中有很多重复计算。 43 | * 解决重复计算的问题一种是利用记忆化搜索,将已经计算过的结果保存起来,下次需要使用直接拿出来。 44 | * 另外一种方式就是利用动态规划,设定边界条件,通过转移方程进行递推。本题中状态转移方程都已经写出来了,边界条件也给出了,所以直接动态规划即可。 45 | * 这个题还要注意取模,斐波那契数列可以看做很多数累加,对最后累加的最后结果取余,与在相加过程中不断取余用余数相加是一样的。这里如果不在过程中取余,会导致超出32位而出错。 46 | * 时间复杂度为$O(n)$,空间复杂度为$O(n)$。 47 | 48 | 运行结果: 49 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户 50 | -------------------------------------------------------------------------------- /SwordToOffer/findNthDigit.java: -------------------------------------------------------------------------------- 1 | package SwordToOffer; 2 | 3 | /** 4 | * @Time : 2020年5月6日09:55:42 5 | * @Author : yyw@ustc 6 | * @E-mail : yang0@mail.ustc.edu.cn 7 | * @Github : https://github.com/ustcyyw 8 | * @desc : 已总结 9 | */ 10 | 11 | /** 12 | * 数字以0123456789101112131415…的格式序列化到一个字符序列中。 13 | * 在这个序列中,第5位(从下标0开始计数)是5,第13位是1,第19位是4,等等。 14 | * 请写一个函数,求任意第n位对应的数字。 15 | *
16 | * 示例 1: 17 | * 输入:n = 3 18 | * 输出:3 19 | *
20 | * 示例 2: 21 | * 输入:n = 11 22 | * 输出:0 23 | *
24 | * 限制: 25 | * 0 <= n < 2^31 26 | *
27 | * 来源:力扣(LeetCode) 28 | * 链接:https://leetcode-cn.com/problems/shu-zi-xu-lie-zhong-mou-yi-wei-de-shu-zi-lcof 29 | */ 30 | public class findNthDigit { 31 | // 0, 一位数,两位数,三位数……的累计数字的和 32 | private static int[] sum = {10, 190, 2890, 38890, 488890, 5888890, 68888890, 788888890}; 33 | 34 | /** 35 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户 36 | * 内存消耗 :35.8 MB, 在所有 Java 提交中击败了100.00%的用户 37 | */ 38 | public int findNthDigit(int n) { 39 | if (n <= 9) return n; 40 | int i = 0; 41 | for (; i < sum.length && n >= sum[i]; i++) ; 42 | int left = n - sum[i - 1]; 43 | int index = left / (i + 1), offset = left % (i + 1); 44 | String num = String.valueOf((int) Math.pow(10, i) + index); 45 | return num.charAt(offset) - '0'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /SwordToOffer/findNthDigit.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/SwordToOffer/findNthDigit.md -------------------------------------------------------------------------------- /SwordToOffer/findNumberIn2DArray.java: -------------------------------------------------------------------------------- 1 | package SwordToOffer; 2 | 3 | /** 4 | * @Time : 2020年4月14日00:23:40 5 | * @Author : yyw@ustc 6 | * @E-mail : yang0@mail.ustc.edu.cn 7 | * @Github : https://github.com/ustcyyw 8 | * @desc : 已总结 9 | */ 10 | 11 | /** 12 | * 在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。 13 | * 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 14 | *
15 | * 示例: 16 | * 现有矩阵 matrix 如下: 17 | * [ 18 | * [1, 4, 7, 11, 15], 19 | * [2, 5, 8, 12, 19], 20 | * [3, 6, 9, 16, 22], 21 | * [10, 13, 14, 17, 24], 22 | * [18, 21, 23, 26, 30] 23 | * ] 24 | * 给定 target = 5,返回 true。 25 | * 给定 target = 20,返回 false。 26 | *
27 | * 限制: 28 | * 0 <= n <= 1000 29 | * 0 <= m <= 1000 30 | *
31 | * 注意:本题与主站 240 题相同:https://leetcode-cn.com/problems/search-a-2d-matrix-ii/ 32 | *
33 | * 来源:力扣(LeetCode) 34 | * 链接:https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof 35 | */ 36 | public class findNumberIn2DArray { 37 | /** 38 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户 39 | * 内存消耗 :45.4 MB, 在所有 Java 提交中击败了100.00%的用户 40 | */ 41 | public boolean findNumberIn2DArray(int[][] matrix, int target) { 42 | int row = matrix.length; 43 | if (row == 0) 44 | return false; 45 | int col = matrix[0].length; 46 | if (col == 0) 47 | return false; 48 | int i = row - 1, j = 0; 49 | while (i > -1 && j < col) { 50 | if (target > matrix[i][j]) // 右移 51 | j++; 52 | else if (target < matrix[i][j]) 53 | i--; 54 | else return true; 55 | } 56 | return false; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /SwordToOffer/findNumberIn2DArray.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/SwordToOffer/findNumberIn2DArray.md -------------------------------------------------------------------------------- /SwordToOffer/findRepeatNumber.java: -------------------------------------------------------------------------------- 1 | package SwordToOffer; 2 | 3 | /** 4 | * @Time : 2020年4月14日00:19:19 5 | * @Author : yyw@ustc 6 | * @E-mail : yang0@mail.ustc.edu.cn 7 | * @Github : https://github.com/ustcyyw 8 | * @desc : 9 | */ 10 | 11 | /** 12 | * 找出数组中重复的数字。 13 | * 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。 14 | * 数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。 15 | * 16 | * 示例 1: 17 | * 输入: 18 | * [2, 3, 1, 0, 2, 5, 3] 19 | * 输出:2 或 3 20 | * 21 | * 限制: 22 | * 2 <= n <= 100000 23 | * 24 | * 来源:力扣(LeetCode) 25 | * 链接:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof 26 | */ 27 | public class findRepeatNumber { 28 | /** 29 | * 执行用时 :1 ms, 在所有 Java 提交中击败了92.46%的用户 30 | * 内存消耗 :47.4 MB, 在所有 Java 提交中击败了100.00%的用 31 | */ 32 | public int findRepeatNumber(int[] nums) { 33 | int[] count = new int[nums.length]; 34 | for(int i : nums){ 35 | if(count[i] == 1) 36 | return i; 37 | count[i] = 1; 38 | } 39 | return -1; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /SwordToOffer/findRepeatNumber.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/SwordToOffer/findRepeatNumber.md -------------------------------------------------------------------------------- /SwordToOffer/firstUniqChar.java: -------------------------------------------------------------------------------- 1 | package SwordToOffer; 2 | 3 | /** 4 | * @Time : 2020年5月6日16:39:56 5 | * @Author : yyw@ustc 6 | * @E-mail : yang0@mail.ustc.edu.cn 7 | * @Github : https://github.com/ustcyyw 8 | * @desc : 已总结 9 | */ 10 | 11 | /** 12 | * 在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 13 | * 14 | * 示例: 15 | * s = "abaccdeff" 16 | * 返回 "b" 17 | * 18 | * s = "" 19 | * 返回 " " 20 | * 21 | * 限制: 22 | * 0 <= s 的长度 <= 50000 23 | * 24 | * 来源:力扣(LeetCode) 25 | * 链接:https://leetcode-cn.com/problems/di-yi-ge-zhi-chu-xian-yi-ci-de-zi-fu-lcof 26 | */ 27 | public class firstUniqChar { 28 | /** 29 | * 执行用时 :4 ms, 在所有 Java 提交中击败了99.92%的用户 30 | * 内存消耗 :39.7 MB, 在所有 Java 提交中击败了100.00%的用户 31 | */ 32 | public char firstUniqChar(String s) { 33 | int[] count = new int[256]; 34 | char[] chars = s.toCharArray(); 35 | for(char c : chars) 36 | count[c]++; 37 | for(char c : chars){ 38 | if(count[c] == 1) 39 | return c; 40 | } 41 | return ' '; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /SwordToOffer/firstUniqChar.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/SwordToOffer/firstUniqChar.md -------------------------------------------------------------------------------- /SwordToOffer/isStraight.java: -------------------------------------------------------------------------------- 1 | package SwordToOffer; 2 | 3 | /** 4 | * @Time : 2020年5月9日16:32:55 5 | * @Author : yyw@ustc 6 | * @E-mail : yang0@mail.ustc.edu.cn 7 | * @Github : https://github.com/ustcyyw 8 | * @desc : 9 | */ 10 | 11 | import java.util.Arrays; 12 | 13 | /** 14 | * 从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。 15 | * 2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。 16 | *
17 | * 示例 1: 18 | * 输入: [1,2,3,4,5] 19 | * 输出: True 20 | *
21 | * 示例 2: 22 | * 输入: [0,0,1,2,5] 23 | * 输出: True 24 | *
25 | * 限制: 26 | * 数组长度为 5 27 | * 数组的数取值为 [0, 13] . 28 | *
29 | * 来源:力扣(LeetCode)
30 | * 链接:https://leetcode-cn.com/problems/bu-ke-pai-zhong-de-shun-zi-lcof
31 | */
32 | public class isStraight {
33 | /**
34 | * 执行用时 :1 ms, 在所有 Java 提交中击败了84.84%的用户
35 | * 内存消耗 :37.5 MB, 在所有 Java 提交中击败了100.00%的用户
36 | */
37 | public boolean isStraight(int[] nums) {
38 | Arrays.sort(nums);
39 | int countZero = 0, i = 0, gap = 0;
40 | for (; i < 5 && nums[i] == 0; i++)
41 | countZero++;
42 | for (i = i + 1; i < 5; i++) {
43 | if (nums[i] == nums[i - 1])
44 | return false;
45 | if (nums[i] - nums[i - 1] > 1)
46 | gap += nums[i] - nums[i - 1] - 1;
47 | }
48 | return countZero >= gap;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/SwordToOffer/isStraight.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/SwordToOffer/isStraight.md
--------------------------------------------------------------------------------
/SwordToOffer/lowestCommonAncestor.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/SwordToOffer/lowestCommonAncestor.md
--------------------------------------------------------------------------------
/SwordToOffer/lowestCommonAncestor2.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/SwordToOffer/lowestCommonAncestor2.md
--------------------------------------------------------------------------------
/SwordToOffer/replaceSpace.java:
--------------------------------------------------------------------------------
1 | package SwordToOffer;
2 |
3 | /**
4 | * @Time : 2020年4月14日00:33:00
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc : 已总结
9 | */
10 |
11 | /**
12 | * 请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
13 | *
14 | * 示例 1:
15 | * 输入:s = "We are happy."
16 | * 输出:"We%20are%20happy."
17 | *
18 | * 限制:
19 | * 0 <= s 的长度 <= 10000
20 | *
21 | * 来源:力扣(LeetCode)
22 | * 链接:https://leetcode-cn.com/problems/ti-huan-kong-ge-lcof
23 | */
24 | public class replaceSpace {
25 | public String replaceSpace(String s) {
26 | return s.replace(" ", "%20");
27 | }
28 |
29 | /**
30 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
31 | * 内存消耗 :37.2 MB, 在所有 Java 提交中击败了100.00%的用户
32 | */
33 | public String replaceSpace2(String s) {
34 | StringBuilder res = new StringBuilder();
35 | for(char c : s.toCharArray()){
36 | if(c == ' ')
37 | res.append("%20");
38 | else
39 | res.append(c);
40 | }
41 | return res.toString();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/SwordToOffer/replaceSpace.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/SwordToOffer/replaceSpace.md
--------------------------------------------------------------------------------
/SwordToOffer/reverseLeftWords.java:
--------------------------------------------------------------------------------
1 | package SwordToOffer;
2 |
3 | /**
4 | * @Time : 2020年5月9日10:51:00
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | /**
12 | * 字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。
13 | * 请定义一个函数实现字符串左旋转操作的功能。
14 | * 比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
15 | *
16 | * 示例 1:
17 | * 输入: s = "abcdefg", k = 2
18 | * 输出: "cdefgab"
19 | *
20 | * 示例 2:
21 | * 输入: s = "lrloseumgh", k = 6
22 | * 输出: "umghlrlose"
23 | *
24 | * 限制:
25 | * 1 <= k < s.length <= 10000
26 | *
27 | * 来源:力扣(LeetCode)
28 | * 链接:https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof
29 | */
30 | public class reverseLeftWords {
31 | /**
32 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
33 | * 内存消耗 :39.7 MB, 在所有 Java 提交中击败了100.00%的用户
34 | */
35 | public String reverseLeftWords(String s, int n) {
36 | return s.substring(n + 1) + s.substring(0, n + 1);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/SwordToOffer/reverseLeftWords.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/SwordToOffer/reverseLeftWords.md
--------------------------------------------------------------------------------
/SwordToOffer/reversePrint.java:
--------------------------------------------------------------------------------
1 | package SwordToOffer;
2 |
3 | /**
4 | * @Time : 2020年4月14日00:37:36
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc : 已总结
9 | */
10 |
11 | import BaseClass.ListNode;
12 |
13 | import java.util.ArrayList;
14 | import java.util.List;
15 |
16 | /**
17 | *输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
18 | *
19 | * 示例 1:
20 | * 输入:head = [1,3,2]
21 | * 输出:[2,3,1]
22 | *
23 | * 限制:
24 | * 0 <= 链表长度 <= 10000
25 | *
26 | * 来源:力扣(LeetCode)
27 | * 链接:https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof
28 | */
29 | public class reversePrint {
30 | /**
31 | * 执行用时 :2 ms, 在所有 Java 提交中击败了59.23%的用户
32 | * 内存消耗 :40.1 MB, 在所有 Java 提交中击败了100.00%的用户
33 | */
34 | public int[] reversePrint(ListNode head) {
35 | if(head == null)
36 | return new int[0];
37 | List
13 | * 示例 1:
14 | * 输入:n = 4
15 | * 输出:"pppz"
16 | * 解释:"pppz" 是一个满足题目要求的字符串,因为 'p' 出现 3 次,且 'z' 出现 1 次。当然,还有很多其他字符串也满足题目要求,比如:"ohhh" 和 "love"。
17 | *
18 | * 示例 2:
19 | * 输入:n = 2
20 | * 输出:"xy"
21 | * 解释:"xy" 是一个满足题目要求的字符串,因为 'x' 和 'y' 各出现 1 次。当然,还有很多其他字符串也满足题目要求,比如:"ag" 和 "ur"。
22 | * 示例 3:
23 | *
24 | * 输入:n = 7
25 | * 输出:"holasss"
26 | *
27 | * 提示:
28 | * 1 <= n <= 500
29 | *
30 | * 难度:easy
31 | *
32 | * 来源:力扣(LeetCode)
33 | * 链接:https://leetcode-cn.com/problems/generate-a-string-with-characters-that-have-odd-counts
34 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
35 | */
36 | public class generateTheString {
37 | public String generateTheString(int n) {
38 | StringBuilder sb = new StringBuilder();
39 | if (n % 2 == 0) {
40 | for (int i = 0; i < n - 1; i++)
41 | sb.append('a');
42 | sb.append('b');
43 | } else {
44 | for (int i = 0; i < n; i++)
45 | sb.append('a');
46 | }
47 | return sb.toString();
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/WeekContest/generateTheString.md:
--------------------------------------------------------------------------------
1 | # 5352. 生成每种字符都是奇数个的字符串
2 |
3 | ### 原题
4 | 给你一个整数 n,请你返回一个含 n 个字符的字符串,其中每种字符在该字符串中都恰好出现 奇数次 。
5 | 返回的字符串必须只含小写英文字母。如果存在多个满足题目要求的字符串,则返回其中任意一个即可。
6 |
7 | 示例 1:
8 | 输入:n = 4
9 | 输出:"pppz"
10 | 解释:"pppz" 是一个满足题目要求的字符串,因为 'p' 出现 3 次,且 'z' 出现 1 次。当然,还有很多其他字符串也满足题目要求,比如:"ohhh" 和 "love"。
11 |
12 | 示例 2:
13 | 输入:n = 2
14 | 输出:"xy"
15 | 解释:"xy" 是一个满足题目要求的字符串,因为 'x' 和 'y' 各出现 1 次。当然,还有很多其他字符串也满足题目要求,比如:"ag" 和 "ur"。
16 |
17 | 示例 3:
18 | 输入:n = 7
19 | 输出:"holasss"
20 |
21 | 提示:
22 | 1 <= n <= 500
23 |
24 | 来源:力扣(LeetCode)
25 | [链接](https://leetcode-cn.com/problems/generate-a-string-with-characters-that-have-odd-counts):https://leetcode-cn.com/problems/generate-a-string-with-characters-that-have-odd-counts
26 |
27 | ### 解法
28 |
29 | ```java
30 | public String generateTheString(int n) {
31 | StringBuilder sb = new StringBuilder();
32 | if (n % 2 == 0) {
33 | for (int i = 0; i < n - 1; i++)
34 | sb.append('a');
35 | sb.append('b');
36 | } else {
37 | for (int i = 0; i < n; i++)
38 | sb.append('a');
39 | }
40 | return sb.toString();
41 | }
42 | ```
43 |
44 | 思路分析:
45 |
46 | * 只需要找到满足条件的一个字符串。条件是:字符串中的每一个字符,出现次数都是奇数。即没有限定要有几个字符,也没有限定每个字符至少至多能出现几次。
47 | * 那么找最简单的越方便,如果给定的n是奇数,那么我只用一个小写字母构成该长度的字符串就满足题意。如果n是偶数,那么我就用一个小写字母构成n-1位,第n位选另外一个小写字母也满足了题意。
48 | * 为了避免频繁的字符串拼接,使用`StringBuilder`类。
49 | * 时间复杂度是$O(n)$的,空间复杂度也是$O(n)$。
50 |
51 | 运行结果:执行时间1ms。
--------------------------------------------------------------------------------
/WeekContest/getTriggerTime.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/WeekContest/getTriggerTime.md
--------------------------------------------------------------------------------
/WeekContest/kLengthApart.java:
--------------------------------------------------------------------------------
1 | package Niuke;
2 |
3 | /**
4 | * @Time : 2020年5月3日10:38:14
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc : 已总结
9 | */
10 |
11 | /**
12 | * 给你一个由若干 0 和 1 组成的数组 nums 以及整数 k。
13 | * 如果所有 1 都至少相隔 k 个元素,则返回 True ;否则,返回 False 。
14 | *
15 | * 示例 1:
16 | * 输入:nums = [1,0,0,0,1,0,0,1], k = 2
17 | * 输出:true
18 | * 解释:每个 1 都至少相隔 2 个元素。
19 | *
20 | * 示例 2:
21 | * 输入:nums = [1,0,0,1,0,1], k = 2
22 | * 输出:false
23 | * 解释:第二个 1 和第三个 1 之间只隔了 1 个元素。
24 | *
25 | * 示例 3:
26 | * 输入:nums = [1,1,1,1,1], k = 0
27 | * 输出:true
28 | *
29 | * 示例 4:
30 | * 输入:nums = [0,1,0,1], k = 1
31 | * 输出:true
32 | *
33 | * 提示:
34 | * 1 <= nums.length <= 10^5
35 | * 0 <= k <= nums.length
36 | * nums[i] 的值为 0 或 1
37 | *
38 | * 来源:力扣(LeetCode)
39 | * 链接:https://leetcode-cn.com/problems/check-if-all-1s-are-at-least-length-k-places-away
40 | */
41 | public class kLengthApart {
42 | public boolean kLengthApart(int[] nums, int k) {
43 | for (int pre = -100000, next = 0; next < nums.length; next++) {
44 | if (nums[next] == 1) {
45 | if (next - pre <= k)
46 | return false;
47 | pre = next;
48 | }
49 | }
50 | return true;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/WeekContest/kLengthApart.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/WeekContest/kLengthApart.md
--------------------------------------------------------------------------------
/WeekContest/longestSubarray.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/WeekContest/longestSubarray.md
--------------------------------------------------------------------------------
/WeekContest/maxScore.java:
--------------------------------------------------------------------------------
1 | /**
2 | * @Time : 2020年4月26日10:32:41
3 | * @Author : yyw@ustc
4 | * @E-mail : yang0@mail.ustc.edu.cn
5 | * @Github : https://github.com/ustcyyw
6 | * @desc : 已总结
7 | */
8 |
9 | /**
10 | * 给你一个由若干 0 和 1 组成的字符串 s ,
11 | * 请你计算并返回将该字符串分割成两个 非空 子字符串(即 左 子字符串和 右 子字符串)所能获得的最大得分。
12 | * 「分割字符串的得分」为 左 子字符串中 0 的数量加上 右 子字符串中 1 的数量。
13 | *
14 | * 示例 1:
15 | * 输入:s = "011101"
16 | * 输出:5
17 | * 解释:
18 | * 将字符串 s 划分为两个非空子字符串的可行方案有:
19 | * 左子字符串 = "0" 且 右子字符串 = "11101",得分 = 1 + 4 = 5
20 | * 左子字符串 = "01" 且 右子字符串 = "1101",得分 = 1 + 3 = 4
21 | * 左子字符串 = "011" 且 右子字符串 = "101",得分 = 1 + 2 = 3
22 | * 左子字符串 = "0111" 且 右子字符串 = "01",得分 = 1 + 1 = 2
23 | * 左子字符串 = "01110" 且 右子字符串 = "1",得分 = 2 + 1 = 3
24 | *
25 | * 示例 2:
26 | * 输入:s = "00111"
27 | * 输出:5
28 | * 解释:当 左子字符串 = "00" 且 右子字符串 = "111" 时,我们得到最大得分 = 2 + 3 = 5
29 | *
30 | * 示例 3:
31 | * 输入:s = "1111"
32 | * 输出:3
33 | *
34 | * 提示:
35 | * 2 <= s.length <= 500
36 | * 字符串 s 仅由字符 '0' 和 '1' 组成。
37 | *
38 | * 来源:力扣(LeetCode)
39 | * 链接:https://leetcode-cn.com/problems/maximum-score-after-splitting-a-string
40 | */
41 | public class maxScore {
42 | public int maxScore(String s) {
43 | int res = 0;
44 | char[] chars = s.toCharArray();
45 | int left = 0, right = 0;
46 | for (char c : chars) {
47 | if (c == '1')
48 | right++;
49 | }
50 | for (int i = 0; i < s.length() - 1; i++) {
51 | if (chars[i] == '0')
52 | left++;
53 | else right--;
54 | res = Math.max(res, left + right);
55 | }
56 | return res;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/WeekContest/maxScore.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/WeekContest/maxScore.md
--------------------------------------------------------------------------------
/WeekContest/maxScore2.java:
--------------------------------------------------------------------------------
1 | /**
2 | * @Time : 2020年4月26日10:42:15
3 | * @Author : yyw@ustc
4 | * @E-mail : yang0@mail.ustc.edu.cn
5 | * @Github : https://github.com/ustcyyw
6 | * @desc : 已总结
7 | */
8 |
9 | /**
10 | * 几张卡牌 排成一行,每张卡牌都有一个对应的点数。点数由整数数组 cardPoints 给出。
11 | * 每次行动,你可以从行的开头或者末尾拿一张卡牌,最终你必须正好拿 k 张卡牌。
12 | * 你的点数就是你拿到手中的所有卡牌的点数之和。
13 | * 给你一个整数数组 cardPoints 和整数 k,请你返回可以获得的最大点数。
14 | *
15 | * 示例 1:
16 | * 输入:cardPoints = [1,2,3,4,5,6,1], k = 3
17 | * 输出:12
18 | * 解释:第一次行动,不管拿哪张牌,你的点数总是 1 。但是,先拿最右边的卡牌将会最大化你的可获得点数。最优策略是拿右边的三张牌,最终点数为 1 + 6 + 5 = 12 。
19 | *
20 | * 示例 2:
21 | * 输入:cardPoints = [2,2,2], k = 2
22 | * 输出:4
23 | * 解释:无论你拿起哪两张卡牌,可获得的点数总是 4 。
24 | *
25 | * 示例 3:
26 | * 输入:cardPoints = [9,7,7,9,7,7,9], k = 7
27 | * 输出:55
28 | * 解释:你必须拿起所有卡牌,可以获得的点数为所有卡牌的点数之和。
29 | *
30 | * 示例 4:
31 | * 输入:cardPoints = [1,1000,1], k = 1
32 | * 输出:1
33 | * 解释:你无法拿到中间那张卡牌,所以可以获得的最大点数为 1 。
34 | *
35 | * 示例 5:
36 | * 输入:cardPoints = [1,79,80,1,1,1,200,1], k = 3
37 | * 输出:202
38 | *
39 | * 提示:
40 | * 1 <= cardPoints.length <= 10^5
41 | * 1 <= cardPoints[i] <= 10^4
42 | * 1 <= k <= cardPoints.length
43 | *
44 | * 来源:力扣(LeetCode)
45 | * 链接:https://leetcode-cn.com/problems/maximum-points-you-can-obtain-from-cards
46 | */
47 | public class maxScore2 {
48 | public int maxScore(int[] cardPoints, int k) {
49 | int n = cardPoints.length, scoreR = 0, scoreL = 0;
50 | for(int i = 0; i < k; i++)
51 | scoreL += cardPoints[i];
52 | int res = scoreL;
53 | for(int l = 1; l <= k; l++){
54 | scoreL -= cardPoints[k - l];
55 | scoreR += cardPoints[n - l];
56 | res = Math.max(res, scoreR + scoreL);
57 | }
58 | return res;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/WeekContest/maxScore2.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/WeekContest/maxScore2.md
--------------------------------------------------------------------------------
/WeekContest/minCount.java:
--------------------------------------------------------------------------------
1 | /**
2 | * @Time : 2020年4月18日15:01:37
3 | * @Author : yyw@ustc
4 | * @E-mail : yang0@mail.ustc.edu.cn
5 | * @Github : https://github.com/ustcyyw
6 | * @desc : 已总结
7 | */
8 |
9 | /**
10 | * 桌上有 n 堆力扣币,每堆的数量保存在数组 coins 中。
11 | * 我们每次可以选择任意一堆,拿走其中的一枚或者两枚,求拿完所有力扣币的最少次数。
12 | *
13 | * 示例 1:
14 | * 输入:[4,2,1]
15 | * 输出:4
16 | * 解释:第一堆力扣币最少需要拿 2 次,第二堆最少需要拿 1 次,第三堆最少需要拿 1 次,总共 4 次即可拿完。
17 | *
18 | * 示例 2:
19 | * 输入:[2,3,10]
20 | * 输出:8
21 | *
22 | * 限制:
23 | * 1 <= n <= 4
24 | * 1 <= coins[i] <= 10
25 | *
26 | * 来源:力扣(LeetCode)
27 | * 链接:https://leetcode-cn.com/problems/na-ying-bi
28 | */
29 | public class minCount {
30 | /**
31 | * 0 ms
32 | */
33 | public int minCount(int[] coins) {
34 | int res = 0;
35 | for(int i : coins)
36 | res += count(i);
37 | return res;
38 | }
39 |
40 | private int count(int num){
41 | int count = 0;
42 | while(num > 0){
43 | num -= 2;
44 | count++;
45 | }
46 | return count;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/WeekContest/minCount.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/WeekContest/minCount.md
--------------------------------------------------------------------------------
/WeekContest/minNumberOfFrogs.java:
--------------------------------------------------------------------------------
1 |
2 | import java.util.HashMap;
3 | import java.util.Map;
4 |
5 | /**
6 | * @Time : 2020年4月19日11:08:10
7 | * @Author : yyw@ustc
8 | * @E-mail : yang0@mail.ustc.edu.cn
9 | * @Github : https://github.com/ustcyyw
10 | * @desc : 已总结
11 | */
12 | public class minNumberOfFrogs {
13 | private static Map
18 | * 示例 1:
19 | * 输入: [1,2,3,1]
20 | * 输出: true
21 | *
22 | * 示例 2:
23 | * 输入: [1,2,3,4]
24 | * 输出: false
25 | *
26 | * 示例 3:
27 | * 输入: [1,1,1,3,3,4,3,2,4,2]
28 | * 输出: true
29 | *
30 | * 来源:力扣(LeetCode)
31 | * 链接:https://leetcode-cn.com/problems/contains-duplicate
32 | */
33 | public class containsDuplicate {
34 | /**
35 | * 执行用时 :12 ms, 在所有 Java 提交中击败了63.45%的用户
36 | * 内存消耗 :53.6 MB, 在所有 Java 提交中击败了5.11%的用户
37 | */
38 | public boolean containsDuplicate(int[] nums) {
39 | HashSet
14 | * 示例 1:
15 | * 输入: [1,1,0,1,1,1]
16 | * 输出: 3
17 | * 解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3.
18 | *
19 | * 注意:
20 | * 输入的数组只包含 0 和1。
21 | * 输入数组的长度是正整数,且不超过 10,000。
22 | *
23 | * 来源:力扣(LeetCode)
24 | * 链接:https://leetcode-cn.com/problems/max-consecutive-ones
25 | */
26 | public class findMaxConsecutiveOnes {
27 | /**
28 | * 执行用时 :3 ms, 在所有 Java 提交中击败了69.75%的用户
29 | * 内存消耗 :38.7 MB, 在所有 Java 提交中击败了64.94%的用户
30 | */
31 | public int findMaxConsecutiveOnes(int[] nums) {
32 | int result = 0;
33 | int temp = 0;
34 | for (int num : nums) {
35 | if (num == 1)
36 | temp++;
37 | else {
38 | result = Math.max(result, temp);
39 | temp = 0;
40 | }
41 | }
42 | return Math.max(result, temp);
43 | }
44 |
45 | /**
46 | * 执行用时 :4 ms, 在所有 Java 提交中击败了36.84%的用户
47 | * 内存消耗 :39.4 MB, 在所有 Java 提交中击败了36.06%的用户
48 | */
49 | public int findMaxConsecutiveOnes2(int[] nums) {
50 | int pre = -1; // 用来表示上一个为0元素的索引
51 | int result = 0;
52 | for (int i = 0; i < nums.length; i++) {
53 | if (nums[i] == 0) {
54 | result = Math.max(result, i - pre - 1);
55 | pre = i;
56 | }
57 | }
58 | result = Math.max(result, nums.length - pre - 1);
59 | return result;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/easy/ArrayAndMatrix/isToeplitzMatrix.java:
--------------------------------------------------------------------------------
1 | package easy.ArrayAndMatrix;
2 |
3 | /**
4 | * @Time : 2020年2月14日14:13:48
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | /**
12 | * 如果一个矩阵的每一方向由左上到右下的对角线上具有相同元素,那么这个矩阵是托普利茨矩阵。
13 | * 给定一个 M x N 的矩阵,当且仅当它是托普利茨矩阵时返回 True。
14 | *
15 | * 示例 1:
16 | * 输入:
17 | * matrix = [
18 | * [1,2,3,4],
19 | * [5,1,2,3],
20 | * [9,5,1,2]
21 | * ]
22 | * 输出: True
23 | * 解释:
24 | * 在上述矩阵中, 其对角线为:
25 | * "[9]", "[5, 5]", "[1, 1, 1]", "[2, 2, 2]", "[3, 3]", "[4]"。
26 | * 各条对角线上的所有元素均相同, 因此答案是True。
27 | *
28 | * 示例 2:
29 | * 输入:
30 | * matrix = [
31 | * [1,2],
32 | * [2,2]
33 | * ]
34 | * 输出: False
35 | * 解释:
36 | * 对角线"[1, 2]"上的元素不同。
37 | * 说明:
38 | * matrix 是一个包含整数的二维数组。
39 | * matrix 的行数和列数均在 [1, 20]范围内。
40 | * matrix[i][j] 包含的整数在 [0, 99]范围内。
41 | *
42 | * 进阶:
43 | * 如果矩阵存储在磁盘上,并且磁盘内存是有限的,因此一次最多只能将一行矩阵加载到内存中,该怎么办?
44 | * 如果矩阵太大以至于只能一次将部分行加载到内存中,该怎么办?
45 | *
46 | * 来源:力扣(LeetCode)
47 | * 链接:https://leetcode-cn.com/problems/toeplitz-matrix
48 | */
49 | public class isToeplitzMatrix {
50 | /**
51 | * 执行用时 :1 ms, 在所有 Java 提交中击败了100.00%的用户
52 | * 内存消耗 :48.4 MB, 在所有 Java 提交中击败了5.27%的用户
53 | * 这个做法 一次使用了矩阵的两个元素
54 | */
55 | public boolean isToeplitzMatrix(int[][] matrix) {
56 | int column = matrix[0].length;
57 | for (int i = 1; i < matrix.length; i++) {
58 | for (int j = 1; j < column; j++) {
59 | if (matrix[i][j] != matrix[i - 1][j - 1])
60 | return false;
61 | }
62 | }
63 | return true;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/easy/ArrayAndMatrix/isToeplitzMatrix.md:
--------------------------------------------------------------------------------
1 | # 托普利茨矩阵
2 |
3 | ### 原题
4 | 如果一个矩阵的每一方向由左上到右下的对角线上具有相同元素,那么这个矩阵是托普利茨矩阵。
5 | 给定一个 M x N 的矩阵,当且仅当它是托普利茨矩阵时返回 True。
6 |
7 | 示例 1:
8 | 输入:
9 | matrix = [
10 | [1,2,3,4],
11 | [5,1,2,3],
12 | [9,5,1,2]
13 | ]
14 | 输出: True
15 | 解释:
16 | 在上述矩阵中, 其对角线为:
17 | "[9]", "[5, 5]", "[1, 1, 1]", "[2, 2, 2]", "[3, 3]", "[4]"。
18 | 各条对角线上的所有元素均相同, 因此答案是True。
19 |
20 | 示例 2:
21 | 输入:
22 | matrix = [
23 | [1,2],
24 | [2,2]
25 | ]
26 | 输出: False
27 | 解释:
28 | 对角线"[1, 2]"上的元素不同。
29 |
30 | 说明:
31 | matrix 是一个包含整数的二维数组。
32 | matrix 的行数和列数均在 [1, 20]范围内。
33 | matrix[i][j] 包含的整数在 [0, 99]范围内。
34 | 进阶:
35 | 如果矩阵存储在磁盘上,并且磁盘内存是有限的,因此一次最多只能将一行矩阵加载到内存中,该怎么办?
36 | 如果矩阵太大以至于只能一次将部分行加载到内存中,该怎么办?
37 |
38 | 来源:力扣(LeetCode)
39 | [链接](https://leetcode-cn.com/problems/toeplitz-matrix):https://leetcode-cn.com/problems/toeplitz-matrix
40 |
41 | ----
42 |
43 | ### 解法
44 |
45 | ##### 1. 每次仅使用两个元素(我的第一解)
46 |
47 | ```java
48 | public boolean isToeplitzMatrix(int[][] matrix) {
49 | int column = matrix[0].length;
50 | for (int i = 1; i < matrix.length; i++) {
51 | for (int j = 1; j < column; j++) {
52 | if (matrix[i][j] != matrix[i - 1][j - 1])
53 | return false;
54 | }
55 | }
56 | return true;
57 | }
58 | ```
59 |
60 | 思路分析:
61 |
62 | * 观察矩阵其实很容易发现,满足托普利茨矩阵定义的矩阵,从第二行开始,每个元素都与左上角的元素相等。
63 | * 所以只需要一个二层循环,外层循环从第二行开始,内层循环从每行的第二个元素开始(因为第一行,以及其余行的第一个元素都是没有左上角元素的)。如果循环过程中有一组元素不相等,即不满足条件,返回`false`。
64 | * 由于两层循环,遍历了除第一行及每行第一个元素外的所有元素,所以时间复杂度为$O((n-1)(m-1))$;每次仅使用了两个元素,空间复杂度为$O(1)$。
65 |
66 | 运行结果:
67 | * 执行用时 :1 ms, 在所有 Java 提交中击败了100.00%的用户
68 | * 内存消耗 :48.4 MB, 在所有 Java 提交中击败了5.27%的用户
69 |
--------------------------------------------------------------------------------
/easy/ArrayAndMatrix/matrixReshape.java:
--------------------------------------------------------------------------------
1 | package easy.ArrayAndMatrix;
2 |
3 | /**
4 | * @Time : 2020年2月10日16:04:21
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | /**
12 | * 在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。
13 | * 给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表示想要的重构的矩阵的行数和列数。
14 | * 重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。
15 | * 如果具有给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。
16 | *
17 | * 示例 1:
18 | * 输入:
19 | * nums =
20 | * [[1,2],
21 | * [3,4]]
22 | * r = 1, c = 4
23 | * 输出:
24 | * [[1,2,3,4]]
25 | * 解释:
26 | * 行遍历nums的结果是 [1,2,3,4]。新的矩阵是 1 * 4 矩阵, 用之前的元素值一行一行填充新矩阵。
27 | *
28 | * 示例 2:
29 | * 输入:
30 | * nums =
31 | * [[1,2],
32 | * [3,4]]
33 | * r = 2, c = 4
34 | * 输出:
35 | * [[1,2],
36 | * [3,4]]
37 | * 解释:
38 | * 没有办法将 2 * 2 矩阵转化为 2 * 4 矩阵。 所以输出原矩阵。
39 | * 注意:
40 | * 给定矩阵的宽和高范围在 [1, 100]。
41 | * 给定的 r 和 c 都是正数。
42 | *
43 | * 来源:力扣(LeetCode)
44 | * 链接:https://leetcode-cn.com/problems/reshape-the-matrix
45 | */
46 | public class matrixReshape {
47 | /**
48 | * 执行用时 :1 ms, 在所有 Java 提交中击败了100.00%的用户
49 | * 内存消耗 :39.1 MB, 在所有 Java 提交中击败了75.12%的用户
50 | */
51 | public int[][] matrixReshape(int[][] nums, int r, int c) {
52 | if(r * c != nums.length * nums[0].length) // 无法转化的时候,输出原矩阵。
53 | return nums;
54 | int[][] result = new int[r][c];
55 | int count = 0;
56 | for(int[] row: nums)
57 | for(int item: row){
58 | result[count / c][count % c] = item;
59 | count++;
60 | }
61 | return result;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/easy/ArrayAndMatrix/matrixReshape.md:
--------------------------------------------------------------------------------
1 | # 重塑矩阵
2 |
3 | ### 原题
4 |
5 | 在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。
6 | 给出一个由二维数组表示的矩阵,以及两个正整数r和c,分别表示想要的重构的矩阵的行数和列数。
7 | 重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充。
8 | 如果具有**给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。**
9 |
10 | 示例 1:
11 | 输入:
12 | nums =
13 | [[1,2],
14 | [3,4]]
15 | r = 1, c = 4
16 | 输出:
17 | [[1,2,3,4]]
18 | 解释:
19 | 行遍历nums的结果是 [1,2,3,4]。新的矩阵是 1 * 4 矩阵, 用之前的元素值一行一行填充新矩阵。
20 |
21 | 示例 2:
22 | 输入:
23 | nums =
24 | [[1,2],
25 | [3,4]]
26 | r = 2, c = 4
27 | 输出:
28 | [[1,2],
29 | [3,4]]
30 | 解释:
31 | 没有办法将 2 * 2 矩阵转化为 2 * 4 矩阵。 所以输出原矩阵。
32 |
33 | 注意:
34 | 给定矩阵的宽和高范围在 [1, 100]。
35 | 给定的 r 和 c 都是正数。
36 |
37 | 来源:力扣(LeetCode)
38 | [链接](https://leetcode-cn.com/problems/reshape-the-matrix):https://leetcode-cn.com/problems/reshape-the-matrix
39 |
40 | ----
41 |
42 | ### 解法
43 |
44 | ##### 1.我的第一解
45 |
46 | ```java
47 | public int[][] matrixReshape(int[][] nums, int r, int c) {
48 | if(r * c != nums.length * nums[0].length) // 无法转化的时候,输出原矩阵。
49 | return nums;
50 | int[][] result = new int[r][c];
51 | int count = 0;
52 | for(int[] row: nums)
53 | for(int item: row){
54 | result[count / c][count % c] = item;
55 | count++;
56 | }
57 | return result;
58 | }
59 | ```
60 |
61 | 思路分析:
62 |
63 | * 无法完成reshape的意思就是,原矩阵元素无法恰好填充指定行数列数的新矩阵。所以当`r * c != nums.length * nums[0].length`时,返回原矩阵。
64 | * 遍历原矩阵,第`0,1,2...,c-1`个元素放入第一行(索引为0),其中第`0`个元素放入第一列...第`c-1`个元素放入第c-1列。第`c,c+1...,2c-1`个元素放入第二行(索引为1)...
65 | * 以此类推,所以需要一个变量`count`来表示当前是第几个元素,因为索引是从0开始的,所以`count=0`表示第一个元素。第`count`个元素应该放入`count/c`行,`count%c`列。
66 | * 遍历使用嵌套的 `for-each`语句即可,每添加一个元素进入新矩阵中,使得计算`count++`。
67 |
68 | 运行结果:
69 | * 执行用时 :1 ms, 在所有 Java 提交中击败了100.00%的用户
70 | * 内存消耗 :39.1 MB, 在所有 Java 提交中击败了75.12%的用户
--------------------------------------------------------------------------------
/easy/ArrayAndMatrix/merge88.java:
--------------------------------------------------------------------------------
1 | package easy.ArrayAndMatrix;
2 |
3 | /**
4 | * @Time : 2020年2月23日14:08:00
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc : 已总结
9 | */
10 |
11 | /**
12 | * 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
13 | * 说明:
14 | * 初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
15 | * 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
16 | * 示例:
17 | *
18 | * 输入:
19 | * nums1 = [1,2,3,0,0,0], m = 3
20 | * nums2 = [2,5,6], n = 3
21 | *
22 | * 输出: [1,2,2,3,5,6]
23 | *
24 | * 来源:力扣(LeetCode)
25 | * 链接:https://leetcode-cn.com/problems/merge-sorted-array
26 | */
27 | public class merge88 {
28 | /**
29 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
30 | * 内存消耗 :38.3 MB, 在所有 Java 提交中击败了5.25%的用户
31 | * 就是归并排序的 merge 的过程
32 | */
33 | public void merge(int[] nums1, int m, int[] nums2, int n) {
34 | int[] temp = new int[m];
35 | System.arraycopy(nums1, 0, temp, 0, m);
36 |
37 | int i = 0, j = 0;
38 | for(int k = 0; k < m + n; k++){
39 | if(i >= m) nums1[k] = nums2[j++];
40 | else if (j >= n) nums1[k] = temp[i++];
41 | else if(temp[i] > nums2[j]) nums1[k] = nums2[j++];
42 | else nums1[k] = temp[i++];
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/easy/ArrayAndMatrix/merge88.md:
--------------------------------------------------------------------------------
1 | # 88.合并两个有序数组
2 |
3 | ### 原题
4 | 给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
5 |
6 | 说明:
7 | 初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
8 | 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
9 | 示例:
10 |
11 | 输入:
12 | nums1 = [1,2,3,0,0,0], m = 3
13 | nums2 = [2,5,6], n = 3
14 | 输出: [1,2,2,3,5,6]
15 |
16 | 来源:力扣(LeetCode)
17 | [链接](https://leetcode-cn.com/problems/merge-sorted-array):https://leetcode-cn.com/problems/merge-sorted-array
18 |
19 | ----
20 |
21 | ### 解法
22 |
23 | ```java
24 | public void merge(int[] nums1, int m, int[] nums2, int n) {
25 | int[] temp = new int[m];
26 | System.arraycopy(nums1, 0, temp, 0, m);
27 |
28 | int i = 0, j = 0;
29 | for(int k = 0; k < m + n; k++){
30 | if(i >= m) nums1[k] = nums2[j++];
31 | else if (j >= n) nums1[k] = temp[i++];
32 | else if(temp[i] > nums2[j]) nums1[k] = nums2[j++];
33 | else nums1[k] = temp[i++];
34 | }
35 | }
36 | ```
37 |
38 | 思路分析:
39 |
40 | * 这就是归并排序中的归并步骤。实现这一步需要辅助数组,这个题中要归并到`nums1`中,那么我们就用辅助数组来存放其前m个元素。`System.arraycopy(nums1, 0, temp, 0, m);`
41 | * 用`i,j`分别指向`temp,nums2`两个数组的当前元素。单次循环,将`nums1`的`m+n`个位置放满该放的元素。注意,当`i>=m`时,意味着`temp`中的元素已归并完毕,此时就无脑将剩余的`nums2`中的元素放到`nums1`中即可;同理`j>=n`时类似处理。
42 | * 除了上述两种情况,就需要比较两个数组中当前元素,将小的一个放到`num1`中。
43 | * 要复制m个元素到辅助数组,归并又需要放置n+m个元素(单层循环),所以时间复杂度为$O(2m+n)$;空间复杂度为$O(m)$。
44 |
45 | 运行结果:
46 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
47 | * 内存消耗 :38.3 MB, 在所有 Java 提交中击败了5.25%的用户
--------------------------------------------------------------------------------
/easy/ArrayAndMatrix/removeDuplicates.java:
--------------------------------------------------------------------------------
1 | package easy.ArrayAndMatrix;
2 |
3 | /**
4 | * @Time : 2020年3月29日09:38:44
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc : 已总结
9 | */
10 |
11 | /**
12 | * 给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
13 | * 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
14 | *
15 | * 示例 1:
16 | * 给定数组 nums = [1,1,2],
17 | * 函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。
18 | * 你不需要考虑数组中超出新长度后面的元素。
19 | *
20 | * 示例 2:
21 | * 给定 nums = [0,0,1,1,1,2,2,3,3,4],
22 | * 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。
23 | * 你不需要考虑数组中超出新长度后面的元素。
24 | *
25 | *
26 | * 说明:
27 | * 为什么返回数值是整数,但输出的答案是数组呢?
28 | * 请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
29 | * 你可以想象内部操作如下:
30 | * // nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
31 | * int len = removeDuplicates(nums);
32 | *
33 | * // 在函数里修改输入数组对于调用者是可见的。
34 | * // 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
35 | * for (int i = 0; i < len; i++) {
36 | * print(nums[i]);
37 | * }
38 | *
39 | * 来源:力扣(LeetCode)
40 | * 链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array
41 | */
42 | public class removeDuplicates {
43 | /**
44 | * 执行用时 :1 ms, 在所有 Java 提交中击败了99.71%的用户
45 | * 内存消耗 :41.4 MB, 在所有 Java 提交中击败了9.63%的用户
46 | */
47 | public int removeDuplicates(int[] nums) {
48 | if(nums == null || nums.length == 0)
49 | return 0;
50 | int i = 0;
51 | for(int j = i + 1; j < nums.length; j++){
52 | if(nums[j] != nums[i]){
53 | nums[++i] = nums[j];
54 | }
55 | }
56 | return i + 1;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/easy/ArrayAndMatrix/removeDuplicates图示.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/easy/ArrayAndMatrix/removeDuplicates图示.png
--------------------------------------------------------------------------------
/easy/ArrayAndMatrix/removeElement.java:
--------------------------------------------------------------------------------
1 | package easy.ArrayAndMatrix;
2 |
3 | /**
4 | * @Time : 2020年3月29日10:20:04
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | /**
12 | * 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
13 | * 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
14 | * 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
15 | *
16 | * 示例 1:
17 | * 给定 nums = [3,2,2,3], val = 3,
18 | * 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
19 | * 你不需要考虑数组中超出新长度后面的元素。
20 | *
21 | * 示例 2:
22 | * 给定 nums = [0,1,2,2,3,0,4,2], val = 2,
23 | * 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
24 | * 注意这五个元素可为任意顺序。
25 | * 你不需要考虑数组中超出新长度后面的元素。
26 | *
27 | * 说明:
28 | * 为什么返回数值是整数,但输出的答案是数组呢?
29 | * 请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
30 | * 你可以想象内部操作如下:
31 | *
32 | * // nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
33 | * int len = removeElement(nums, val);
34 | *
35 | * // 在函数里修改输入数组对于调用者是可见的。
36 | * // 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
37 | * for (int i = 0; i < len; i++) {
38 | * print(nums[i]);
39 | * }
40 | *
41 | * 来源:力扣(LeetCode)
42 | * 链接:https://leetcode-cn.com/problems/remove-element
43 | */
44 | public class removeElement {
45 | /**
46 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
47 | * 内存消耗 :38.6 MB, 在所有 Java 提交中击败了5.11%的用户
48 | */
49 | public int removeElement(int[] nums, int val) {
50 | if(nums == null || nums.length == 0)
51 | return 0;
52 | int hi = nums.length - 1, lo = 0;
53 | while(lo <= hi){
54 | if(nums[lo] == val){
55 | nums[lo] = nums[hi];
56 | hi--;
57 | } else {
58 | lo++;
59 | }
60 | }
61 | return lo;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/easy/ArrayAndMatrix/surfaceArea.java:
--------------------------------------------------------------------------------
1 | package easy.ArrayAndMatrix;
2 |
3 | /**
4 | * @Time : 2020年3月25日19:40:14
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | /**
12 | * 在 N * N 的网格上,我们放置一些 1 * 1 * 1 的立方体。
13 | * 每个值 v = grid[i][j] 表示 v 个正方体叠放在对应单元格 (i, j) 上。
14 | * 请你返回最终形体的表面积。
15 | *
16 | * 示例 1:
17 | * 输入:[[2]]
18 | * 输出:10
19 | *
20 | * 示例 2:
21 | * 输入:[[1,2],[3,4]]
22 | * 输出:34
23 | *
24 | * 示例 3:
25 | * 输入:[[1,0],[0,2]]
26 | * 输出:16
27 | *
28 | * 示例 4:
29 | * 输入:[[1,1,1],[1,0,1],[1,1,1]]
30 | * 输出:32
31 | *
32 | * 示例 5:
33 | * 输入:[[2,2,2],[2,1,2],[2,2,2]]
34 | * 输出:46
35 | *
36 | *
37 | * 提示:
38 | * 1 <= N <= 50
39 | * 0 <= grid[i][j] <= 50
40 | *
41 | * 来源:力扣(LeetCode)
42 | * 链接:https://leetcode-cn.com/problems/surface-area-of-3d-shapes
43 | */
44 | public class surfaceArea {
45 | /**
46 | * 执行用时 :3 ms, 在所有 Java 提交中击败了98.69%的用户
47 | * 内存消耗 :41 MB, 在所有 Java 提交中击败了90.44%的用户
48 | */
49 | public int surfaceArea(int[][] grid) {
50 | int sum = 0; // 用来记录几个格子上有放立方体
51 | int n = grid.length;
52 | for(int i = 0; i < n; i++){
53 | if(grid[i][0] != 0) sum += 2;
54 | for(int j = 1; j < n; j++){
55 | if(grid[i][j] != 0) sum += 2;
56 | sum += Math.abs(grid[i][j] - grid[i][j - 1]) + Math.abs(grid[j][i] - grid[j - 1][i]);
57 | }
58 | sum += grid[i][n - 1] + grid[i][0] + grid[0][i] + grid[n - 1][i];
59 | }
60 | return sum;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/easy/ArrayAndMatrix/surfaceArea图示.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/easy/ArrayAndMatrix/surfaceArea图示.png
--------------------------------------------------------------------------------
/easy/BinarySearch/findTheDistanceValue图示.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/easy/BinarySearch/findTheDistanceValue图示.png
--------------------------------------------------------------------------------
/easy/BinarySearch/mySqrt.java:
--------------------------------------------------------------------------------
1 | package easy.BinarySearch;
2 |
3 | /**
4 | * @Time : 2020年3月11日15:07:47
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | /**
12 | * 实现 int sqrt(int x) 函数。
13 | * 计算并返回 x 的平方根,其中 x 是非负整数。
14 | * 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
15 | *
16 | * 示例 1:
17 | * 输入: 4
18 | * 输出: 2
19 | *
20 | * 示例 2:
21 | * 输入: 8
22 | * 输出: 2
23 | * 说明: 8 的平方根是 2.82842...,
24 | * 由于返回类型是整数,小数部分将被舍去。
25 | *
26 | * 来源:力扣(LeetCode)
27 | * 链接:https://leetcode-cn.com/problems/sqrtx
28 | * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
29 | */
30 | public class mySqrt {
31 | /**
32 | * 执行用时 :2 ms, 在所有 Java 提交中击败了79.59%的用户
33 | * 内存消耗 :37.3 MB, 在所有 Java 提交中击败了5.09%的用户
34 | */
35 | public int mySqrt(int x) {
36 | long lo = 0, hi = x;
37 | while(lo <= hi){
38 | long mid = (hi - lo) / 2 + lo;
39 | if(mid * mid > x) hi = mid - 1;
40 | else if(mid * mid < x) lo = mid + 1;
41 | else return (int)mid;
42 | }
43 | return (int)hi;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/easy/BinarySearch/mySqrt.md:
--------------------------------------------------------------------------------
1 | # 69. x 的平方根
2 | ### 原题
3 |
4 | 实现 `int sqrt(int x)` 函数。
5 | 计算并返回 *x* 的平方根,其中 *x* 是非负整数。
6 | 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
7 | **示例 1:**
8 |
9 | ```
10 | 输入: 4
11 | 输出: 2
12 | ```
13 |
14 | **示例 2:**
15 |
16 | ```
17 | 输入: 8
18 | 输出: 2
19 | 说明: 8 的平方根是 2.82842...,
20 | 由于返回类型是整数,小数部分将被舍去。
21 | ```
22 |
23 | ### 解法:二分法的运用
24 |
25 | ```java
26 | public int mySqrt(int x) {
27 | long lo = 0, hi = x;
28 | while(lo <= hi){
29 | long mid = (hi - lo) / 2 + lo;
30 | if(mid * mid > x) hi = mid - 1;
31 | else if(mid * mid < x) lo = mid + 1;
32 | else return (int)mid;
33 | }
34 | return (int)hi;
35 | }
36 | ```
37 |
38 | 思路分析:
39 |
40 | * 题目要求找到x的算术平方根,只需要返回整数部分。如果答案为y,则满足$y^2=x$或者$y^2
15 | * 注意:
16 | * 0 ≤ x, y < 2^31.
17 | *
18 | * 示例:
19 | * 输入: x = 1, y = 4
20 | * 输出: 2
21 | * 解释:
22 | * 1 (0 0 0 1)
23 | * 4 (0 1 0 0)
24 | * ↑ ↑
25 | *
26 | * 上面的箭头指出了对应二进制位不同的位置。
27 | *
28 | * 来源:力扣(LeetCode)
29 | * 链接:https://leetcode-cn.com/problems/hamming-distance
30 | */
31 | public class hammingDistance {
32 | /**
33 | * 注意 x y都是正数
34 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
35 | * 内存消耗 :36.3 MB, 在所有 Java 提交中击败了5.05%的用户
36 | */
37 | public int hammingDistance(int x, int y) {
38 | int count = 0;
39 | while (y != 0 || x != 0) { // 直到移位使得都为0,那么更高位均为0,是相等的就不用去统计了。
40 | if ((y & 1) != (x & 1)) // 除了当前位,一定都变0(和0进行与运算),当前位则保留(和1进行与运算)
41 | count++;
42 | y >>= 1; // 右移动一位
43 | x >>= 1;
44 | }
45 | return count;
46 | }
47 |
48 | private int hammingDistance2(int x, int y) {
49 | int n = x ^ y;
50 | int count = 0;
51 | while (n != 0) {
52 | count++;
53 | n = n & (n - 1);
54 | }
55 | return count;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/easy/BitOperation/hammingWeight.java:
--------------------------------------------------------------------------------
1 | package easy.BitOperation;
2 |
3 | /**
4 | * @Time : 2020年3月27日14:19:51
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | /**
12 | * 编写一个函数,输入是一个无符号整数,返回其二进制表达式中数字位数为 ‘1’ 的个数(也被称为汉明重量)。
13 | *
14 | * 示例 1:
15 | * 输入:00000000000000000000000000001011
16 | * 输出:3
17 | * 解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
18 | *
19 | * 示例 2:
20 | * 输入:00000000000000000000000010000000
21 | * 输出:1
22 | * 解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 '1'。
23 | *
24 | * 示例 3:
25 | * 输入:11111111111111111111111111111101
26 | * 输出:31
27 | * 解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 '1'。
28 | *
29 | * 提示:
30 | *
31 | * 请注意,在某些语言(如 Java)中,没有无符号整数类型。
32 | * 在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,
33 | * 其内部的二进制表示形式都是相同的。
34 | * 在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在上面的 示例 3 中,输入表示有符号整数 -3。
35 | *
36 | * 进阶:
37 | * 如果多次调用这个函数,你将如何优化你的算法?
38 | *
39 | * 来源:力扣(LeetCode)
40 | * 链接:https://leetcode-cn.com/problems/number-of-1-bits
41 | */
42 | public class hammingWeight {
43 | /**
44 | * 执行用时 :1 ms, 在所有 Java 提交中击败了99.75%的用户
45 | * 内存消耗 :36.3 MB, 在所有 Java 提交中击败了5.45%的用户
46 | */
47 | public int hammingWeight(int n) {
48 | int count = 0;
49 | while(n != 0){
50 | if((n & 1) == 1)
51 | count++;
52 | n >>>= 1; //
53 | }
54 | return count;
55 | }
56 |
57 | public int hammingWeight2(int n) {
58 | int count = 0;
59 | while(n != 0){
60 | count++;
61 | n = n & (n - 1);
62 | }
63 | return count;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/easy/BitOperation/hasAlternatingBits.java:
--------------------------------------------------------------------------------
1 | package easy.BitOperation;
2 |
3 | /**
4 | * @Time : 2020年3月28日12:01:15
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc : 已总结
9 | */
10 |
11 | /**
12 | * 给定一个正整数,检查他是否为交替位二进制数:换句话说,就是他的二进制数相邻的两个位数永不相等。
13 | *
14 | * 示例 1:
15 | * 输入: 5
16 | * 输出: True
17 | * 解释:
18 | * 5的二进制数是: 101
19 | *
20 | * 示例 2:
21 | * 输入: 7
22 | * 输出: False
23 | * 解释:
24 | * 7的二进制数是: 111
25 | *
26 | * 示例 3:
27 | * 输入: 11
28 | * 输出: False
29 | * 解释:
30 | * 11的二进制数是: 1011
31 | *
32 | * 示例 4:
33 | * 输入: 10
34 | * 输出: True
35 | * 解释:
36 | * 10的二进制数是: 1010
37 | *
38 | * 来源:力扣(LeetCode)
39 | * 链接:https://leetcode-cn.com/problems/binary-number-with-alternating-bits
40 | */
41 | public class hasAlternatingBits {
42 | /**
43 | * 执行用时 :1 ms, 在所有 Java 提交中击败了69.73%的用户
44 | * 内存消耗 :36 MB, 在所有 Java 提交中击败了5.74%的用户
45 | */
46 | public boolean hasAlternatingBits(int n) {
47 | int pre = n & 1;
48 | n >>>= 1;
49 | while(n != 0){
50 | if((n & 1) == pre)
51 | return false;
52 | pre = n & 1;
53 | n >>>= 1;
54 | }
55 | return true;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/easy/BitOperation/hasAlternatingBits.md:
--------------------------------------------------------------------------------
1 | # 693. 交替位二进制数
2 |
3 | ### 原题
4 | 给定一个正整数,检查他是否为交替位二进制数:换句话说,就是他的二进制数相邻的两个位数永不相等。
5 |
6 | 示例 1:
7 | 输入: 5
8 | 输出: True
9 | 解释:
10 | 5的二进制数是: 101
11 |
12 | 示例 2:
13 | 输入: 7
14 | 输出: False
15 | 解释:
16 | 7的二进制数是: 111
17 |
18 | 示例 3:
19 | 输入: 11
20 | 输出: False
21 | 解释:
22 | 11的二进制数是: 1011
23 |
24 | 示例 4:
25 | 输入: 10
26 | 输出: True
27 | 解释:
28 | 10的二进制数是: 1010
29 |
30 | 来源:力扣(LeetCode)
31 | [链接](https://leetcode-cn.com/problems/binary-number-with-alternating-bits):https://leetcode-cn.com/problems/binary-number-with-alternating-bits
32 |
33 | ### 解法:位运算
34 |
35 | ```java
36 | public boolean hasAlternatingBits(int n) {
37 | int pre = n & 1;
38 | n >>>= 1;
39 | while(n != 0){
40 | if((n & 1) == pre)
41 | return false;
42 | pre = n & 1;
43 | n >>>= 1;
44 | }
45 | return true;
46 | }
47 | ```
48 |
49 | 思路分析:
50 |
51 | * 判断某个数的二进制数相邻的两个位数永不相等。所以还是要按顺序知道它二进制数的每一位的数字是多少。参考[191.只出现一次的数字](https://github.com/ustcyyw/yyw_algorithm/blob/master/easy/BitOperation/hammingWeight.md)的做法来获取每一位二进制数字。
52 | * 这里需要拿当前位二进制的数字与前一位二进制的数字进行比较,所以在进入循环之前,先通过`int pre = n & 1`获取第一位二进制的数字。在循环过程中如果发现当前位的数字与前一位相等`(n & 1) == pre`,就返回false。
53 | * 在循环中不断无符号右移n的同时,还要不断更新`pre = n & 1`。
54 | * 时间复杂度:$O(1)$ 。运行时间依赖于数字n的位数。由于这题中n是 32 位数。空间复杂度是$O(1)$的。
55 |
56 | 运行结果:
57 | * 执行用时 :1 ms, 在所有 Java 提交中击败了69.73%的用户
58 | * 内存消耗 :36 MB, 在所有 Java 提交中击败了5.74%的用户
--------------------------------------------------------------------------------
/easy/BitOperation/isPowerOfFour.java:
--------------------------------------------------------------------------------
1 | package easy.BitOperation;
2 |
3 | /**
4 | * @Time : 2020年3月28日11:14:32
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | /**
12 | * 给定一个整数 (32 位有符号整数),请编写一个函数来判断它是否是 4 的幂次方。
13 | *
14 | * 示例 1:
15 | * 输入: 16
16 | * 输出: true
17 | *
18 | * 示例 2:
19 | * 输入: 5
20 | * 输出: false
21 | *
22 | * 进阶:
23 | * 你能不使用循环或者递归来完成本题吗?
24 | *
25 | * 来源:力扣(LeetCode)
26 | * 链接:https://leetcode-cn.com/problems/power-of-four
27 | */
28 | public class isPowerOfFour {
29 | /**
30 | * 执行用时 :1 ms, 在所有 Java 提交中击败了100.00%的用户
31 | * 内存消耗 :36.6 MB, 在所有 Java 提交中击败了5.21%的用户
32 | * 在类载入的时候计算一次 后面都是直接使用了
33 | */
34 | private static int flag; // flag = 715827882
35 | static{
36 | int temp = 2;
37 | for(int i = 0; i <= 14; i++){
38 | flag += temp;
39 | temp <<= 2;
40 | }
41 | }
42 |
43 | /**
44 | * 相比于2的幂,4的幂也只有一位是1,但是这一位必须位于1,3,5这样的奇数位置。
45 | * 所以用一个奇数位为0的mask与要检查的数相与,如果为0,才能说明那一位1出在奇数位上
46 | * 其实 flag = 0xaaaaaaaa
47 | */
48 | public boolean isPowerOfFour(int num) {
49 | return num > 0 && (num & (num - 1)) == 0 && (num & flag) == 0;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/easy/BitOperation/isPowerOfFour.md:
--------------------------------------------------------------------------------
1 | # 342. 4的幂
2 |
3 | ### 原题
4 | 给定一个整数 (32 位有符号整数),请编写一个函数来判断它是否是 4 的幂次方。
5 |
6 | 示例 1:
7 | 输入: 16
8 | 输出: true
9 |
10 | 示例 2:
11 | 输入: 5
12 | 输出: false
13 |
14 | 进阶:
15 | 你能不使用循环或者递归来完成本题吗?
16 |
17 | 来源:力扣(LeetCode)
18 | [链接](https://leetcode-cn.com/problems/power-of-four):https://leetcode-cn.com/problems/power-of-four
19 |
20 | ### 解法:位运算
21 |
22 | ```java
23 | public boolean isPowerOfFour(int num) {
24 | return num > 0 && (num & (num - 1)) == 0 && (num & 0xaaaaaaaa) == 0;
25 | }
26 | ```
27 |
28 | 思路分析:
29 |
30 | * 4的幂也是2的幂,参考[231. 2的幂](https://github.com/ustcyyw/yyw_algorithm/blob/master/easy/BitOperation/isPowerOfTwo.md)。但是4的幂更特殊一些,除了它一定非负,二进制表示只有1位是1以外,唯一的1出现在二进制中的奇数位(比如0,4,16,对应的二进制1出现在0,3,5位)
31 | * 所以该数字在满足为2的幂的基础上`num > 0 && (num & (num - 1)) == 0`,还要去判断二进制的1是否出现在奇数位置。位的与运算,某一位其中之一为0,那么该位的结果就是0。所以可以使用1010这样的序列与要判断的数相与,如果结果为0,就可以保证1只出现在奇数位上。
32 | * 1010这样的32位数字,用16进制表示就是0xaaaaaaaa。
33 | * 所以判断依旧为`num > 0 && (num & (num - 1)) == 0 && (num & 0xaaaaaaaa) == 0`。
34 | * 时间复杂度:$O(1)$ 。空间复杂度是$O(1)$。
35 |
36 | 运行结果:
37 | * 执行用时 :1 ms, 在所有 Java 提交中击败了100.00%的用户
38 | * 内存消耗 :36.6 MB, 在所有 Java 提交中击败了5.21%的用户
39 |
40 |
--------------------------------------------------------------------------------
/easy/BitOperation/isPowerOfTwo.java:
--------------------------------------------------------------------------------
1 | package easy.BitOperation;
2 |
3 | /**
4 | * @Time : 2020年3月28日10:56:58
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | /**
12 | * 给定一个整数,编写一个函数来判断它是否是 2 的幂次方。
13 | *
14 | * 示例 1:
15 | * 输入: 1
16 | * 输出: true
17 | * 解释: 20 = 1
18 | *
19 | * 示例 2:
20 | * 输入: 16
21 | * 输出: true
22 | * 解释: 24 = 16
23 | *
24 | * 示例 3:
25 | * 输入: 218
26 | * 输出: false
27 | *
28 | * 来源:力扣(LeetCode)
29 | * 链接:https://leetcode-cn.com/problems/power-of-two
30 | */
31 | public class isPowerOfTwo {
32 | /**
33 | * 执行用时 :1 ms, 在所有 Java 提交中击败了100.00%的用户
34 | * 内存消耗 :36.8 MB, 在所有 Java 提交中击败了5.50%的用户
35 | */
36 | public boolean isPowerOfTwo(int n) {
37 | if(n < 0)
38 | return false;
39 | int count = 0;
40 | while(n != 0){ // 2的幂次 二进制位级表示只有1个1存在。
41 | if((n & 1) == 1)
42 | count++;
43 | n >>>= 1;
44 | if(count > 1) return false; // 当两个1存在时,肯定不满足条件了 直接返回false
45 | }
46 | return count == 1;
47 | }
48 |
49 | /**
50 | * 评论区别人的做法
51 | * 首先 负数不可能是2的幂
52 | * 2的幂次 二进制位级表示只有1个1存在。
53 | * 有一个技巧 x & (x - 1) 将x位级中最右的一位 1 改为 0。对于2的幂,改了之后一定是一串0000000
54 | */
55 | public boolean isPowerOfTwo2(int n) {
56 | if(n < 0) return false;
57 | return (n & (n - 1)) == 0;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/easy/BitOperation/missingNumber.java:
--------------------------------------------------------------------------------
1 | package easy.BitOperation;
2 |
3 | /**
4 | * @Time : 2020年3月27日17:23:05
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc : 已总结
9 | */
10 |
11 | /**
12 | * 给定一个包含 0, 1, 2, ..., n 中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数。
13 | *
14 | * 示例 1:
15 | * 输入: [3,0,1]
16 | * 输出: 2
17 | *
18 | * 示例 2:
19 | * 输入: [9,6,4,2,3,5,7,0,1]
20 | * 输出: 8
21 | * 说明:
22 | * 你的算法应具有线性时间复杂度。你能否仅使用额外常数空间来实现?
23 | *
24 | * 来源:力扣(LeetCode)
25 | * 链接:https://leetcode-cn.com/problems/missing-number
26 | */
27 |
28 |
29 | public class missingNumber {
30 | /**
31 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
32 | * 内存消耗 :42.7 MB, 在所有 Java 提交中击败了5.07%的用户
33 | * 运用等差数列的做法
34 | */
35 | public int missingNumber(int[] nums) {
36 | int sum = 0;
37 | for(int i : nums)
38 | sum += i;
39 | return nums.length * (nums.length + 1) / 2- sum;
40 | }
41 |
42 | /**
43 | * 使用位运算
44 | * 1.异或满足交换律
45 | * 2.一个数与自己异或等于0。
46 | * 3.一个数与0异或得到它本身
47 | * 先将0,1,2……n进行异或,再将nums中的元素与刚才的结果异或。除了缺失的那个数,其余都与自己通过交换律进行了异或变为0
48 | * 仅有的那个数与一堆0异或,还是它本身
49 | *
50 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
51 | * 内存消耗 :42.6 MB, 在所有 Java 提交中击败了5.07%的用户
52 | */
53 | public int missingNumber2(int[] nums) {
54 | int res = 0;
55 | for(int i = 1; i <= nums.length; i++)
56 | res ^= i;
57 | for(int i : nums)
58 | res ^= i;
59 | return res;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/easy/BitOperation/missingNumber.md:
--------------------------------------------------------------------------------
1 | # 268. 缺失数字
2 |
3 | ### 原题
4 | 给定一个包含 0, 1, 2, ..., n 中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数。
5 |
6 | 示例 1:
7 | 输入: [3,0,1]
8 | 输出: 2
9 |
10 | 示例 2:
11 | 输入: [9,6,4,2,3,5,7,0,1]
12 | 输出: 8
13 |
14 | 说明:
15 | 你的算法应具有线性时间复杂度。你能否仅使用额外常数空间来实现?
16 |
17 | 来源:力扣(LeetCode)
18 | [链接](https://leetcode-cn.com/problems/missing-number):https://leetcode-cn.com/problems/missing-number
19 |
20 | ### 两种解法
21 |
22 | ##### 1.等差数列和
23 |
24 | ```java
25 | public int missingNumber(int[] nums) {
26 | int sum = 0;
27 | for(int i : nums)
28 | sum += i;
29 | return nums.length * (nums.length + 1) / 2- sum;
30 | }
31 | ```
32 |
33 | 思路分析:
34 |
35 | * 1+2+……+n-1+n的和可以直接使用等差数列的求和公式得到。
36 | * 遍历数组,得到数组中所有元素的和,是缺少了一个数的和。用公式得到的和减去数组元素的和就得到了缺失的元素。
37 | * 时间复杂度为$O(n)$,空间复杂度为$O(1)$。
38 |
39 | 运行结果:
40 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
41 | * 内存消耗 :42.7 MB, 在所有 Java 提交中击败了5.07%的用户
42 |
43 | ##### 2.异或的运用
44 |
45 | ```java
46 | public int missingNumber2(int[] nums) {
47 | int res = 0;
48 | for(int i = 1; i <= nums.length; i++)
49 | res ^= i;
50 | for(int i : nums)
51 | res ^= i;
52 | return res;
53 | }
54 | ```
55 |
56 | 思路分析:
57 |
58 | * 在本题中,我们可以想象,如果将1,2,3……n-1,n都放入数组中,那么数组中除了目标元素只出现了一次,其余元素都出现了两次。问题就变成了在一个所有元素都成对出现,但有一个元素只出现了一次的数组中找到只出现了一次的数组。
59 | * 所以可以参考[136.只出现一次的数字](https://github.com/ustcyyw/yyw_algorithm/blob/master/easy/BitOperation/singleNumber.md)使用异或的做法。
60 | * 异或可以将相同的两个数变为0 即 x ^ x = 0
61 | * 异或具有交换律。
62 | * 0与一个数异或结果仍然为该数 0 ^ x = x
63 | * 两个相同的数进行异或操作会得到0,同时异或具有交换律,所以对于这个无序数组,成对的元素依次异或的结果为0。同时0 ^ x = x,所以最终只出现的一个元素会剩下。
64 | * 本题先进行 `1 ^ 2 ^ 3 ^ …… ^ n - 1 ^ n`,再将这个结果与数组中每个元素进行异或得到的结果就是要找的答案。
65 | * 时间复杂度为$O(n)$,空间复杂度为$O(1)$。
66 |
67 | 运行结果:
68 |
69 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
70 | * 内存消耗 :42.6 MB, 在所有 Java 提交中击败了5.07%的用户
--------------------------------------------------------------------------------
/easy/BitOperation/singleNumber.java:
--------------------------------------------------------------------------------
1 | package easy.BitOperation;
2 |
3 | /**
4 | * @Time : 2020年3月1日00:06:43
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | import java.util.HashMap;
12 | import java.util.Map;
13 |
14 | /**
15 | * 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
16 | *
17 | * 说明:
18 | * 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
19 | *
20 | * 示例 1:
21 | * 输入: [2,2,1]
22 | * 输出: 1
23 | *
24 | * 示例 2:
25 | * 输入: [4,1,2,1,2]
26 | * 输出: 4
27 | *
28 | * 来源:力扣(LeetCode)
29 | * 链接:https://leetcode-cn.com/problems/single-number
30 | */
31 | public class singleNumber {
32 | public int singleNumber(int[] nums) {
33 | Map
16 | * 示例 1:
17 | * 输入: 2
18 | * 输出: 2
19 | * 解释: 有两种方法可以爬到楼顶。
20 | * 1. 1 阶 + 1 阶
21 | * 2. 2 阶
22 | *
23 | * 示例 2:
24 | * 输入: 3
25 | * 输出: 3
26 | * 解释: 有三种方法可以爬到楼顶。
27 | * 1. 1 阶 + 1 阶 + 1 阶
28 | * 2. 1 阶 + 2 阶
29 | * 3. 2 阶 + 1 阶
30 | *
31 | * 来源:力扣(LeetCode)
32 | * 链接:https://leetcode-cn.com/problems/climbing-stairs
33 | */
34 |
35 | /**
36 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
37 | * 内存消耗 :36.1 MB, 在所有 Java 提交中击败了5.17%的用户
38 | */
39 | public class climbStairs {
40 | public int climbStairs(int n) {
41 | int[] count = new int[n + 1];
42 | count[0] = 1;
43 | count[1] = 1; // 边界条件
44 | for(int i = 2; i <= n; i++)
45 | count[i] = count[i - 1] + count[i - 2]; // 转移方程
46 | return count[n];
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/easy/DP/climbStairs.md:
--------------------------------------------------------------------------------
1 | # 70.爬楼梯
2 |
3 | ### 原题
4 | 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
5 | 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
6 | 注意:给定 n 是一个正整数。
7 |
8 | 示例 1:
9 | 输入: 2
10 | 输出: 2
11 | 解释: 有两种方法可以爬到楼顶。
12 | 1. 1 阶 + 1 阶
13 | 2. 2 阶
14 |
15 | 示例 2:
16 | 输入: 3
17 | 输出: 3
18 | 解释: 有三种方法可以爬到楼顶。
19 | 1. 1 阶 + 1 阶 + 1 阶
20 | 2. 1 阶 + 2 阶
21 | 3. 2 阶 + 1 阶
22 |
23 | 来源:力扣(LeetCode)
24 | [链接](https://leetcode-cn.com/problems/climbing-stairs):https://leetcode-cn.com/problems/climbing-stairs
25 |
26 | ### 解法:动态规划
27 |
28 | ```java
29 | public int climbStairs(int n) {
30 | int[] count = new int[n + 1];
31 | count[0] = 1;
32 | count[1] = 1; // 边界条件
33 | for(int i = 2; i <= n; i++)
34 | count[i] = count[i - 1] + count[i - 2]; // 转移方程
35 | return count[n];
36 | }
37 | ```
38 |
39 | 思路分析:
40 |
41 | * 题目要求共有多少种方法可以到达楼顶。每一个阶梯都可以选择走两个阶梯或者1个阶梯,看起来是可以通过回溯来解决的计数问题,但其中存在很多重复计算比如1->2->3与1->3两种方式走到第三个阶梯,之后的走法在回溯中都会重复计算。这样的问题 是典型的动态规划的问题。
42 | * 动态规划第一步:确定状态,找子问题及完成问题的最后一步。最后一步是,达到最后一个阶梯有多少种方法。要到达最后一个阶梯,可以从倒数第二个台阶走两阶,也可以从倒数第一个台阶走一阶。所以到达最后一个台阶的方法数,就转化为求两个子问题,到达倒数第一,二个台阶有多少方法,然后再相加。所以状态就是到达第i个台阶有多少种方法。用`count[i]`表示到达第`i`个台阶的方法总数。
43 | * 动态规划第二步:写出状态转移方程。从上面的描述可以直接得出来 转移方程为`count[i] = count[i - 1] + count[i - 2]`。
44 | * 动态规划第三步:边界条件,也就是找到无法通过转移方程得到的结果。大部分情况都是结合状态的实际意义来确定的。在本题中`count[0]=0,count[1]`的意义就是第0阶台阶有一种方法达到,就是不跳;第一阶台阶有一种方法就是从0阶跳一阶。
45 | * 动态规划第四步:确定计算方向,这个看状态方程与边界条件。在本题中显然是从小台阶得到大台阶。
46 | * 时间负责度为$O(n)$,空间复杂度也为$O(n)$。
47 |
48 | 运行结果:
49 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
50 | * 内存消耗 :36.1 MB, 在所有 Java 提交中击败了5.17%的用户
--------------------------------------------------------------------------------
/easy/DP/massage.java:
--------------------------------------------------------------------------------
1 | package easy.DP;
2 |
3 | /**
4 | * @Time : 2020年3月24日00:27:10
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc : 已总结
9 | */
10 |
11 | /**
12 | * 一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。
13 | * 给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。
14 | * 注意:本题相对原题稍作改动
15 | *
16 | * 示例 1:
17 | * 输入: [1,2,3,1]
18 | * 输出: 4
19 | * 解释: 选择 1 号预约和 3 号预约,总时长 = 1 + 3 = 4。
20 | *
21 | * 示例 2:
22 | * 输入: [2,7,9,3,1]
23 | * 输出: 12
24 | * 解释: 选择 1 号预约、 3 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。
25 | *
26 | * 示例 3:
27 | * 输入: [2,1,4,5,3,1,1,3]
28 | * 输出: 12
29 | * 解释: 选择 1 号预约、 3 号预约、 5 号预约和 8 号预约,总时长 = 2 + 4 + 3 + 3 = 12。
30 | *
31 | * 来源:力扣(LeetCode)
32 | * 链接:https://leetcode-cn.com/problems/the-masseuse-lcci
33 | */
34 | public class massage {
35 | public int massage(int[] nums) {
36 | if(nums == null || nums.length == 0)
37 | return 0;
38 | int first = 0, second = nums[0];
39 | for(int i = 1; i < nums.length; i++){
40 | int temp = second;
41 | second = Math.max(nums[i] + first, second);
42 | first = temp;
43 | }
44 | return second;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/easy/DP/massage.md:
--------------------------------------------------------------------------------
1 | # 10.17面试题 17.16. 按摩师
2 | ### 原题
3 |
4 | 一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。
5 |
6 | 示例 1:
7 | 输入: [1,2,3,1]
8 | 输出: 4
9 | 解释: 选择 1 号预约和 3 号预约,总时长 = 1 + 3 = 4。
10 |
11 | 示例 2:
12 | 输入: [2,7,9,3,1]
13 | 输出: 12
14 | 解释: 选择 1 号预约、 3 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。
15 |
16 | 示例 3:
17 | 输入: [2,1,4,5,3,1,1,3]
18 | 输出: 12
19 | 解释: 选择 1 号预约、 3 号预约、 5 号预约和 8 号预约,总时长 = 2 + 4 + 3 + 3 = 12。
20 |
21 | 来源:力扣(LeetCode)
22 | [链接](https://leetcode-cn.com/problems/the-masseuse-lcci):https://leetcode-cn.com/problems/the-masseuse-lcci
23 |
24 | ### 解法
25 |
26 | ```java
27 | public int massage(int[] nums) {
28 | if(nums == null || nums.length == 0)
29 | return 0;
30 | int first = 0, second = nums[0];
31 | for(int i = 1; i < nums.length; i++){
32 | int temp = second;
33 | second = Math.max(nums[i] + first, second);
34 | first = temp;
35 | }
36 | return second;
37 | }
38 | ```
39 |
40 | 思路分析:
41 |
42 | * 这个题其实看一下示例之后很容易发现,就是 [198题.打家劫舍i](https://github.com/ustcyyw/yyw_algorithm/blob/master/easy/DP/rob198.md)。
43 | * 这里做了一个状态压缩,因为计算截至`i`号最大的预约时间只需要`i-1`,`i - 2`的最大预约时间及`nums[i]`。所以只需要用两个变量`first, second`分别表示前一天,前前一天的状态即可。
44 | * 扩展:
45 | * [213.打家劫舍ii](https://github.com/ustcyyw/yyw_algorithm/blob/master/medium/DP/rob213.md)
46 | * [337.打家劫舍iii](https://github.com/ustcyyw/yyw_algorithm/blob/master/medium/DP/rob337.md)
47 |
48 |
--------------------------------------------------------------------------------
/easy/DP/maxSubArray.java:
--------------------------------------------------------------------------------
1 | package easy.DP;
2 |
3 | /**
4 | * @Time : 2020年3月7日12:48:07
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | /**
12 | * 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
13 | *
14 | * 示例:
15 | * 输入: [-2,1,-3,4,-1,2,1,-5,4],
16 | * 输出: 6
17 | * 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
18 | *
19 | * 进阶:
20 | * 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
21 | *
22 | * 来源:力扣(LeetCode)
23 | * 链接:https://leetcode-cn.com/problems/maximum-subarray
24 | */
25 | public class maxSubArray {
26 | /**
27 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
28 | * 内存消耗 :41.6 MB, 在所有 Java 提交中击败了8.46%的用户
29 | * 贪心算法
30 | */
31 | public int maxSubArray(int[] nums) {
32 | int res = nums[0];
33 | int sum = nums[0];
34 | for(int i = 1; i < nums.length; i++){
35 | if(sum < 0) // 如果sum已经是负资产了,说明前面选定的子序列对于后面不论子序列在哪里结束都是负面影响,从当前元素开始尝试
36 | sum = nums[i];
37 | else // 如果sum是正的,当前元素为必然要加上,当前元素为负则加上看sum还是不是正资产,判断交由下一次循环来判断。
38 | sum += nums[i];
39 | res = Math.max(res, sum); // 因为每次循环都在记录最大和,所以不会出现遗漏。
40 | }
41 | return res;
42 | }
43 |
44 | /**
45 | * DP
46 | * 执行用时 :1 ms, 在所有 Java 提交中击败了98.60%的用户
47 | * 内存消耗 :41.5 MB, 在所有 Java 提交中击败了8.61%的用户
48 | *
49 | * 可以和152对照着看
50 | */
51 | public int maxSubArray2(int[] nums) {
52 | int[] count = new int[nums.length]; // count[i] 表示 0~i 这些元素 所有以nums[i]为结尾的连续子序列中 的最大和
53 | count[0] = nums[0];
54 | for(int i = 1; i < nums.length; i++){
55 | count[i] = Math.max(count[i - 1] + nums[i], nums[i]);
56 | }
57 | int res = Integer.MIN_VALUE;
58 | for(int i : count)
59 | res = Math.max(res, i);
60 | return res;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/easy/DP/rob198.java:
--------------------------------------------------------------------------------
1 | package easy.DP;
2 |
3 | /**
4 | * @Time : 2020年2月26日23:42:01
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc : 已总结
9 | */
10 |
11 |
12 | /**
13 | * 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,
14 | * 如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
15 | * 给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。
16 | *
17 | * 示例 1:
18 | * 输入: [1,2,3,1]
19 | * 输出: 4
20 | * 解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
21 | * 偷窃到的最高金额 = 1 + 3 = 4 。
22 | *
23 | * 示例 2:
24 | * 输入: [2,7,9,3,1]
25 | * 输出: 12
26 | * 解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
27 | * 偷窃到的最高金额 = 2 + 9 + 1 = 12 。
28 | *
29 | * 来源:力扣(LeetCode)
30 | * 链接:https://leetcode-cn.com/problems/house-robber
31 | */
32 | public class rob198 {
33 | /**
34 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
35 | * 内存消耗 :37 MB, 在所有 Java 提交中击败了5.21%的用户
36 | */
37 | public int rob(int[] nums) {
38 | int n = nums.length;
39 | if(n == 0) return 0;
40 | int[] amount = new int[n + 1]; // amount[i]的意义是截至第i家,能偷的最多的钱为amount[i]
41 | amount[0] = 0;
42 | amount[1] = nums[0];
43 | for(int i = 2; i <= n; i++){
44 | amount[i] = Math.max(amount[i - 1], amount[i - 2] + nums[i - 1]);
45 | }
46 | return amount[n];
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/easy/DP/rob198.md:
--------------------------------------------------------------------------------
1 | # 198.打家劫舍I
2 |
3 | ### 原题
4 | 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
5 | 给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。
6 |
7 | 示例 1:
8 | 输入: [1,2,3,1]
9 | 输出: 4
10 | 解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
11 | 偷窃到的最高金额 = 1 + 3 = 4 。
12 |
13 | 示例 2:
14 | 输入: [2,7,9,3,1]
15 | 输出: 12
16 | 解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
17 | 偷窃到的最高金额 = 2 + 9 + 1 = 12 。
18 |
19 | 来源:力扣(LeetCode)
20 | [链接](https://leetcode-cn.com/problems/house-robber):https://leetcode-cn.com/problems/house-robber
21 |
22 | ### 解法
23 |
24 | ```java
25 | public int rob(int[] nums) {
26 | int n = nums.length;
27 | if(n == 0) return 0;
28 | int[] amount = new int[n + 1]; // amount[i]的意义是截至第i家,能偷的最多的钱为amount[i]
29 | amount[0] = 0;
30 | amount[1] = nums[0];
31 | for(int i = 2; i <= n; i++){
32 | amount[i] = Math.max(amount[i - 1], amount[i - 2] + nums[i - 1]);
33 | }
34 | return amount[n];
35 | }
36 | ```
37 |
38 | 思路分析:
39 |
40 | * 限制条件,不能偷连续的两家。本题要求出窃取的最高金额,是一个最优问题。可以尝试能不能使用动态规划。
41 | * 最后能偷到的最大金额,最后一家偷还是不偷呢?这取决于截至倒数第二家能偷到的最多金额以及截至倒数第三家能偷到的最多的金额。如果最后一家的钱加上截至倒数第三家的偷取的金额比截至倒数第二家能偷到的最多金额大,那么小偷就选择倒数第二家不偷。否则不如最后一家放弃,拿着截至倒数第二家的金额走。
42 | * 所以存在一个最优子结构,要得到截至第`i`家最多能偷取多少钱,就得先知道截至第`i-1`与截至第`i-2`家最多能偷取多少钱。所以可以确定问题的状态`amount[i]`表示截至第`i`家,能偷的最多的钱。
43 | * 下一个问题就是确定状态转移方程,从前面提到的小偷的决策逻辑可以知道,转移方程`amount[i] = Math.max(amount[i - 1], amount[i - 2] + nums[i - 1]);`
44 | * 确定计算方向,很明显要先知道前面的情况,所以是从小到大进行计算。边界条件的确定需要看哪些元素无法通过状态转移方程得到。第0家不存在,所以`amount[0] = 0`;截至第一家只能偷这一家的钱,所以`amount[1] = nums[0]`。
45 | * 根据状态定义,最终我们要求的就是`count[n]`。
46 | * 只进行了单层遍历,所以时间复杂度为$O(n)$,空间复杂度也为$O(n)$。当然空间复杂度可以做到$O(1)$,只需要两个辅助变量即可。
47 |
48 | 运行结果:
49 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
50 | * 内存消耗 :37 MB, 在所有 Java 提交中击败了5.21%的用户
--------------------------------------------------------------------------------
/easy/LinkedList/ListNode.java:
--------------------------------------------------------------------------------
1 | package easy.linkedList;
2 |
3 | /**
4 | * @Time : 2020年2月3日15:12:23
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 | public class ListNode {
11 | public int val;
12 | ListNode next;
13 |
14 | ListNode(int x) {
15 | val = x;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/easy/LinkedList/deleteDuplicates.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/easy/LinkedList/deleteDuplicates.jpg
--------------------------------------------------------------------------------
/easy/LinkedList/deleteNode.java:
--------------------------------------------------------------------------------
1 | package easy.linkedList;
2 |
3 | import BaseClass.ListNode;
4 |
5 | /**
6 | * @Time : 2020年3月23日19:24:35
7 | * @Author : yyw@ustc
8 | * @E-mail : yang0@mail.ustc.edu.cn
9 | * @Github : https://github.com/ustcyyw
10 | * @desc : 已总结
11 | */
12 |
13 | /**
14 | * 请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。
15 | * 现有一个链表 -- head = [4,5,1,9],它可以表示为:
16 | *
17 | * 示例 1:
18 | * 输入: head = [4,5,1,9], node = 5
19 | * 输出: [4,1,9]
20 | * 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
21 | *
22 | * 示例 2:
23 | * 输入: head = [4,5,1,9], node = 1
24 | * 输出: [4,5,9]
25 | * 解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
26 | *
27 | *
28 | * 说明:
29 | * 链表至少包含两个节点。
30 | * 链表中所有节点的值都是唯一的。
31 | * 给定的节点为非末尾节点并且一定是链表中的一个有效节点。
32 | * 不要从你的函数中返回任何结果。
33 | *
34 | * 来源:力扣(LeetCode)
35 | * 链接:https://leetcode-cn.com/problems/delete-node-in-a-linked-list
36 | */
37 | public class deleteNode {
38 | /**
39 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
40 | * 内存消耗 :38.5 MB, 在所有 Java 提交中击败了5.07%的用户
41 | */
42 | public void deleteNode(ListNode node) {
43 | while(node.next.next != null){
44 | node.val = node.next.val;
45 | node = node.next;
46 | }
47 | node.val = node.next.val;
48 | node.next = null;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/easy/LinkedList/deleteNode.md:
--------------------------------------------------------------------------------
1 | # 237. 删除链表中的节点
2 |
3 | ### 原题
4 | 请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。
5 | 现有一个链表 -- head = [4,5,1,9],它可以表示为:
6 |
7 | 示例 1:
8 | 输入: head = [4,5,1,9], node = 5
9 | 输出: [4,1,9]
10 | 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
11 |
12 | 示例 2:
13 | 输入: head = [4,5,1,9], node = 1
14 | 输出: [4,5,9]
15 | 解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
16 |
17 | 说明:
18 |
19 | 链表至少包含两个节点。
20 | 链表中所有节点的值都是唯一的。
21 | 给定的节点为非末尾节点并且一定是链表中的一个有效节点。
22 | 不要从你的函数中返回任何结果。
23 |
24 | 来源:力扣(LeetCode)
25 | [链接](https://leetcode-cn.com/problems/delete-node-in-a-linked-list):https://leetcode-cn.com/problems/delete-node-in-a-linked-list
26 |
27 | ### 解法
28 |
29 | ```java
30 | public void deleteNode(ListNode node) {
31 | while(node.next.next != null){
32 | node.val = node.next.val;
33 | node = node.next;
34 | }
35 | node.val = node.next.val;
36 | node.next = null;
37 | }
38 | ```
39 |
40 | 思路分析:
41 |
42 | * 这个题的难点在于读题目,给定的输入不是`head`而是要删除的值的结点。没有头结点,就不能通过找到要删除的结点的上一个结点,通过改变连接来删除指定结点。
43 | * 再看一下奇怪的说明。给定结点不是末尾结点,链表包含至少两个结点。如果通过值的覆盖,来完成删除值。那么当前的结点需要用下一个结点的值来覆盖,所以题目说给定结点不是末尾结点。最终是要删除一个值,意味着会减少一个结点,因为覆盖需要一直进行,所以删除的结点只能是尾结点。
44 | * 覆盖结点值是一个简单的迭代`node.val = node.next.val; node = node.next; `。关键在于什么时候停止?删除尾结点,就需要在尾结点的前一个结点停止`while(node.next.next != null)`,然后用尾结点的值覆盖其前一个节点,最后前一个结点的`node.next = null`
45 | * 时间复杂度为$O(n)$,空间复杂度为$O(1)$。
46 |
47 | 运行结果:
48 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
49 | * 内存消耗 :38.5 MB, 在所有 Java 提交中击败了5.07%的用户
--------------------------------------------------------------------------------
/easy/LinkedList/hasCycle.java:
--------------------------------------------------------------------------------
1 | package easy.linkedList;
2 |
3 | /**
4 | * @Time : 2020年2月3日16:16:31
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | import java.util.HashSet;
12 | import java.util.Set;
13 |
14 | /**
15 | * 给定一个链表,判断链表中是否有环。
16 | *
17 | * 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
18 | * 示例 1:
19 | * 输入:head = [3,2,0,-4], pos = 1
20 | * 输出:true
21 | * 解释:链表中有一个环,其尾部连接到第二个节点。
22 | *
23 | * 来源:力扣(LeetCode)
24 | * 链接:https://leetcode-cn.com/problems/linked-list-cycle
25 | */
26 | public class hasCycle {
27 | /**
28 | * 执行用时 :11 ms, 在所有 Java 提交中击败了5.35%的用户
29 | * 内存消耗 :38.1 MB, 在所有 Java 提交中击败了13.83%的用户
30 | */
31 | public boolean hasCycle(ListNode head){
32 | Set
19 | * 示例:
20 | * root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
21 | * 10
22 | * / \
23 | * 5 -3
24 | * / \ \
25 | * 3 2 11
26 | * / \ \
27 | * 3 -2 1
28 | *
29 | * 返回 3。和等于 8 的路径有:
30 | * 1. 5 -> 3
31 | * 2. 5 -> 2 -> 1
32 | * 3. -3 -> 11
33 | *
34 | * 来源:力扣(LeetCode)
35 | * 链接:https://leetcode-cn.com/problems/path-sum-iii
36 | */
37 | public class pathSum437 {
38 | /**
39 | * 评论区大佬的解法
40 | * 3~4秒就解决了
41 | */
42 | private int count;
43 | public int pathSum(TreeNode root, int sum) {
44 | count = 0;
45 | backTrack(root, sum, new int[1000], 0);
46 | return count;
47 | }
48 |
49 | public void backTrack(TreeNode x, int sum, int[] pathItem, int curIndex){
50 | if(x == null) return;
51 |
52 | if(x.val == sum) count++;
53 | for(int i = curIndex - 1, temp = x.val; i >= 0; i--){
54 | temp += pathItem[i];
55 | if(temp == sum)
56 | count++;
57 | }
58 |
59 | pathItem[curIndex] = x.val;
60 | backTrack(x.left, sum, pathItem, curIndex + 1);
61 | backTrack(x.right, sum, pathItem, curIndex + 1);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/easy/Tree/sortedArrayToBST.java:
--------------------------------------------------------------------------------
1 | package easy.Tree;
2 |
3 | /**
4 | * @Time : 2020年3月1日18:35:25
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | import BaseClass.TreeNode;
12 |
13 | /**
14 | * 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
15 | * 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。
16 | *
17 | * 示例:
18 | * 给定有序数组: [-10,-3,0,5,9],
19 | * 一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树:
20 | * 0
21 | * / \
22 | * -3 9
23 | * / /
24 | * -10 5
25 | *
26 | * 来源:力扣(LeetCode)
27 | * 链接:https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree
28 | */
29 | public class sortedArrayToBST {
30 | /**
31 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
32 | * 内存消耗 :41.3 MB, 在所有 Java 提交中击败了5.03%的用户
33 | */
34 | public TreeNode sortedArrayToBST(int[] nums) {
35 | int lo = 0, hi = nums.length - 1;
36 | return create(nums, lo, hi);
37 | }
38 |
39 | private TreeNode create(int[] nums, int lo, int hi){
40 | if(lo > hi) return null;
41 | if(lo == hi) return new TreeNode(nums[lo]);
42 | int mid = (hi - lo) / 2 + lo;
43 | TreeNode temp = new TreeNode(nums[mid]);
44 | temp.left = create(nums, lo, mid - 1);
45 | temp.right = create(nums, mid + 1, hi);
46 | return temp;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/easy/Tree/trimBST.java:
--------------------------------------------------------------------------------
1 | package easy.Tree;
2 |
3 | /**
4 | * @Time : 2020年2月29日14:18:01
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc :
9 | */
10 |
11 | import BaseClass.TreeNode;
12 |
13 | /**
14 | * 给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。
15 | * 你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。
16 | *
17 | * 示例 1:
18 | * 输入:
19 | * 1
20 | * / \
21 | * 0 2
22 | * L = 1
23 | * R = 2
24 | * 输出:
25 | * 1
26 | * \
27 | * 2
28 | *
29 | * 示例 2:
30 | * 输入:
31 | * 3
32 | * / \
33 | * 0 4
34 | * \
35 | * 2
36 | * /
37 | * 1
38 | * L = 1
39 | * R = 3
40 | * 输出:
41 | * 3
42 | * /
43 | * 2
44 | * /
45 | * 1
46 | *
47 | * 来源:力扣(LeetCode)
48 | * 链接:https://leetcode-cn.com/problems/trim-a-binary-search-tree
49 | */
50 | public class trimBST {
51 | /**
52 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
53 | * 内存消耗 :39.5 MB, 在所有 Java 提交中击败了9.09%的用户
54 | * 返回以当前结点为根的已修剪好的数的根结点(可能根结点变化了)。
55 | */
56 | public TreeNode trimBST(TreeNode root, int L, int R) {
57 | if(root == null) return null;
58 | if(root.val < L) return trimBST(root.right, L, R);
59 | if(root.val > R) return trimBST(root.left, L, R);
60 | root.left = trimBST(root.left, L, R); // 涉及到改变树结构的,肯定要改变链接
61 | root.right = trimBST(root.right, L, R); // 通过这两个链接更新,当前结点的左右子树都是修剪过的了。
62 | return root;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/easy/Tree/trimBST.md:
--------------------------------------------------------------------------------
1 | # 669. 修剪二叉搜索树
2 |
3 | ### 原题
4 | 给定一个二叉搜索树,同时给定最小边界L 和最大边界 R。通过修剪二叉搜索树,使得所有节点的值在[L, R]中 (R>=L) 。你可能需要改变树的根节点,所以结果应当返回修剪好的二叉搜索树的新的根节点。
5 |
6 | 示例 1:
7 | 输入:
8 | ```
9 | 1
10 | / \
11 | 0 2
12 | ```
13 | L = 1
14 | R = 2
15 | 输出:
16 | ```
17 | 1
18 | \
19 | 2
20 | ```
21 |
22 | 示例 2:
23 | 输入:
24 | ```
25 | 3
26 | / \
27 | 0 4
28 | \
29 | 2
30 | /
31 | 1
32 | ```
33 | L = 1
34 | R = 3
35 |
36 | 输出:
37 | ```
38 | 3
39 | /
40 | 2
41 | /
42 | 1
43 | ```
44 |
45 | 来源:力扣(LeetCode)
46 | [链接](https://leetcode-cn.com/problems/trim-a-binary-search-tre):https://leetcode-cn.com/problems/trim-a-binary-search-tree
47 |
48 | ### 解法
49 |
50 | ```java
51 | public TreeNode trimBST(TreeNode root, int L, int R) {
52 | if(root == null) return null;
53 | if(root.val < L) return trimBST(root.right, L, R);
54 | if(root.val > R) return trimBST(root.left, L, R);
55 | root.left = trimBST(root.left, L, R); // 涉及到改变树结构的,肯定要改变链接
56 | root.right = trimBST(root.right, L, R); // 通过这两个链接更新,当前结点的左右子树都是修剪过的了。
57 | return root;
58 | }
59 | ```
60 |
61 | 思路分析:
62 |
63 | * 修剪一棵树,如果根结点的值小于给定的左边界`L`,那么当前结点及其左子树就会被修剪掉,修剪后的树应该是其右子树,但是右子树不一定是符合范围的树,所以要对其右子树叶进行修剪,然后返回修剪后的右子树。
64 | * 同理,根结点的值大于给定的右边界`R`,修剪后的树应该是其左子树且要对左子树修剪。
65 | * 涉及到改变树的结构,就需要更新链接,如果当前结点值在范围内,那么修建其左右子树,并且更新左右链接。最后将当前修剪好的子树返回。
66 | * 时间复杂度为$O(n)$, 空间复杂度与树高成正比。
67 |
68 | 运行结果:
69 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
70 | * 内存消耗 :39.5 MB, 在所有 Java 提交中击败了9.09%的用户
71 |
72 |
--------------------------------------------------------------------------------
/easy/TwoPoint/findContinuousSequence.java:
--------------------------------------------------------------------------------
1 | package easy.TwoPoint;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * @Time : 2020年3月6日08:58:05
8 | * @Author : yyw@ustc
9 | * @E-mail : yang0@mail.ustc.edu.cn
10 | * @Github : https://github.com/ustcyyw
11 | * @desc :
12 | */
13 |
14 | /**
15 | * 输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
16 | * 序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
17 | *
18 | * 示例 1:
19 | * 输入:target = 9
20 | * 输出:[[2,3,4],[4,5]]
21 | *
22 | * 示例 2:
23 | * 输入:target = 15
24 | * 输出:[[1,2,3,4,5],[4,5,6],[7,8]]
25 | *
26 | *
27 | * 限制:
28 | * 1 <= target <= 10^5
29 | *
30 | * 来源:力扣(LeetCode)
31 | * 链接:https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof
32 | */
33 | public class findContinuousSequence {
34 | /**
35 | * 执行用时 :4 ms, 在所有 Java 提交中击败了75.32%的用户
36 | * 内存消耗 :37.4 MB, 在所有 Java 提交中击败了100.00%的用户
37 | * 一个指针指向参与相加的最小值,另外一个指针指向参与相加的最大值
38 | */
39 | public int[][] findContinuousSequence(int target) {
40 | if(target == 2) return null;
41 | List
20 | * 示例:
21 | * 输入:19
22 | * 输出:true
23 | * 解释:
24 | * 12 + 92 = 82
25 | * 82 + 22 = 68
26 | * 62 + 82 = 100
27 | * 12 + 02 + 02 = 1
28 | *
29 | * 来源:力扣(LeetCode)
30 | * 链接:https://leetcode-cn.com/problems/happy-number
31 | */
32 | public class isHappy {
33 | /**
34 | * 执行用时 :2 ms, 在所有 Java 提交中击败了51.98%的用户
35 | * 内存消耗 :36.6 MB, 在所有 Java 提交中击败了8.33%的用户
36 | */
37 | public boolean isHappy(int n) {
38 | Set
16 | * 示例1:
17 | *
18 | * 输入: 5
19 | * 输出: True
20 | * 解释: 1 * 1 + 2 * 2 = 5
21 | *
22 | *
23 | * 示例2:
24 | *
25 | * 输入: 3
26 | * 输出: False
27 | *
28 | * 来源:力扣(LeetCode)
29 | * 链接:https://leetcode-cn.com/problems/sum-of-square-numbers
30 | */
31 | public class judgeSquareSum633 {
32 | /**
33 | * 执行用时 :5 ms, 在所有 Java 提交中击败了36.36%的用户
34 | * 内存消耗 :36.3 MB, 在所有 Java 提交中击败了5.18%的用户
35 | */
36 | public boolean judgeSquareSum(int c) {
37 | int end = (int) Math.sqrt(c);
38 | for (int i = 0; i <= end; i++) {
39 | double temp = Math.sqrt(c - i * i);
40 | if (temp == (int) temp)
41 | return true;
42 | }
43 | return false;
44 | }
45 |
46 | /**
47 | * 其它人解法
48 | */
49 | public boolean judgeSquareSum2(int c){
50 | int end = (int) Math.sqrt(c);
51 | int start = 0;
52 | while(start <= end){
53 | int temp = start * start + end * end;
54 | if(temp == c)
55 | return true;
56 | else if(temp < c)
57 | start++;
58 | else end--;
59 | }
60 | return false;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/hard/Greedy/jump.java:
--------------------------------------------------------------------------------
1 | package hard.Greedy;
2 |
3 | /**
4 | * @Time : 2020年5月4日14:18:42
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc : 已总结
9 | */
10 |
11 | /**
12 | * 给定一个非负整数数组,你最初位于数组的第一个位置。
13 | * 数组中的每个元素代表你在该位置可以跳跃的最大长度。
14 | * 你的目标是使用最少的跳跃次数到达数组的最后一个位置。
15 | *
16 | * 示例:
17 | * 输入: [2,3,1,1,4]
18 | * 输出: 2
19 | * 解释: 跳到最后一个位置的最小跳跃数是 2。
20 | * 从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
21 | *
22 | * 说明:
23 | * 假设你总是可以到达数组的最后一个位置。
24 | *
25 | * 来源:力扣(LeetCode)
26 | * 链接:https://leetcode-cn.com/problems/jump-game-ii。
27 | */
28 | public class jump {
29 | /**
30 | * 执行用时 :2 ms, 在所有 Java 提交中击败了94.93%的用户
31 | * 内存消耗 :41.3 MB, 在所有 Java 提交中击败了5.00%的用户
32 | */
33 | public int jump(int[] nums) {
34 | int n = nums.length;
35 | int[] count = new int[n];
36 | int start = 0;
37 | for(int i = 0; i < n && start < n; i++){
38 | if(i + nums[i] < start)
39 | continue;
40 | for(int j = start; j < n && j <= i + nums[i]; j++)
41 | count[j] = count[i] + 1;
42 | start = i + nums[i] + 1;
43 | }
44 | return count[n - 1] - 1;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/hard/Greedy/jump.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/hard/Greedy/jump.md
--------------------------------------------------------------------------------
/hard/Greedy/jump图示.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/hard/Greedy/jump图示.png
--------------------------------------------------------------------------------
/medium/ArrayAndMatrix/checkSubarraySum.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/ArrayAndMatrix/checkSubarraySum.md
--------------------------------------------------------------------------------
/medium/ArrayAndMatrix/constructArray.java:
--------------------------------------------------------------------------------
1 | package medium.ArrayAndMatrix;
2 |
3 | /**
4 | * @Time : 2020年2月13日17:28:23
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc : 已总结
9 | */
10 |
11 | /**
12 | * 给定两个整数 n 和 k,你需要实现一个数组,这个数组包含从 1 到 n 的 n 个不同整数,同时满足以下条件:
13 | * ① 如果这个数组是 [a1, a2, a3, ... , an] ,那么数组 [|a1 - a2|, |a2 - a3|, |a3 - a4|, ... , |an-1 - an|] 中应该有且仅有 k 个不同整数;.
14 | * ② 如果存在多种答案,你只需实现并返回其中任意一种.
15 | *
16 | * 示例 1:
17 | * 输入: n = 3, k = 1
18 | * 输出: [1, 2, 3]
19 | * 解释: [1, 2, 3] 包含 3 个范围在 1-3 的不同整数, 并且 [1, 1] 中有且仅有 1 个不同整数 : 1
20 | *
21 | * 示例 2:
22 | * 输入: n = 3, k = 2
23 | * 输出: [1, 3, 2]
24 | * 解释: [1, 3, 2] 包含 3 个范围在 1-3 的不同整数, 并且 [2, 1] 中有且仅有 2 个不同整数: 1 和 2
25 | *
26 | * 来源:力扣(LeetCode)
27 | * 链接:https://leetcode-cn.com/problems/beautiful-arrangement-ii
28 | */
29 | public class constructArray {
30 | /**
31 | * 执行用时 :1 ms, 在所有 Java 提交中击败了100.00%的用户
32 | * 内存消耗 :44.8 MB, 在所有 Java 提交中击败了5.34%的用户
33 | */
34 | public int[] constructArray(int n, int k) {
35 | int[] result = new int[n];
36 | result[0] = n;
37 | for (int i = k + 1, temp = n - k - 1; i < n; i++, temp--)
38 | result[i] = temp;
39 | for (int i = 1, flag = -1, temp = k; i < k + 1; i++) {
40 | result[i] = result[i - 1] + temp * flag;
41 | flag = -1 * flag;
42 | temp--;
43 | }
44 | return result;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/medium/ArrayAndMatrix/constructArray.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/ArrayAndMatrix/constructArray.md
--------------------------------------------------------------------------------
/medium/ArrayAndMatrix/kthSmallest.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/ArrayAndMatrix/kthSmallest.md
--------------------------------------------------------------------------------
/medium/ArrayAndMatrix/kthSmallest图示.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/ArrayAndMatrix/kthSmallest图示.png
--------------------------------------------------------------------------------
/medium/ArrayAndMatrix/longestWPI.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/ArrayAndMatrix/longestWPI.md
--------------------------------------------------------------------------------
/medium/ArrayAndMatrix/maxChunksToSorted.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/ArrayAndMatrix/maxChunksToSorted.md
--------------------------------------------------------------------------------
/medium/ArrayAndMatrix/maxChunksToSorted图示.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/ArrayAndMatrix/maxChunksToSorted图示.png
--------------------------------------------------------------------------------
/medium/ArrayAndMatrix/nextPermutation.java:
--------------------------------------------------------------------------------
1 | package medium.ArrayAndMatrix;
2 |
3 | /**
4 | * @Time : 2020年3月6日12:03:55
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc : 已总结
9 | */
10 |
11 | import java.util.Arrays;
12 |
13 | /**
14 | * 实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
15 | * 如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
16 | * 必须原地修改,只允许使用额外常数空间。
17 | *
18 | * 以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
19 | * 1,2,3 → 1,3,2
20 | * 3,2,1 → 1,2,3
21 | * 1,1,5 → 1,5,1
22 | *
23 | * 来源:力扣(LeetCode)
24 | * 链接:https://leetcode-cn.com/problems/next-permutation
25 | */
26 | public class nextPermutation {
27 | /**
28 | * 执行用时 :1 ms, 在所有 Java 提交中击败了99.86%的用户
29 | * 内存消耗 :39 MB, 在所有 Java 提交中击败了30.38%的用户
30 | * 要得到下一个更大的数字而且该数字要尽量小,就需要尽量在低位换一个稍大的数字过来。
31 | * 比如通过改变第i位来使数字更大,交换的数字得从i+1,i+2...找。往i-1,i-2找会使得数字更小。
32 | * 要找一个更大的数字,而且要让这个更大的数字尽可能的小,那么就在 i+1,i+2...中找比i大的最小值:
33 | * 如果找不到这样的值,说明i+1,i+2...后面的数字都比i小,不满足题意。
34 | * 如果找到了,进行交换。交换之后,只能保证从0到i位是尽可能小的,i+1,i+2...还不一定,要进行排序才可以。
35 | * 从低位开始,就是从数组右侧开始遍历。
36 | */
37 | public void nextPermutation(int[] nums) {
38 | int n = nums.length - 1;
39 | for (int i = n - 1; i >= 0; i--) {
40 | if (nums[i] < nums[i + 1]) {
41 | int j = nums.length - 1;
42 | for (; j > i && nums[j] <= nums[i]; j--) ;
43 | exch(nums, i, j);
44 | reverse(nums, i + 1, n);
45 | return;
46 | }
47 | }
48 | reverse(nums, 0, n);
49 | }
50 |
51 | private void exch(int[] nums, int i, int j) {
52 | int temp = nums[i];
53 | nums[i] = nums[j];
54 | nums[j] = temp;
55 | }
56 |
57 | private void reverse(int[] nums, int lo, int hi){
58 | while(lo < hi){
59 | exch(nums, lo++, hi--);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/medium/ArrayAndMatrix/nextPermutation.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/ArrayAndMatrix/nextPermutation.md
--------------------------------------------------------------------------------
/medium/ArrayAndMatrix/searchMatrix.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/ArrayAndMatrix/searchMatrix.md
--------------------------------------------------------------------------------
/medium/ArrayAndMatrix/searchMatrix图示.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/ArrayAndMatrix/searchMatrix图示.png
--------------------------------------------------------------------------------
/medium/BFSorDFS/findCircleNum.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/BFSorDFS/findCircleNum.md
--------------------------------------------------------------------------------
/medium/BFSorDFS/ladderLength.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/BFSorDFS/ladderLength.md
--------------------------------------------------------------------------------
/medium/BFSorDFS/ladderLength.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/BFSorDFS/ladderLength.png
--------------------------------------------------------------------------------
/medium/BFSorDFS/pacificAtlantic.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/BFSorDFS/pacificAtlantic.md
--------------------------------------------------------------------------------
/medium/BFSorDFS/shortestPathBinaryMatrix.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/BFSorDFS/shortestPathBinaryMatrix.md
--------------------------------------------------------------------------------
/medium/BFSorDFS/updateMatrix.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/BFSorDFS/updateMatrix.md
--------------------------------------------------------------------------------
/medium/BackTracking/combinationSum3.java:
--------------------------------------------------------------------------------
1 | package medium.Backtracking;
2 |
3 | /**
4 | * @Time : 2020年2月24日15:55:21
5 | * @Author : yyw@ustc
6 | * @E-mail : yang0@mail.ustc.edu.cn
7 | * @Github : https://github.com/ustcyyw
8 | * @desc : 已总结
9 | */
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | /**
15 | * 找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
16 | * 说明:
17 | * 所有数字都是正整数。
18 | * 解集不能包含重复的组合。
19 | * 示例 1:
20 | * 输入: k = 3, n = 7
21 | * 输出: [[1,2,4]]
22 | * 示例 2:
23 | * 输入: k = 3, n = 9
24 | * 输出: [[1,2,6], [1,3,5], [2,3,4]]
25 | *
26 | * 来源:力扣(LeetCode)
27 | * 链接:https://leetcode-cn.com/problems/combination-sum-iii
28 | */
29 | public class combinationSum3 {
30 | private List
28 | * 来源:力扣(LeetCode)
29 | * 链接:https://leetcode-cn.com/problems/combinations
30 | */
31 | public class combine77 {
32 | private List
32 | * 来源:力扣(LeetCode)
33 | * 链接:https://leetcode-cn.com/problems/subsets
34 | */
35 | public class subsets78 {
36 | private List
17 | * 示例:
18 | * 输入: [1,2,2]
19 | * 输出:
20 | * [
21 | * [2],
22 | * [1],
23 | * [1,2,2],
24 | * [2,2],
25 | * [1,2],
26 | * []
27 | * ]
28 | *
29 | * 来源:力扣(LeetCode)
30 | * 链接:https://leetcode-cn.com/problems/subsets-ii
31 | */
32 | public class subsetsWithDup90 {
33 | /**
34 | * 执行用时 :1 ms, 在所有 Java 提交中击败了100.00%的用户
35 | * 内存消耗 :41.8 MB, 在所有 Java 提交中击败了5.01%的用户
36 | * 联系78题 只是多了一点 有重复元素
37 | */
38 | private List
17 | * 示例:
18 | * 输入: [2,0,2,1,1,0]
19 | * 输出: [0,0,1,1,2,2]
20 | *
21 | * 进阶:
22 | * 一个直观的解决方案是使用计数排序的两趟扫描算法。
23 | * 首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
24 | * 你能想出一个仅使用常数空间的一趟扫描算法吗?
25 | *
26 | * 来源:力扣(LeetCode)
27 | * 链接:https://leetcode-cn.com/problems/sort-colors
28 | */
29 | public class sortColors {
30 | /**
31 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
32 | * 内存消耗 :38.5 MB, 在所有 Java 提交中击败了5.02%的用户
33 | * 三向切分的快速排序中切分的步骤
34 | */
35 | public void sortColors(int[] nums) {
36 | for (int i = 0; i < nums.length; i++) {
37 | if (nums[i] == 1){
38 | exch(nums, i, 0);
39 | break;
40 | }
41 | }
42 | int gt = nums.length - 1, lt = 0, i = 1;
43 | while(gt >= i){
44 | if(nums[i] > 1) exch(nums, gt--, i);
45 | else if (nums[i] < 1) exch(nums, lt++, i++);
46 | else i++;
47 | }
48 | }
49 |
50 | private void exch(int[] nums, int i, int j) {
51 | int temp = nums[i];
52 | nums[i] = nums[j];
53 | nums[j] = temp;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/medium/String/longestPalindrome5图示.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustcyyw/yyw_algorithm/d6b3b7204c955d936180d39e2582c21a34eacc34/medium/String/longestPalindrome5图示.png
--------------------------------------------------------------------------------
/medium/Tree/generateTrees95.java:
--------------------------------------------------------------------------------
1 | package medium.Tree;
2 |
3 | import BaseClass.TreeNode;
4 |
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | /**
9 | * @Time : 2020年3月4日12:17:28
10 | * @Author : yyw@ustc
11 | * @E-mail : yang0@mail.ustc.edu.cn
12 | * @Github : https://github.com/ustcyyw
13 | * @desc : 已总结
14 | */
15 | public class generateTrees95 {
16 | /**
17 | * 官方标答:使用递归,选定i为根,则其左子树在[1,2,...i - 1]生成,右子树在[i+1,i+2,...n]生成
18 | * 以i为根一共能生产的BST 为其左子树可能的数量乘右子树可能的数量。
19 | * 执行用时 :1 ms, 在所有 Java 提交中击败了100.00%的用户
20 | * 内存消耗 :41.4 MB, 在所有 Java 提交中击败了5.07%的用户
21 | */
22 | public List> paths) {
52 | Map
> paths){
62 | Map
> result = null;
31 |
32 | /**
33 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
34 | * 内存消耗 :36.8 MB, 在所有 Java 提交中击败了5.08%的用户
35 | */
36 | public List
> combinationSum3(int k, int n) {
37 | result = new ArrayList<>();
38 | if (k >= n || n == 0)
39 | return result;
40 | backTrack3(k, n, 0, 0, 0, new int[k]);
41 | return result;
42 | }
43 |
44 | private void backTrack3(int k, int n, int pre, int curSum, int curIndex, int[] temp) {
45 | if (curSum == n && curIndex == k){
46 | List
> result = null;
33 |
34 | /**
35 | * 执行用时 :9 ms, 在所有 Java 提交中击败了72.85%的用户
36 | * 内存消耗 :42.8 MB, 在所有 Java 提交中击败了11.56%的用户
37 | */
38 | public List
> combine(int n, int k) {
39 | result = new ArrayList<>();
40 | if (k == 0 || k > n)
41 | return result;
42 | backTrack(n, k, 0, new int[k], 0);
43 | return result;
44 | }
45 |
46 | private void backTrack(int n, int k, int pre, int[] temp, int curIndex) {
47 | if (curIndex == k) {
48 | List
> result = null;
21 | public List
> permute(int[] nums) {
22 | result = new ArrayList<>();
23 | if(nums == null || nums.length == 0)
24 | return result;
25 |
26 | List
> result = null;
37 |
38 | /**
39 | * 执行用时 :0 ms, 在所有 Java 提交中击败了100.00%的用户
40 | * 内存消耗 :39.3 MB, 在所有 Java 提交中击败了5.08%的用户
41 | */
42 | public List
> subsets(int[] nums) {
43 | result = new ArrayList<>();
44 | result.add(new ArrayList<>()); // 空集
45 | if (nums.length == 0)
46 | return result;
47 | for (int i = 1; i <= nums.length; i++) {
48 | backTrack(nums, i, 0, new int[i], 0);
49 | }
50 |
51 | return result;
52 | }
53 |
54 | private void backTrack(int[] nums, int k, int start, int[] temp, int curIndex) {
55 | if(curIndex == k){
56 | List
> res;
39 |
40 | public List
> subsetsWithDup(int[] nums) {
41 | res = new ArrayList<>();
42 | res.add(new ArrayList<>());
43 | if (nums == null || nums.length == 0)
44 | return res;
45 | Arrays.sort(nums);
46 | for (int i = 1; i <= nums.length; i++) {
47 | backTrack(nums, i, 0, new int[i], 0);
48 | }
49 | return res;
50 | }
51 |
52 | private void backTrack(int[] nums, int k, int start, int[] temp, int curIndex) {
53 | if (curIndex == k) {
54 | List
> res;
45 | public List
> pathSum(TreeNode root, int sum) {
46 | res = new ArrayList<>();
47 | if(root == null)
48 | return res;
49 | backTrack(root, sum, 0, new ArrayList<>());
50 | return res;
51 | }
52 |
53 | private void backTrack(TreeNode x, int sum, int curSum, List