├── .gitignore ├── README.md ├── shell.sh └── src ├── dailyExercise ├── LeetCodeArray │ ├── ArrayPrint │ │ ├── GenerateMatrix.java │ │ ├── PrintArrayByZ.java │ │ ├── Rotate.java │ │ └── SpiralOrder.java │ ├── FindAnagrams.java │ ├── MaxArea.java │ ├── QuickSort.java │ ├── RemoveElement.java │ ├── Rotate.java │ ├── Search.java │ ├── SortedSquares.java │ └── window │ │ ├── CheckInclusion.java │ │ ├── FindLHS.java │ │ ├── FindMaxAverage.java │ │ ├── LengthOfLongestSubstring.java │ │ ├── MinSubArrayLen.java │ │ ├── MinWindow.java │ │ ├── ShortestSubarray.java │ │ └── TotalFruit.java ├── LeetCodeBacktracking │ ├── CanPartitionKSubsets.java │ ├── CombinationSum.java │ ├── CombinationSum2.java │ ├── CombinationSum3.java │ ├── Combine.java │ ├── FindSubsequences.java │ ├── Partition.java │ ├── Permute.java │ ├── PermuteUnique.java │ ├── RestoreIpAddresses.java │ └── SubsetsWithDup.java ├── LeetCodeDynamicProgram │ ├── Bag │ │ ├── Bag.java │ │ ├── CanPartition.java │ │ ├── FindTargetSumWays.java │ │ └── LastStoneWeightII.java │ └── FullBag │ │ ├── Change.java │ │ ├── CoinChange.java │ │ └── CombinationSum4.java ├── LeetCodeGraph │ └── Modle.java ├── LeetCodeGreedy │ ├── EraseOverlapIntervals.java │ ├── FindContentChildren.java │ ├── MaxSubArray.java │ └── WiggleMaxLength.java ├── LeetCodeHashMap │ ├── FourSum.java │ ├── FourSumCount.java │ ├── IsHappy.java │ ├── ThreeSum.java │ └── ThreeSumClosest.java ├── LeetCodeListNode │ ├── DetectCycle.java │ ├── GetIntersectionNode.java │ ├── HasCycle.java │ ├── IsPalindrome.java │ ├── ListNode.java │ ├── MyLinkedList.java │ ├── RemoveElements.java │ ├── ReverseBetween.java │ ├── ReverseKGroup.java │ ├── ReverseList.java │ └── SwapPairs.java ├── LeetCodeQueue │ └── TopKFrequent.java ├── LeetCodeString │ ├── RepeatedSubstringPattern.java │ ├── ReverseLeftWords.java │ ├── ReverseStr.java │ ├── ReverseString.java │ ├── ReverseWords.java │ └── StrStr.java ├── LeetCodeTree │ ├── BinaryTreePaths.java │ ├── BuildTree.java │ ├── Connect.java │ ├── ConstructMaximumBinaryTree.java │ ├── IsBalanced.java │ ├── IsValidBST.java │ ├── MinDiffInBST.java │ ├── TreeModle.java │ └── TreeNode.java ├── Lock │ ├── CreateLock.java │ └── TestCreatLock.java ├── Thread │ └── Demo.java ├── lanqiaoTest1 │ └── LanQiaoTest2.java ├── model │ ├── CombinationModle.java │ ├── Compare.java │ ├── FullArrangement.java │ ├── FullCombination.java │ ├── Input.java │ ├── InputAndOutput.java │ ├── InputModle.java │ ├── ListNode.java │ ├── Mid0rUpMidNode.java │ ├── QuickSort.java │ └── Reverse.java └── skillsContest │ ├── Main1.java │ ├── Main2.java │ └── Main3.java └── dailyStudy └── TrieTreeModle.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 | replay_pid* 25 | 26 | /code.iml 27 | /.idea 28 | /out 29 | 30 | /src/dailyExercise/test/ 31 | code-exercise.iml 32 | /src/dailyExercise/lanqiaoTest1/ 33 | /src/dailyExercise/skillsContest/ 34 | -------------------------------------------------------------------------------- /shell.sh: -------------------------------------------------------------------------------- 1 | now=$(date "+%Y-%m-%d-%H:%M") 2 | 3 | git add ./ 4 | git commit -m "代码提交$now" 5 | git push origin main 6 | 7 | echo "上传完成" -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/ArrayPrint/GenerateMatrix.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray.ArrayPrint; 2 | 3 | /** 4 | * @ClassName: GenerateMatrix 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/19 3:27 下午 8 | */ 9 | 10 | public class GenerateMatrix { 11 | 12 | /** 13 | * [59. 螺旋矩阵 II](https://leetcode-cn.com/problems/spiral-matrix-ii/) 14 | * 15 | * @param n 16 | * @return 17 | */ 18 | public static int number = 1; 19 | 20 | 21 | public static int[][] generateMatrix( int n ) { 22 | int[][] res = new int[n][n]; 23 | int startX = 0; 24 | int startY = 0; 25 | int endX = n - 1; 26 | int endY = n - 1; 27 | while ( startX <= endX ) { 28 | generate( res, startX++, startY++, endX--, endY-- ); 29 | } 30 | return res; 31 | } 32 | 33 | 34 | public static void main( String[] args ) { 35 | int n = 5; 36 | int[][] arr = generateMatrix( n ); 37 | for ( int i = 0; i < arr.length; i++ ) { 38 | for ( int j = 0; j < arr[0].length; j++ ) { 39 | System.out.printf( "%5d", arr[i][j] ); 40 | } 41 | System.out.println(); 42 | } 43 | } 44 | 45 | 46 | private static void generate( int[][] res, int x1, int y1, int x2, int y2 ) { 47 | //行 48 | for ( int i = y1; i <= y2; i++ ) { 49 | res[x1][i] = number++; 50 | } 51 | //列 52 | for ( int i = x1 + 1; i <= x2; i++ ) { 53 | res[i][y2] = number++; 54 | } 55 | // 行 《---- 56 | for ( int i = y2 - 1; i >= y1; i-- ) { 57 | res[x2][i] = number++; 58 | } 59 | // 列 60 | for ( int i = x2 - 1; i > x1; i-- ) { 61 | res[i][y1] = number++; 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/ArrayPrint/PrintArrayByZ.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray.ArrayPrint; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @ClassName: PrintArrayByZ 8 | * @Description: 9 | * @author: dk 10 | * @date: 2021/12/16 9:09 下午 11 | */ 12 | 13 | public class PrintArrayByZ { 14 | 15 | /* 16 | 17 | 给定一个矩阵matrix,按照“之”字形的方式打印这个矩阵。例如 18 | 19 | 1,8,6,7 20 | 21 | 2,6,4,11 22 | 23 | 3,5,9,10 24 | 25 | 打印结果是1,8,2,3,6,6,7,4,5,9,11,10。要求额外空间复杂度是O(1)。 26 | 27 | */ 28 | public static List list = new ArrayList<>(); 29 | 30 | 31 | private static void printByZ( int[][] arr ) { 32 | int m = arr.length - 1; 33 | int n = arr[0].length - 1; 34 | int a = 0; 35 | int b = 0; 36 | int c = 0; 37 | int d = 0; 38 | // 是否从下往上 39 | boolean f = true; 40 | while ( b <= n ) { 41 | int printB = a == m ? b++ : b; 42 | int printA = a == m ? m : a++; 43 | int printC = d == n ? c++ : c; 44 | int printD = d == n ? d : d++; 45 | add( arr, printA, printB, printC, printD, f ); 46 | f = !f; 47 | } 48 | } 49 | 50 | 51 | private static void add( int[][] arr, int printA, int printB, int printC, int printD, boolean f ) { 52 | //从下往上 53 | if ( f == true ) { 54 | for ( int i = printA; i >= printC; i-- ) { 55 | list.add( arr[i][printB++] ); 56 | } 57 | } else { 58 | for ( int i = printC; i <= printA; i++ ) { 59 | list.add( arr[i][printD--] ); 60 | } 61 | } 62 | } 63 | 64 | 65 | public static void main( String[] args ) { 66 | int[][] arr = new int[][]{ 67 | { 1, 8, 6 }, { 2, 6, 4 }, { 3, 5, 9 } 68 | }; 69 | printByZ( arr ); 70 | for ( Integer i : list 71 | ) { 72 | System.out.printf( "%3d", i ); 73 | } 74 | } 75 | 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/ArrayPrint/Rotate.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray.ArrayPrint; 2 | 3 | /** 4 | * @ClassName: Rotate 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/19 4:23 下午 8 | */ 9 | 10 | public class Rotate { 11 | 12 | /** 13 | * [48. 旋转图像](https://leetcode-cn.com/problems/rotate-image/) 14 | * 15 | * @param matrix 16 | */ 17 | public static void rotate( int[][] matrix ) { 18 | int x = 0; 19 | int y = 0; 20 | int endX = matrix.length - 1; 21 | int endY = matrix[0].length - 1; 22 | while ( x < endX ) { 23 | rotateArr( matrix, x++, y++, endX--, endY-- ); 24 | } 25 | } 26 | 27 | 28 | private static void rotateArr( int[][] matrix, int x, int y, int endX, int endY ) { 29 | int temp = 0; 30 | for ( int i = 0; i < endY - y; i++ ) { 31 | //保存第一行的数 32 | temp = matrix[x][y + i]; 33 | // 将第一列的数给第一行 34 | matrix[x][y + i] = matrix[endX - i][y]; 35 | // 将最后一行的数 给第一列 36 | matrix[endX - i][y] = matrix[endX][endY - i]; 37 | // 将最后一列的数 给最后一行 38 | matrix[endX][endY - i] = matrix[x + i][endY]; 39 | // 将 第一行的数 给最后一列 40 | matrix[x + i][endY] = temp; 41 | } 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/ArrayPrint/SpiralOrder.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray.ArrayPrint; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @ClassName: SpiralOrder 8 | * @Description: 9 | * @author: dk 10 | * @date: 2021/12/19 3:41 下午 11 | */ 12 | 13 | public class SpiralOrder { 14 | 15 | /** 16 | * [54. 螺旋矩阵](https://leetcode-cn.com/problems/spiral-matrix/) 17 | * 18 | * @param matrix 19 | * @return 20 | */ 21 | public List list = new ArrayList<>(); 22 | 23 | 24 | public List spiralOrder( int[][] matrix ) { 25 | int m = matrix.length - 1; 26 | int n = matrix[0].length - 1; 27 | int x = 0; 28 | int y = 0; 29 | while ( x <= m && y <= n ) { 30 | generate( matrix, x++, y++, m--, n-- ); 31 | } 32 | return list; 33 | } 34 | 35 | 36 | private void generate( int[][] matrix, int x, int y, int m, int n ) { 37 | if ( x == m ) { 38 | for ( int i = y; i <= n; i++ ) { 39 | list.add( matrix[x][i] ); 40 | } 41 | } else if ( y == n ) { 42 | for ( int i = x; i <= m; i++ ) { 43 | list.add( matrix[i][y] ); 44 | } 45 | } else { 46 | // 行 47 | for ( int i = y; i <= n; i++ ) { 48 | list.add( matrix[x][i] ); 49 | } 50 | //列 51 | for ( int i = x + 1; i <= m; i++ ) { 52 | list.add( matrix[i][n] ); 53 | } 54 | // 行 《-- 55 | for ( int i = n - 1; i >= y; i-- ) { 56 | list.add( matrix[m][i] ); 57 | } 58 | // 列 59 | for ( int i = m - 1; i > x; i-- ) { 60 | list.add( matrix[i][y] ); 61 | } 62 | 63 | } 64 | 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/FindAnagrams.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @ClassName: FindAnagrams 8 | * @Description: 9 | * @author: dk 10 | * @date: 2021/12/16 10:02 上午 11 | */ 12 | 13 | public class FindAnagrams { 14 | 15 | /** 16 | * [438. 找到字符串中所有字母异位词 (mid)](https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/) 17 | * 18 | * @param s 19 | * @param p 20 | * @return 参考 https://leetcode-cn.com/problems/find-all-anagrams-in-a-string/solution/gong-shui-san-xie-shuang-zhi-zhen-shi-xi-t5hc/ 21 | */ 22 | public List findAnagrams( String s, String p ) { 23 | List res = new ArrayList<>(); 24 | int[] c1 = new int[26]; 25 | int[] c2 = new int[26]; 26 | int l = 0; 27 | for ( int i = 0; i < p.length(); i++ ) { 28 | c2[p.charAt( i ) - 'a']++; 29 | } 30 | for ( int r = 0; r < s.length(); r++ ) { 31 | c1[s.charAt( r ) - 'a']++; 32 | // 如果 l到r 之间的距离超过了 p 的长度,就将最前面的字符频率-1 33 | if ( (r + 1 - l) > p.length() ) { 34 | c1[s.charAt( l++ ) - 'a']--; 35 | } 36 | if ( check( c1, c2 ) ) { 37 | res.add( l ); 38 | } 39 | } 40 | return res; 41 | } 42 | 43 | 44 | private Boolean check( int[] c1, int[] c2 ) { 45 | for ( int i = 0; i < c1.length; i++ ) { 46 | if ( c1[i] != c2[i] ) { 47 | return false; 48 | } 49 | } 50 | return true; 51 | } 52 | 53 | } 54 | /* 55 | cbaebac 56 | abc 57 | 58 | c1 [ c 1] 59 | c2 [ a 1 b 1 c 1] 60 | r=0 61 | 62 | c1 [ c 1 b 1 ] 63 | c2 [ a 1 b 1 c 1] 64 | r=1 65 | 66 | c1 [ c 1 b 1 a 1] 67 | c2 [ a 1 b 1 c 1] 68 | r=2 69 | r+1-l = 3 = p.length 70 | 进入check return true 71 | left=0 72 | res.add(left=0) 73 | 74 | 75 | cbaebac 76 | abc 77 | 78 | c1 [ c 1 b 1 a 1 e 1] 79 | c2 [ a 1 b 1 c 1] 80 | r=3 81 | r+1-l = 4 > p.length 82 | 将s的left 位置的字符频率-1 83 | 此时left = 0 84 | c1 [ c 0 b 1 a 1 e 1] 85 | l++ l=1 86 | 87 | 88 | c1 [ c 0 b 2 a 1 e 1 ] 89 | c2 [ a 1 b 1 c 1] 90 | r=4 91 | r+1-l = 4+1-1 > p.length 92 | 将s的left 位置的字符频率-1 93 | 此时left = 1 94 | c1 [ c 0 b 1 a 1 e 1] 95 | l++ l=2 96 | 97 | 98 | 99 | cbaebac 100 | abc 101 | 102 | c1 [ c 0 b 1 a 2 e 1 ] 103 | c2 [ a 1 b 1 c 1] 104 | r=5 105 | r+1-l = 5+1-2 > p.length 106 | 将s的left 位置的字符频率-1 107 | 此时left = 2 108 | c1 [ c 0 b 1 a 1 e 1 ] 109 | l++ l=3 110 | 111 | c1 [ c 1 b 1 a 1 e 1 ] 112 | c2 [ a 1 b 1 c 1] 113 | r=6 114 | r+1-l = 6+1-3 > p.length 115 | 将s的left 位置的字符频率-1 116 | 此时left = 3 117 | c1 [ c 1 b 1 a 1 e 0 ] 118 | l++ l=4 119 | 120 | check return true 121 | res.add(4) 122 | 123 | */ -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/MaxArea.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray; 2 | 3 | /** 4 | * @ClassName: MaxArea 5 | * @Description: 6 | * @author: dk 7 | * @date: 2022/10/29 13:22 8 | */ 9 | 10 | public class MaxArea { 11 | 12 | /* 13 | [11. 盛最多水的容器](https://leetcode.cn/problems/container-with-most-water/) 14 | 15 | 每次排除掉左右两侧最小的,因为这个最小的决定了整体的下限 16 | 17 | */ 18 | public int maxArea(int[] height) { 19 | int n = height.length-1; 20 | int left = 0; 21 | int right = n; 22 | int res = 0; 23 | while(left < right){ 24 | res = Math.max(res, (right-left) * Math.min(height[left],height[right]) ); 25 | if(height[left]=nums[l])l++; 57 | if (l <= r) swap(nums, l, r); 58 | } 59 | System.out.println("当前交换前数组是"+Arrays.toString(nums)); 60 | swap(nums, r + 1, right); 61 | System.out.println("当前交换后数组是"+Arrays.toString(nums)); 62 | System.out.println("---------------------end"); 63 | return r + 1; 64 | } 65 | 66 | private void swap(int[] nums, int i, int j) { 67 | int temp = nums[i]; 68 | nums[i] = nums[j]; 69 | nums[j] = temp; 70 | } 71 | } 72 | 73 | /* 74 | 75 | 76 | 77 | ---------------------start 78 | 当前pivot=10 79 | 当前数组是[3, 6, 7, 13, 12, 2, 10]left=0 right=6 80 | 内部第0次循环[3, 6, 7, 2, 12, 13, 10] 81 | 内部第1次循环[3, 6, 7, 2, 12, 13, 10] 82 | 83 | 当前交换前数组是[3, 6, 7, 2, 12, 13, 10] 84 | 当前交换后数组是[3, 6, 7, 2, 10, 13, 12] 85 | ---------------------end 86 | 87 | ---------------------start 88 | 当前pivot=13 89 | 当前数组是[3, 6, 7, 2, 10, 12, 13]left=5 right=6 90 | 内部第0次循环[3, 6, 7, 2, 10, 12, 13] 91 | 92 | 当前交换前数组是[3, 6, 7, 2, 10, 12, 13] 93 | 当前交换后数组是[3, 6, 7, 2, 10, 12, 13] 94 | ---------------------end 95 | 96 | ---------------------start 97 | 当前pivot=3 98 | 当前数组是[2, 6, 7, 3, 10, 12, 13]left=0 right=3 99 | 内部第0次循环[2, 6, 7, 3, 10, 12, 13] 100 | 101 | 当前交换前数组是[2, 6, 7, 3, 10, 12, 13] 102 | 当前交换后数组是[2, 3, 7, 6, 10, 12, 13] 103 | ---------------------end 104 | 105 | ---------------------start 106 | 当前pivot=7 107 | 当前数组是[2, 3, 6, 7, 10, 12, 13]left=2 right=3 108 | 内部第0次循环[2, 3, 6, 7, 10, 12, 13] 109 | 110 | 当前交换前数组是[2, 3, 6, 7, 10, 12, 13] 111 | 当前交换后数组是[2, 3, 6, 7, 10, 12, 13] 112 | ---------------------end 113 | 114 | 115 | */ 116 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/RemoveElement.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray; 2 | 3 | /** 4 | * @ClassName: RemoveElement 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/12 8:02 下午 8 | */ 9 | 10 | public class RemoveElement { 11 | 12 | /** 13 | * 27. 移除元素https://leetcode-cn.com/problems/remove-element/ 14 | * 15 | * @param nums 16 | * @param val 17 | * @return 18 | */ 19 | public int removeElement(int[] nums, int val) { 20 | int s = 0; 21 | for (int f = 0; f < nums.length; f++) { 22 | if (nums[f] != val) { 23 | nums[s++] = nums[f]; 24 | } 25 | } 26 | return s; 27 | } 28 | 29 | /** 30 | * 26. 删除有序数组中的重复项https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/ 31 | * 32 | * @param nums 33 | * @return 34 | */ 35 | public int removeDuplicates(int[] nums) { 36 | if (nums.length <= 1) { 37 | return nums.length; 38 | } 39 | int s = 0; 40 | for (int f = 1; f < nums.length; f++) { 41 | if (nums[f] != nums[s]) { 42 | nums[++s] = nums[f]; 43 | } 44 | } 45 | return s + 1; 46 | } 47 | 48 | int removeDuplicatesTwo(int[] nums) { 49 | if (nums.length == 0) { 50 | return 0; 51 | } 52 | int slow = 0, fast = 0; 53 | while (fast < nums.length) { 54 | if (nums[fast] != nums[slow]) { 55 | slow++; 56 | // 维护 nums[0..slow] 无重复 57 | nums[slow] = nums[fast]; 58 | } 59 | fast++; 60 | } 61 | // 数组长度为索引 + 1 62 | return slow + 1; 63 | } 64 | 65 | 66 | class ListNode { 67 | int val; 68 | ListNode next; 69 | 70 | ListNode() { 71 | } 72 | 73 | ListNode(int val) { 74 | this.val = val; 75 | } 76 | 77 | ListNode(int val, ListNode next) { 78 | this.val = val; 79 | this.next = next; 80 | } 81 | } 82 | 83 | /** 84 | * 83. 删除排序链表中的重复元素https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/ 85 | * 86 | * @param head 87 | * @return 88 | */ 89 | public ListNode deleteDuplicates(ListNode head) { 90 | if (head == null || head.next == null) { 91 | return head; 92 | } 93 | ListNode s = head; 94 | ListNode f = head.next; 95 | while (f != null) { 96 | if (s.val != f.val) { 97 | s.next = f; 98 | s = s.next; 99 | f = f.next; 100 | } else { 101 | f = f.next; 102 | } 103 | } 104 | // 断开与后面重复元素的连接 105 | s.next = null; 106 | return head; 107 | } 108 | 109 | /** 110 | * 283. 移动零 https://leetcode-cn.com/problems/move-zeroes/ 111 | * 112 | * @param nums 113 | */ 114 | public void moveZeroes(int[] nums) { 115 | // 去除 nums 中的所有 0 116 | // 返回去除 0 之后的数组长度 117 | int p = removeElementTemp(nums, 0); 118 | // 将 p 之后的所有元素赋值为 0 119 | for (; p < nums.length; p++) { 120 | nums[p] = 0; 121 | } 122 | } 123 | 124 | public int removeElementTemp(int[] nums, int val) { 125 | int s = 0; 126 | for (int f = 0; f < nums.length; f++) { 127 | if (nums[f] != val) { 128 | nums[s++] = nums[f]; 129 | } 130 | } 131 | return s; 132 | } 133 | 134 | 135 | public void moveZeroesTwo(int[] nums) { 136 | int n = nums.length, left = 0, right = 0; 137 | while (right < n) { 138 | if (nums[right] != 0) { 139 | swap(nums, left, right); 140 | left++; 141 | } 142 | right++; 143 | } 144 | } 145 | 146 | public void swap(int[] nums, int left, int right) { 147 | int temp = nums[left]; 148 | nums[left] = nums[right]; 149 | nums[right] = temp; 150 | } 151 | 152 | public void moveZeroesThree(int[] nums) { 153 | if (nums == null) { 154 | return; 155 | } 156 | //两个指针i和j 157 | int j = 0; 158 | for (int i = 0; i < nums.length; i++) { 159 | //当前元素!=0,就把其交换到左边,等于0的交换到右边 160 | if (nums[i] != 0) { 161 | int tmp = nums[i]; 162 | nums[i] = nums[j]; 163 | nums[j++] = tmp; 164 | } 165 | } 166 | } 167 | // 作者:wang_ni_ma 168 | // 链接:https://leetcode-cn.com/problems/move-zeroes/solution/dong-hua-yan-shi-283yi-dong-ling-by-wang_ni_ma/ 169 | // 来源:力扣(LeetCode) 170 | // 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 171 | 172 | 173 | } 174 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/Rotate.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray; 2 | 3 | 4 | public class Rotate { 5 | 6 | /** 7 | * 189. 轮转数组 8 | * https://leetcode.cn/problems/rotate-array/ 9 | * 省略最简单的方案 拼接、创建新的空间 10 | * 11 | * @param nums 12 | * @param k 13 | */ 14 | public void rotate( int[] nums, int k ) { 15 | int t = k % nums.length; 16 | if ( t == 0 ) { 17 | return; 18 | } 19 | 20 | revese( nums, 0, nums.length - 1 ); 21 | revese( nums, 0, t - 1 ); 22 | revese( nums, t, nums.length - 1 ); 23 | } 24 | 25 | 26 | public void revese( int[] nums, int start, int end ) { 27 | while ( start < end ) { 28 | int temp = nums[start]; 29 | nums[start] = nums[end]; 30 | nums[end] = temp; 31 | start++; 32 | end--; 33 | } 34 | } 35 | 36 | 37 | public void rotate1( int[] nums, int k ) { 38 | int n = nums.length; 39 | k = k % n; 40 | if ( k == 0 ) { 41 | return; 42 | } 43 | int count = 0; 44 | 45 | for ( int i = 0; count < n; i++ ) { 46 | // 当前位置 47 | int cur = i; 48 | // 当前位置的前一个数字(第一个就是其自己) 49 | int pre = nums[cur]; 50 | do { 51 | // 下一个坐标 52 | int next = (cur + k) % n; 53 | // 交换 54 | int temp = nums[next]; 55 | nums[next] = pre; 56 | pre = temp; 57 | // 将下一个位置给cur 58 | cur = next; 59 | // 更换次数增加 60 | count++; 61 | } while ( i != cur ); 62 | 63 | } 64 | } 65 | //https://leetcode.cn/problems/rotate-array/solution/xuan-zhuan-shu-zu-yuan-di-huan-wei-xiang-xi-tu-jie/ 66 | } 67 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/Search.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray; 2 | 3 | 4 | import java.util.HashMap; 5 | 6 | public class Search { 7 | 8 | /** 9 | * 704. 二分查找 https://leetcode-cn.com/problems/binary-search/ 10 | * 11 | * @param nums 12 | * @param target 13 | * @return 14 | */ 15 | public int search( int[] nums, int target ) { 16 | int l = 0; 17 | int r = nums.length - 1; 18 | //因为left == right是有意义的,所以使用 <= 19 | while ( l <= r ) { 20 | // 防止溢出 21 | int mid = l + (r - l) / 2; 22 | if ( nums[mid] == target ) { 23 | return mid; 24 | } else if ( nums[mid] < target ) { 25 | // 当前数字一定比targer小,所以下一次查询的范围是 【mid+1,r】 26 | l = mid + 1; 27 | } else if ( nums[mid] > target ) { 28 | //当前数字一定比targer大,所以下一次查询的范围是 【l,mid-1】 29 | r = mid - 1; 30 | } 31 | } 32 | return -1; 33 | } 34 | 35 | 36 | public int searchTwo( int[] nums, int target ) { 37 | int l = 0; 38 | // 定义target在左闭右开的区间里,即:[left, right) 39 | int r = nums.length; 40 | // 使用< 是因为left == right在区间[left, right)是没有意义的 41 | while ( l < r ) { 42 | // 防止溢出 43 | int mid = l + (r - l) / 2; 44 | if ( nums[mid] == target ) { 45 | return mid; 46 | //当 nums[mid] 被检测之后,下一步的搜索区间应该去掉 mid 分割成两个区间 47 | //即 [left, mid) 或 [mid + 1, right) 48 | } else if ( nums[mid] < target ) { 49 | //由于判断的区间范围是 【left,right),此时 mid 位置的数是小于target的 50 | //下一步判断时就可以跳过 mid ,从mid +1 开始 51 | //判断范围为 [middle + 1, right) 52 | l = mid + 1; 53 | } else if ( nums[mid] > target ) { 54 | //由于判断的区间范围是 【left,right),此时 mid 位置的数是大于target的 55 | //判断范围为【left, middle) 56 | // 若 r=mid-1 ,则本来 mid 与 l 产生的判断范围被忽略掉了 57 | r = mid; 58 | } 59 | } 60 | return -1; 61 | } 62 | /** 63 | * -1 0 3 5 9 12 64 | * ---------------------- 65 | * 0 1 2 3 4 5 66 | * target=3 67 | * l=0,r=6 68 | * 第一次 mid = (0+6)/2 =3 69 | * num[3] =5>3 70 | * 若 r =mid-1 71 | * 则 r=3-1=2 72 | * 第二次 mid = (0+2)/2=1 73 | * num[1]=0 <3 74 | * l=mid+1 =1+1=2 = r l==r while 循环退出,找不到target了 75 | * 但本例子中是有targer=3的 76 | * 77 | * ------------------------ 78 | * 选用r =mid 79 | * 则 r=3 80 | * 第二次 mid = (0+3)/2=1 81 | * num[1]=0 <3 82 | * l=mid+1 = 1+1 =2 < r 83 | * 第三次 mid = (2+3)/2=2 84 | * num[2]=3 找到了target 85 | */ 86 | 87 | //二分边界查找最优算法 88 | 89 | 90 | /** 91 | * 34. 在排序数组中查找元素的第一个和最后一个位置 https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/ 92 | * 93 | * @param nums 94 | * @param target 95 | * @return 96 | */ 97 | public int[] searchRange( int[] nums, int target ) { 98 | if ( nums.length == 0 || (nums.length == 1 && nums[0] != target) ) { 99 | return new int[]{ -1, -1 }; 100 | } 101 | int left = searchLeft( nums, target ); 102 | int right = searchRight( nums, target ); 103 | return new int[]{ left, right }; 104 | } 105 | 106 | 107 | private int searchRight( int[] nums, int target ) { 108 | int l = 0; 109 | int r = nums.length - 1; 110 | while ( l <= r ) { 111 | int mid = l + (r - l) / 2; 112 | if ( nums[mid] == target ) { 113 | l = mid + 1; 114 | } else if ( nums[mid] > target ) { 115 | r = mid - 1; 116 | } else if ( nums[mid] < target ) { 117 | l = mid + 1; 118 | } 119 | } 120 | return r >= 0 ? (nums[r] == target ? r : -1) : -1; 121 | } 122 | 123 | 124 | private int searchLeft( int[] nums, int target ) { 125 | int l = 0; 126 | int r = nums.length - 1; 127 | while ( l <= r ) { 128 | int mid = l + (r - l) / 2; 129 | if ( nums[mid] == target ) { 130 | r = mid - 1; 131 | } else if ( nums[mid] > target ) { 132 | r = mid - 1; 133 | } else if ( nums[mid] < target ) { 134 | l = mid + 1; 135 | } 136 | } 137 | return l <= nums.length - 1 ? (nums[l] == target ? l : -1) : -1; 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/SortedSquares.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray; 2 | 3 | /** 4 | * @ClassName: SortedSquares 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/15 12:41 下午 8 | */ 9 | 10 | public class SortedSquares { 11 | 12 | /** 13 | * 14 | * @param nums 15 | * @return 16 | */ 17 | public int[] sortedSquares( int[] nums ) { 18 | int[] res = new int[nums.length]; 19 | int n = nums.length - 1; 20 | int l = 0; 21 | int r = nums.length - 1; 22 | for ( int i = 0; i < nums.length; i++ ) { 23 | nums[i] = nums[i] * nums[i]; 24 | } 25 | while ( l < r ) { 26 | if ( nums[l] <= nums[r] ) { 27 | res[n--] = nums[r]; 28 | r--; 29 | } else if ( nums[l] > nums[r] ) { 30 | res[n--] = nums[l]; 31 | l++; 32 | } 33 | } 34 | return res; 35 | } 36 | 37 | /* 38 | -4 -1 0 3 10 39 | 40 | -------------------------- 41 | 42 | 16 1 0 9 100 43 | 44 | 45 | 46 | l=0,r=4 47 | 48 | arr[l]arr[r] 16>9 61 | 62 | n=3 n-- 63 | 64 | res[0,0,0,16,100] 65 | 66 | l++ l=1 67 | 68 | 69 | 70 | l=1,r=3 71 | 72 | arr[l]arr[r] 1>2 85 | 86 | n=1 n-- 87 | 88 | res[0,1,9,16,100] 89 | 90 | l++ l=2 91 | 92 | 93 | 94 | 但此时还有最后一个元素未处理,所以while的循环终止条件应该为l<=r 95 | 96 | 97 | 98 | l=1,r=2 99 | 100 | arr[l]=arr[r] 0=0 101 | 102 | n=0 n-- 103 | 104 | res[0,1,9,16,100] 105 | 106 | r-- r=1 107 | 108 | 109 | 110 | l>r 退出循环 111 | */ 112 | } 113 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/window/CheckInclusion.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray.window; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @ClassName: CheckInclusion 7 | * @Description: 8 | * @author: dk 9 | * @date: 2021/12/19 2:42 下午 10 | */ 11 | 12 | public class CheckInclusion { 13 | 14 | /** 15 | * [567. 字符串的排列](https://leetcode-cn.com/problems/permutation-in-string/) 16 | * @param s1 17 | * @param s2 18 | * @return 19 | */ 20 | public boolean checkInclusion( String s1, String s2 ) { 21 | boolean b = false; 22 | int[] a1 = new int[26]; 23 | int[] a2 = new int[26]; 24 | int l = 0; 25 | int r = 0; 26 | for ( int i = 0; i < s1.length(); i++ ) { 27 | a1[s1.charAt( i ) - 'a']++; 28 | } 29 | while ( r < s2.length() ) { 30 | int index = s2.charAt( r ) - 'a'; 31 | a2[index]++; 32 | if ( r - l + 1 == s1.length() ) { 33 | if ( check( a1, a2 ) ) { 34 | return true; 35 | } else { 36 | a2[s2.charAt( l ) - 'a']--; 37 | l++; 38 | } 39 | } 40 | r++; 41 | 42 | } 43 | return b; 44 | } 45 | 46 | 47 | private boolean check( int[] a1, int[] a2 ) { 48 | Boolean f = true; 49 | for ( int i = 0; i < a1.length; i++ ) { 50 | if ( a1[i] != a2[i] ) { 51 | return false; 52 | } 53 | } 54 | return f; 55 | } 56 | 57 | public static void main(String[] args) { 58 | String s = "123"; 59 | String s1 = "1234"; 60 | 61 | System.out.println(s.indexOf(s1)); 62 | System.out.println(s1.indexOf(s)); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/window/FindLHS.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray.window; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashMap; 5 | 6 | /** 7 | * @ClassName: FindLHS 8 | * @Description: 9 | * @author: dk 10 | * @date: 2021/12/16 7:44 下午 11 | */ 12 | 13 | public class FindLHS { 14 | 15 | /** 16 | * 594. 最长和谐子序列 17 | * https://leetcode-cn.com/problems/longest-harmonious-subsequence/ 18 | * 19 | * @param nums 20 | * @return 21 | */ 22 | public int findLHS( int[] nums ) { 23 | //看到序列,即与原来顺序无关,可考虑排序 24 | if ( nums.length <= 1 ) { 25 | return 0; 26 | } 27 | Arrays.sort( nums ); 28 | int res = 0; 29 | int l = 0; 30 | int r = 1; 31 | while ( r < nums.length ) { 32 | //此时为滑动窗口的时机 33 | while ( nums[r] - nums[l] > 1 && l < r ) { 34 | l++; 35 | } 36 | if ( nums[r] - nums[l] == 1 ) { 37 | res = Math.max( res, r - l + 1 ); 38 | } 39 | r++; 40 | } 41 | return res; 42 | } 43 | 44 | 45 | // O(n^2) 过不去 46 | class Info { 47 | 48 | int low; 49 | int hight; 50 | int val; 51 | 52 | 53 | public Info( int l, int h, int val ) { 54 | this.val = val; 55 | this.low = l; 56 | this.hight = h; 57 | } 58 | 59 | } 60 | 61 | 62 | public int findLHS1( int[] nums ) { 63 | int res = 0; 64 | Info[] infos = new Info[nums.length]; 65 | HashMap map = new HashMap<>(); 66 | for ( int i = 0; i < nums.length; i++ ) { 67 | if ( map.containsKey( nums[i] ) ) { 68 | infos[i] = new Info( 0, 0, map.get( nums[i] ) ); 69 | } else { 70 | int l = serach( nums, nums[i] - 1 ); 71 | int h = serach( nums, nums[i] + 1 ); 72 | infos[i] = new Info( l, h, Math.max( l, h ) ); 73 | } 74 | } 75 | for ( Info inf : infos 76 | ) { 77 | res = Math.max( res, inf.val ); 78 | } 79 | return res; 80 | } 81 | 82 | 83 | private int serach( int[] nums, int i ) { 84 | int res = 0; 85 | for ( int j = 0; j < nums.length; j++ ) { 86 | if ( i == nums[j] || nums[j] + 1 == i ) { 87 | res++; 88 | } 89 | } 90 | return res; 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/window/FindMaxAverage.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray.window; 2 | 3 | /** 4 | * @ClassName: FindMaxAverage 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/16 7:14 下午 8 | */ 9 | 10 | public class FindMaxAverage { 11 | 12 | /** 13 | * 643. 子数组最大平均数 I https://leetcode-cn.com/problems/maximum-average-subarray-i/ 14 | * 15 | * @param nums 16 | * @param k 17 | * @return 18 | */ 19 | public double findMaxAverage(int[] nums, int k) { 20 | int res=Integer.MIN_VALUE; 21 | int l=0; 22 | int r=0; 23 | int sum=0; 24 | while (r map = new HashMap<>(); 26 | int left = 0, right = 0; 27 | int res = 0; 28 | while ( right < s.length() ) { 29 | // 增大窗口 30 | char c = s.charAt( right ); 31 | if ( map.containsKey( c ) ) { 32 | //此时出现了重复的字母,需要更新窗口开始位置 33 | left = Math.max( left, map.get( c ) + 1 ); 34 | } 35 | //更新 c 所代表字符最晚出现位置 36 | map.put( c, right ); 37 | res = Math.max( res, right - left + 1 ); 38 | right++; 39 | } 40 | return res; 41 | } 42 | 43 | 44 | } 45 | /* 46 | pwwkew 47 | 48 | p w 49 | ( p 0 50 | w 1 51 | ) 52 | res = Math.max( res,right-left+1); 53 | (0,1-0+1) res=2 54 | 55 | p w w 56 | ( p 0 57 | w 1 58 | ) 59 | w 重复了,开始重新定位left 60 | left = Math.max( left, map.get( c ) + 1 ); 61 | (0,1+1) left=2 62 | 63 | 更新 c 所代表字符的新的位置 64 | map.put( c,right ); 65 | p w w 66 | ( p 0 67 | w 2 68 | ) 69 | res = Math.max( res,right-left+1); 70 | (2,2-2+1) res=2 71 | 72 | p w w k 73 | ( p 0 74 | w 2 75 | k 3 76 | ) 77 | res = Math.max( res,right-left+1); 78 | (2,3-2+1) res=2 79 | 80 | p w w k e 81 | ( p 0 82 | w 2 83 | k 3 84 | e 4 85 | ) 86 | res = Math.max( res,right-left+1); 87 | (2,4-2+1) res=3 88 | 89 | p w w k e w 90 | ( p 0 91 | w 2 92 | k 3 93 | e 4 94 | ) 95 | w 重复了 重新定位其位置 96 | left = Math.max( left, map.get( c ) + 1 ); 97 | (2,2+1) left=3 98 | res = Math.max( res,right-left+1); 99 | (2,5-3+1) res=3 100 | 101 | 102 | 103 | 104 | */ 105 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/window/MinSubArrayLen.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray.window; 2 | 3 | 4 | /** 5 | * @ClassName: MinSubArrayLen 6 | * @Description: 7 | * @author: dk 8 | * @date: 2021/12/15 12:59 下午 9 | */ 10 | 11 | public class MinSubArrayLen { 12 | 13 | /** 14 | * @param target 15 | * @param nums 16 | * @return 17 | */ 18 | public int minSubArrayLen( int target, int[] nums ) { 19 | int res = Integer.MAX_VALUE; 20 | int sum = 0; 21 | int l = 0; 22 | for ( int right = 0; right < nums.length; right++ ) { 23 | sum = sum + nums[right]; 24 | while ( sum >= target ) { 25 | //System.out.println("--"+l+"--"+r+"--"+sum); 26 | res = Math.min( right - l + 1, res ); 27 | sum = sum - nums[l++]; 28 | } 29 | } 30 | return res == Integer.MAX_VALUE ? 0 : res; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/window/MinWindow.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray.window; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * @ClassName: MinWindow 7 | * @Description: 8 | * @author: dk 9 | * @date: 2021/12/20 2:31 下午 10 | */ 11 | 12 | public class MinWindow { 13 | 14 | /** 15 | * [76. 最小覆盖子串](https://leetcode-cn.com/problems/minimum-window-substring/) 16 | * 17 | * @param s 18 | * @param t 19 | * @return 20 | */ 21 | public String minWindow( String s, String t ) { 22 | String res = ""; 23 | if ( t.length() > s.length() ) { 24 | return res; 25 | } 26 | 27 | HashMap need = new HashMap<>(); 28 | HashMap window = new HashMap<>(); 29 | 30 | for ( int i = 0; i < t.length(); i++ ) { 31 | char ch = t.charAt( i ); 32 | need.put( ch, need.getOrDefault( ch, 0 ) + 1 ); 33 | } 34 | int left = 0; 35 | int right = 0; 36 | int valid = 0; 37 | int len = Integer.MAX_VALUE; 38 | int start = 0; 39 | while ( right < s.length() ) { 40 | char c = s.charAt( right ); 41 | right++; 42 | if ( need.containsKey( c ) ) { 43 | window.put( c, window.getOrDefault( c, 0 ) + 1 ); 44 | if ( window.get( c ).equals( need.get( c ) ) ) { 45 | valid++; 46 | } 47 | } 48 | // 判断左侧窗口是否要收缩 49 | while ( valid == need.size() ) { 50 | // 在这里更新最小覆盖子串 51 | if ( right - left < len ) { 52 | start = left; 53 | len = right - left; 54 | } 55 | // d 是将移出窗口的字符 56 | char d = s.charAt( left ); 57 | // 左移窗口 58 | left++; 59 | // 进行窗口内数据的一系列更新 60 | if ( need.containsKey( d ) ) { 61 | if ( window.get( d ).equals( need.get( d ) ) ) { 62 | valid--; 63 | } 64 | window.put( d, window.get(d) - 1 ); 65 | } 66 | } 67 | } 68 | 69 | return len == Integer.MAX_VALUE ? "" : s.substring( start, start+len ); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/window/ShortestSubarray.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray.window; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Deque; 5 | 6 | /** 7 | * @ClassName: ShortestSubarray 8 | * @Description: 9 | * @author: dk 10 | * @date: 2022/1/16 4:54 下午 11 | */ 12 | 13 | public class ShortestSubarray { 14 | 15 | class Solution { 16 | 17 | /** 18 | * [862. 和至少为 K 的最短子数组](https://leetcode-cn.com/problems/shortest-subarray-with-sum-at-least-k/) 19 | * @param A 20 | * @param K 21 | * @return 22 | */ 23 | public int shortestSubarray( int[] A, int K ) { 24 | long[] arr = new long[A.length + 1]; 25 | for ( int i = 0; i < A.length; i++ ) { 26 | arr[i + 1] = arr[i] + A[i]; 27 | if ( A[i] >= K ) { 28 | return 1; 29 | } 30 | }//得到前缀和数组 31 | int res = Integer.MAX_VALUE; 32 | Deque queue = new ArrayDeque<>(); 33 | for ( int i = 0; i < arr.length; i++ ) { 34 | while ( !queue.isEmpty() && arr[i] <= arr[queue.getLast()] ) { 35 | queue.removeLast(); 36 | } 37 | while ( !queue.isEmpty() && arr[i] - arr[queue.peek()] >= K ) { 38 | res = Math.min( res, i - queue.poll() ); 39 | } 40 | queue.add( i ); 41 | 42 | } 43 | return res == Integer.MAX_VALUE ? -1 : res; 44 | } 45 | 46 | } 47 | 48 | // 作者:ppppjcute 49 | // 链接:https://leetcode-cn.com/problems/shortest-subarray-with-sum-at-least-k/solution/java-qian-zhui-he-yu-shuang-duan-by-ppppjqute/ 50 | // 来源:力扣(LeetCode) 51 | // 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 52 | 53 | /* 54 | [10,-2,4,5,6] 55 | 15 56 | 57 | 如果用滑动窗口,窗口最大会变成【10,-2,4,5,6】 58 | 此时 sum= 23 > 15 59 | 缩小窗口 sum-10 = 13 < 15 60 | 返回合适的窗口大小为 5 ,其实正确的结果应该为【4,5,6】 窗口大小是3 61 | 62 | while(!queue.isEmpty()&&arr[i]<=arr[queue.getLast()]) queue.removeLast(); 63 | while(!queue.isEmpty()&&arr[i]-arr[queue.peek()]>=K) res = Math.min(res,i-queue.poll()); 64 | queue.add( i ); 65 | 66 | arr[i]<=arr[queue.getLast()] 67 | 如果当前的前缀和要小于之前的前缀和,那必然是在求解前缀和的过程中越加越小的, 68 | 69 | 情况1是把位于末尾没用的x1扔掉, 70 | 情况2是把指向前面的已经满足条件的x1的指针向后移动1位,这是就需要比较当前最小值与此时刚符合条件的值的大小了。 71 | 72 | 73 | 74 | 原数组 75 | 【10,-2,4,5,6】 76 | 77 | 前缀和数组为 78 | 【0,10,8,12,17,23】 79 | 添加元素 80 | 81 | 【0】 82 | 【0,1】 83 | 84 | 85 | 86 | 开始删除最后进来的元素 87 | i= 2 队列为: [0, 1] 88 | i= 2 arr[i]= 8 arr[queue.getLast()]=10 删除的是1位置的数,也就是10, 89 | 90 | 添加元素 91 | 【0,2】 92 | 【0,2,3】 93 | 94 | 开始更新结果 95 | i= 4 arr[i]= 17 arr[queue.peek()]=0 96 | i= 4 队列为 [0, 2, 3] 97 | 结果更新为: 4 98 | i= 4 结果更新后的队列为 [2, 3] 99 | 100 | 添加元素 101 | 【2,3,4】 102 | 103 | 开始更新结果 104 | i= 5 arr[i]= 23 arr[queue.peek()]=8 105 | i= 5 队列为 [2, 3, 4] 106 | 结果更新为: 3 107 | 108 | 5-queue.poll() = 5 -2 = 3 109 | 110 | 111 | 112 | 113 | 114 | */ 115 | 116 | 117 | /** 118 | * 滑动窗口不能通过,因为中间有负数,会影响窗口的缩短 119 | * [84,-37,32,40,95] 120 | * 167 121 | * 122 | * @param nums 123 | * @param k 124 | * @return 125 | */ 126 | public int shortestSubarrayBadWay( int[] nums, int k ) { 127 | if ( nums.length == 1 ) { 128 | if ( nums[0] == k ) { 129 | return 1; 130 | } else { 131 | return -1; 132 | } 133 | } 134 | int l = 0; 135 | int r = 0; 136 | int count = 0; 137 | for ( int i = 0; i < nums.length; i++ ) { 138 | if ( nums[i] > 0 ) { 139 | l = i; 140 | r = i; 141 | break; 142 | } 143 | } 144 | 145 | int res = Integer.MAX_VALUE; 146 | while ( r < nums.length ) { 147 | count = count + nums[r]; 148 | r++; 149 | while ( count >= k || l < r ) { 150 | //System.out.println(count+" r= "+ r + " l= " + l); 151 | res = Math.min( res, r - l ); 152 | count = count - nums[l]; 153 | l++; 154 | } 155 | } 156 | return res == Integer.MAX_VALUE ? -1 : res; 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeArray/window/TotalFruit.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeArray.window; 2 | 3 | /** 4 | * @ClassName: TotalFruit 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/15 3:44 下午 8 | */ 9 | 10 | public class TotalFruit { 11 | 12 | /** 13 | * [904. 水果成篮](https://leetcode-cn.com/problems/fruit-into-baskets/) 14 | * 15 | * @param fruits 16 | * @return 17 | */ 18 | public int totalFruit( int[] fruits ) { 19 | int res = 0; 20 | 21 | return res; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeBacktracking/CanPartitionKSubsets.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeBacktracking; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Comparator; 6 | import java.util.List; 7 | 8 | /** 9 | * @ClassName: CanPartitionKSubsets 10 | * @Description: 11 | * @author: dk 12 | * @date: 2021/12/30 5:47 下午 13 | */ 14 | 15 | public class CanPartitionKSubsets { 16 | 17 | public boolean canPartitionKSubsets( int[] nums, int k ) { 18 | // 排除一些基本情况 19 | if ( k > nums.length ) { 20 | return false; 21 | } 22 | int sum = 0; 23 | for ( int v : nums ) { 24 | sum += v; 25 | } 26 | if ( sum % k != 0 ) { 27 | return false; 28 | } 29 | // k 个桶(集合),记录每个桶装的数字之和 30 | int[] bucket = new int[k]; 31 | // 理论上每个桶(集合)中数字的和 32 | int target = sum / k; 33 | //逆序整个数组 34 | Arrays.sort( nums ); 35 | int i = 0, j = nums.length - 1; 36 | for ( ; i < j; i++, j-- ) { 37 | // 交换 nums[i] 和 nums[j] 38 | int temp = nums[i]; 39 | nums[i] = nums[j]; 40 | nums[j] = temp; 41 | } 42 | // 穷举,看看 nums 是否能划分成 k 个和为 target 的子集 43 | return backtrack( nums, 0, bucket, target ); 44 | } 45 | 46 | 47 | // 递归穷举 nums 中的每个数字 48 | boolean backtrack( 49 | int[] nums, int index, int[] bucket, int target ) { 50 | if ( index == nums.length ) { 51 | for ( int i = 0; i < bucket.length; i++ ) { 52 | if ( bucket[i] != target ) { 53 | return false; 54 | } 55 | } 56 | return true; 57 | } 58 | // 穷举 nums[index] 可能装入的桶 59 | for ( int i = 0; i < bucket.length; i++ ) { 60 | // 剪枝,桶装装满了 61 | if ( bucket[i] + nums[index] > target ) { 62 | continue; 63 | } 64 | // 将 nums[index] 装入 bucket[i] 65 | bucket[i] += nums[index]; 66 | // 递归穷举下一个数字的选择 67 | if ( backtrack( nums, index + 1, bucket, target ) ) { 68 | return true; 69 | } 70 | // 撤销选择 71 | bucket[i] -= nums[index]; 72 | } 73 | // nums[index] 装入哪个桶都不行 74 | return false; 75 | } 76 | 77 | 78 | public static void main( String[] args ) { 79 | List list = new ArrayList<>(); 80 | list.add( 4 ); 81 | list.add( 3 ); 82 | list.add( 5 ); 83 | list.add( 1 ); 84 | list.add( 6 ); 85 | // 正序 86 | // list.sort( Integer::compareTo ); 87 | // list.forEach( ( i ) -> System.out.println( i ) ); 88 | // 倒叙 89 | // list.sort( Comparator.reverseOrder() ); 90 | // list.forEach( ( i ) -> System.out.println( i ) ); 91 | 92 | list.sort( new Comparator() { 93 | @Override 94 | public int compare( Integer m1, Integer m2 ) { 95 | return m2 - m1; 96 | } 97 | } ); 98 | list.forEach( ( i ) -> System.out.println( i ) ); 99 | 100 | // List list = new ArrayList<>(); 101 | // list.add(new User(1,12,"java")); 102 | // list.add(new User(2,13, "python")); 103 | // list.add(new User(3,14, "js")); 104 | // list.add(new User(4,15, "scala")); 105 | // list.add(new User(5,16, "ruby")); 106 | // list.add(new User(6,17, "c")); 107 | // 108 | // list.sort((o1, o2) -> o2.getAge() - o1.getAge()); 109 | 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeBacktracking/CombinationSum.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeBacktracking; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * @ClassName: CombinationSum 9 | * @Description: 10 | * @author: dk 11 | * @date: 2021/12/31 3:01 下午 12 | */ 13 | 14 | public class CombinationSum { 15 | 16 | /** 17 | * https://leetcode-cn.com/problems/combination-sum/ 18 | * 19 | * @param candidates 20 | * @param target 21 | * @return 22 | */ 23 | List> res = new ArrayList<>(); 24 | LinkedList path = new LinkedList<>(); 25 | int sum = 0; 26 | // 全局变量,记录递归函数的递归层数 27 | int count = 0; 28 | 29 | 30 | // 输入 n,打印 n 个 tab 缩进 31 | void printIndent( int n ) { 32 | for ( int i = 0; i < n; i++ ) { 33 | System.out.printf( " " ); 34 | } 35 | } 36 | 37 | 38 | public List> combinationSum( int[] candidates, int target ) { 39 | getCombination( candidates, target, 0 ); 40 | return res; 41 | } 42 | 43 | 44 | private void getCombination( int[] candidates, int target, int start ) { 45 | if ( sum > target ) { 46 | return; 47 | } 48 | if ( sum == target ) { 49 | System.out.println( "进入收集,第" + count + "层 ,收集到结果=" + path.toString() ); 50 | res.add( new ArrayList<>( path ) ); 51 | return; 52 | } 53 | 54 | for ( int i = start; i < candidates.length; i++ ) { 55 | 56 | sum += candidates[i]; 57 | path.add( candidates[i] ); 58 | 59 | printIndent( count++ ); 60 | System.out.println( "i=" + i + "第" + count + "层 ,回溯前=" + path.toString() + "sum=" + sum ); 61 | 62 | getCombination( candidates, target, i ); 63 | 64 | sum -= candidates[i]; 65 | path.removeLast(); 66 | printIndent( --count ); 67 | System.out.println( "i=" + i + "第" + count + "层 ,回溯后=" + path.toString() ); 68 | } 69 | } 70 | 71 | } 72 | /* 73 | i=0第1层 ,回溯前=[2]sum=2 74 | i=0第2层 ,回溯前=[2, 2]sum=4 75 | i=0第3层 ,回溯前=[2, 2, 2]sum=6 76 | i=0第4层 ,回溯前=[2, 2, 2, 2]sum=8 77 | 进入收集,第4层 ,收集到结果=[2, 2, 2, 2] 78 | i=0第3层 ,回溯后=[2, 2, 2] 79 | i=1第4层 ,回溯前=[2, 2, 2, 3]sum=9 80 | i=1第3层 ,回溯后=[2, 2, 2] 81 | i=2第4层 ,回溯前=[2, 2, 2, 5]sum=11 82 | i=2第3层 ,回溯后=[2, 2, 2] 83 | i=0第2层 ,回溯后=[2, 2] 84 | i=1第3层 ,回溯前=[2, 2, 3]sum=7 85 | i=1第4层 ,回溯前=[2, 2, 3, 3]sum=10 86 | i=1第3层 ,回溯后=[2, 2, 3] 87 | i=2第4层 ,回溯前=[2, 2, 3, 5]sum=12 88 | i=2第3层 ,回溯后=[2, 2, 3] 89 | i=1第2层 ,回溯后=[2, 2] 90 | i=2第3层 ,回溯前=[2, 2, 5]sum=9 91 | i=2第2层 ,回溯后=[2, 2] 92 | i=0第1层 ,回溯后=[2] 93 | i=1第2层 ,回溯前=[2, 3]sum=5 94 | i=1第3层 ,回溯前=[2, 3, 3]sum=8 95 | 进入收集,第3层 ,收集到结果=[2, 3, 3] 96 | i=1第2层 ,回溯后=[2, 3] 97 | i=2第3层 ,回溯前=[2, 3, 5]sum=10 98 | i=2第2层 ,回溯后=[2, 3] 99 | i=1第1层 ,回溯后=[2] 100 | i=2第2层 ,回溯前=[2, 5]sum=7 101 | i=2第3层 ,回溯前=[2, 5, 5]sum=12 102 | i=2第2层 ,回溯后=[2, 5] 103 | i=2第1层 ,回溯后=[2] 104 | i=0第0层 ,回溯后=[] 105 | i=1第1层 ,回溯前=[3]sum=3 106 | i=1第2层 ,回溯前=[3, 3]sum=6 107 | i=1第3层 ,回溯前=[3, 3, 3]sum=9 108 | i=1第2层 ,回溯后=[3, 3] 109 | i=2第3层 ,回溯前=[3, 3, 5]sum=11 110 | i=2第2层 ,回溯后=[3, 3] 111 | i=1第1层 ,回溯后=[3] 112 | i=2第2层 ,回溯前=[3, 5]sum=8 113 | 进入收集,第2层 ,收集到结果=[3, 5] 114 | i=2第1层 ,回溯后=[3] 115 | i=1第0层 ,回溯后=[] 116 | i=2第1层 ,回溯前=[5]sum=5 117 | i=2第2层 ,回溯前=[5, 5]sum=10 118 | i=2第1层 ,回溯后=[5] 119 | i=2第0层 ,回溯后=[] 120 | 121 | */ -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeBacktracking/CombinationSum2.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeBacktracking; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | /** 9 | * @ClassName: CombinationSum2 10 | * @Description: 11 | * @author: dk 12 | * @date: 2021/12/31 3:27 下午 13 | */ 14 | 15 | public class CombinationSum2 { 16 | 17 | /** 18 | * https://leetcode-cn.com/problems/combination-sum-ii/ 19 | * 20 | * @param candidates 21 | * @param target 22 | * @return 23 | */ 24 | List> res = new ArrayList<>(); 25 | LinkedList path = new LinkedList<>(); 26 | 27 | 28 | public List> combinationSum2( int[] candidates, int target ) { 29 | Arrays.sort( candidates ); 30 | boolean[] used = new boolean[candidates.length]; 31 | getCombination( candidates, used, target, 0 ); 32 | return res; 33 | } 34 | 35 | 36 | int sum = 0; 37 | 38 | 39 | private void getCombination( int[] candidates, boolean[] used, int target, int start ) { 40 | if ( sum > target ) { 41 | return; 42 | } 43 | if ( sum == target ) { 44 | res.add( new ArrayList<>( path ) ); 45 | return; 46 | } 47 | 48 | for ( int i = start; i < candidates.length; i++ ) { 49 | 50 | //只能剔除第一位重复 题目要求是每一位开头只求一次 51 | //if(path.size()==0 && i>0 && candidates[i]==candidates[i-1])continue; 52 | 53 | // 相当于把重复元素值的解给剔除了 54 | //if(path.size()>0 && path.getLast()==candidates[i])continue; 55 | 56 | //如果candidates[i] == candidates[i - 1] 并且 used[i - 1] == false 57 | // 【1,2,2,2,5】 target=5 58 | // 1,2,2, 为一个解 59 | // 1,2, 再次选2 时,candidates[i] == candidates[i - 1] ,且 used[i - 1] == false 60 | // 代表 2 已经被选过,且是当前集合中选取过了,所以不能选,所以continue 61 | 62 | //正确剔除重复解的办法 63 | if ( i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1] ) { 64 | continue; 65 | } 66 | 67 | used[i] = true; 68 | sum += candidates[i]; 69 | path.add( candidates[i] ); 70 | 71 | getCombination( candidates, used, target, i + 1 ); 72 | 73 | used[i] = false; 74 | int temp = path.getLast(); 75 | sum -= temp; 76 | path.removeLast(); 77 | 78 | } 79 | } 80 | 81 | // List> res = new ArrayList<>(); 82 | // LinkedList path = new LinkedList<>(); 83 | // int sum = 0; 84 | 85 | 86 | public List> combinationSum2Two( int[] candidates, int target ) { 87 | //为了将重复的数字都放到一起,所以先进行排序 88 | Arrays.sort( candidates ); 89 | backTracking( candidates, target, 0 ); 90 | return res; 91 | } 92 | 93 | 94 | private void backTracking( int[] candidates, int target, int start ) { 95 | if ( sum == target ) { 96 | res.add( new ArrayList<>( path ) ); 97 | return; 98 | } 99 | for ( int i = start; i < candidates.length && sum + candidates[i] <= target; i++ ) { 100 | //正确剔除重复解的办法 101 | //跳过同一树层使用过的元素,当遍历当前元素时,如果发现,该元素与前一个元素一样,就可以直接跳过 102 | //https://leetcode-cn.com/problems/subsets-ii/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by-19/231171 103 | if ( i > start && candidates[i] == candidates[i - 1] ) { 104 | continue; 105 | } 106 | 107 | sum += candidates[i]; 108 | path.add( candidates[i] ); 109 | // i+1 代表当前组内元素只选取一次 110 | backTracking( candidates, target, i + 1 ); 111 | 112 | int temp = path.getLast(); 113 | sum -= temp; 114 | path.removeLast(); 115 | 116 | } 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeBacktracking/CombinationSum3.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeBacktracking; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | public class CombinationSum3 { 8 | 9 | /** 10 | * https://leetcode-cn.com/problems/combination-sum-iii/ 11 | * 12 | * @param k 13 | * @param n 14 | * @return 15 | */ 16 | List> res = new ArrayList<>(); 17 | LinkedList path = new LinkedList<>(); 18 | int sum = 0; 19 | int end = 9; 20 | 21 | 22 | public List> combinationSum3( int k, int n ) { 23 | show( k, n, 1 ); 24 | return res; 25 | } 26 | 27 | 28 | private void show( int k, int n, int start ) { 29 | //System.out.println(n+"--"+sum +" "+ k+"--"+ path.size()); 30 | if ( path.size() == k && sum == n ) { 31 | printIndent( count ); 32 | //System.out.println( "进入收集,第" + count + "层 ,收集到结果=" + path.toString() ); 33 | res.add( new ArrayList<>( path ) ); 34 | return; 35 | } else if ( sum > n ) { 36 | return; 37 | } 38 | 39 | for ( int i = start; i <= end; i++ ) { 40 | if ( path.contains( i ) ) { 41 | continue; 42 | } 43 | 44 | path.add( i ); 45 | sum = sum + i; 46 | 47 | printIndent( count++ ); 48 | //System.out.println( "i=" + i + "第" + count + "层 ,回溯前=" + path.toString() + "sum="+sum); 49 | show( k, n, i + 1 ); 50 | path.removeLast(); 51 | sum = sum - i; 52 | 53 | printIndent( --count ); 54 | //System.out.println( "i=" + i + "第" + count + "层 ,回溯后=" + path.toString() ); 55 | } 56 | } 57 | 58 | 59 | // 全局变量,记录递归函数的递归层数 60 | int count = 0; 61 | 62 | 63 | // 输入 n,打印 n 个 tab 缩进 64 | void printIndent( int n ) { 65 | for ( int i = 0; i < n; i++ ) { 66 | System.out.printf( " " ); 67 | } 68 | } 69 | 70 | } 71 | 72 | /* 73 | i=1第1层 ,回溯前=[1]sum=1 74 | i=2第2层 ,回溯前=[1, 2]sum=3 75 | i=3第3层 ,回溯前=[1, 2, 3]sum=6 76 | i=4第4层 ,回溯前=[1, 2, 3, 4]sum=10 77 | i=4第3层 ,回溯后=[1, 2, 3] 78 | i=5第4层 ,回溯前=[1, 2, 3, 5]sum=11 79 | i=5第3层 ,回溯后=[1, 2, 3] 80 | i=6第4层 ,回溯前=[1, 2, 3, 6]sum=12 81 | i=6第3层 ,回溯后=[1, 2, 3] 82 | i=7第4层 ,回溯前=[1, 2, 3, 7]sum=13 83 | i=7第3层 ,回溯后=[1, 2, 3] 84 | i=8第4层 ,回溯前=[1, 2, 3, 8]sum=14 85 | i=8第3层 ,回溯后=[1, 2, 3] 86 | i=9第4层 ,回溯前=[1, 2, 3, 9]sum=15 87 | i=9第3层 ,回溯后=[1, 2, 3] 88 | i=3第2层 ,回溯后=[1, 2] 89 | i=4第3层 ,回溯前=[1, 2, 4]sum=7 90 | i=5第4层 ,回溯前=[1, 2, 4, 5]sum=12 91 | i=5第3层 ,回溯后=[1, 2, 4] 92 | i=6第4层 ,回溯前=[1, 2, 4, 6]sum=13 93 | i=6第3层 ,回溯后=[1, 2, 4] 94 | i=7第4层 ,回溯前=[1, 2, 4, 7]sum=14 95 | i=7第3层 ,回溯后=[1, 2, 4] 96 | i=8第4层 ,回溯前=[1, 2, 4, 8]sum=15 97 | i=8第3层 ,回溯后=[1, 2, 4] 98 | i=9第4层 ,回溯前=[1, 2, 4, 9]sum=16 99 | i=9第3层 ,回溯后=[1, 2, 4] 100 | i=4第2层 ,回溯后=[1, 2] 101 | i=5第3层 ,回溯前=[1, 2, 5]sum=8 102 | i=6第4层 ,回溯前=[1, 2, 5, 6]sum=14 103 | i=6第3层 ,回溯后=[1, 2, 5] 104 | i=7第4层 ,回溯前=[1, 2, 5, 7]sum=15 105 | i=7第3层 ,回溯后=[1, 2, 5] 106 | i=8第4层 ,回溯前=[1, 2, 5, 8]sum=16 107 | i=8第3层 ,回溯后=[1, 2, 5] 108 | i=9第4层 ,回溯前=[1, 2, 5, 9]sum=17 109 | i=9第3层 ,回溯后=[1, 2, 5] 110 | i=5第2层 ,回溯后=[1, 2] 111 | i=6第3层 ,回溯前=[1, 2, 6]sum=9 112 | 进入收集,第3层 ,收集到结果=[1, 2, 6] 113 | i=6第2层 ,回溯后=[1, 2] 114 | i=7第3层 ,回溯前=[1, 2, 7]sum=10 115 | i=7第2层 ,回溯后=[1, 2] 116 | i=8第3层 ,回溯前=[1, 2, 8]sum=11 117 | i=8第2层 ,回溯后=[1, 2] 118 | i=9第3层 ,回溯前=[1, 2, 9]sum=12 119 | i=9第2层 ,回溯后=[1, 2] 120 | i=2第1层 ,回溯后=[1] 121 | i=3第2层 ,回溯前=[1, 3]sum=4 122 | i=4第3层 ,回溯前=[1, 3, 4]sum=8 123 | i=5第4层 ,回溯前=[1, 3, 4, 5]sum=13 124 | i=5第3层 ,回溯后=[1, 3, 4] 125 | i=6第4层 ,回溯前=[1, 3, 4, 6]sum=14 126 | i=6第3层 ,回溯后=[1, 3, 4] 127 | i=7第4层 ,回溯前=[1, 3, 4, 7]sum=15 128 | i=7第3层 ,回溯后=[1, 3, 4] 129 | i=8第4层 ,回溯前=[1, 3, 4, 8]sum=16 130 | i=8第3层 ,回溯后=[1, 3, 4] 131 | i=9第4层 ,回溯前=[1, 3, 4, 9]sum=17 132 | i=9第3层 ,回溯后=[1, 3, 4] 133 | i=4第2层 ,回溯后=[1, 3] 134 | i=5第3层 ,回溯前=[1, 3, 5]sum=9 135 | 进入收集,第3层 ,收集到结果=[1, 3, 5] 136 | i=5第2层 ,回溯后=[1, 3] 137 | i=6第3层 ,回溯前=[1, 3, 6]sum=10 138 | i=6第2层 ,回溯后=[1, 3] 139 | i=7第3层 ,回溯前=[1, 3, 7]sum=11 140 | i=7第2层 ,回溯后=[1, 3] 141 | i=8第3层 ,回溯前=[1, 3, 8]sum=12 142 | i=8第2层 ,回溯后=[1, 3] 143 | i=9第3层 ,回溯前=[1, 3, 9]sum=13 144 | i=9第2层 ,回溯后=[1, 3] 145 | i=3第1层 ,回溯后=[1] 146 | i=4第2层 ,回溯前=[1, 4]sum=5 147 | i=5第3层 ,回溯前=[1, 4, 5]sum=10 148 | i=5第2层 ,回溯后=[1, 4] 149 | i=6第3层 ,回溯前=[1, 4, 6]sum=11 150 | i=6第2层 ,回溯后=[1, 4] 151 | i=7第3层 ,回溯前=[1, 4, 7]sum=12 152 | i=7第2层 ,回溯后=[1, 4] 153 | i=8第3层 ,回溯前=[1, 4, 8]sum=13 154 | i=8第2层 ,回溯后=[1, 4] 155 | i=9第3层 ,回溯前=[1, 4, 9]sum=14 156 | i=9第2层 ,回溯后=[1, 4] 157 | i=4第1层 ,回溯后=[1] 158 | i=5第2层 ,回溯前=[1, 5]sum=6 159 | i=6第3层 ,回溯前=[1, 5, 6]sum=12 160 | i=6第2层 ,回溯后=[1, 5] 161 | i=7第3层 ,回溯前=[1, 5, 7]sum=13 162 | i=7第2层 ,回溯后=[1, 5] 163 | i=8第3层 ,回溯前=[1, 5, 8]sum=14 164 | i=8第2层 ,回溯后=[1, 5] 165 | i=9第3层 ,回溯前=[1, 5, 9]sum=15 166 | i=9第2层 ,回溯后=[1, 5] 167 | i=5第1层 ,回溯后=[1] 168 | i=6第2层 ,回溯前=[1, 6]sum=7 169 | i=7第3层 ,回溯前=[1, 6, 7]sum=14 170 | i=7第2层 ,回溯后=[1, 6] 171 | i=8第3层 ,回溯前=[1, 6, 8]sum=15 172 | i=8第2层 ,回溯后=[1, 6] 173 | ... 162 more lines 174 | */ -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeBacktracking/Combine.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeBacktracking; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashMap; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | 9 | /** 10 | * @ClassName: Combine 11 | * @Description: 12 | * @author: dk 13 | * @date: 2021/12/31 1:18 下午 14 | */ 15 | 16 | public class Combine { 17 | 18 | /** 19 | * https://leetcode-cn.com/problems/combinations/ 20 | * 21 | * @param n 22 | * @param k 23 | * @return 24 | */ 25 | List> res = new ArrayList<>(); 26 | //路径集合 27 | LinkedList path = new LinkedList<>(); 28 | 29 | 30 | public List> findSubsequences( int[] nums ) { 31 | 32 | getSubsequences( nums, 0 ); 33 | return res; 34 | } 35 | 36 | 37 | private void getSubsequences( int[] nums, int start ) { 38 | HashMap map = new HashMap<>(200); 39 | List> list = new ArrayList<>(); 40 | 41 | list.add( Arrays.asList( 1,2,3 ) ); 42 | 43 | if ( path.size() > 1 ) { 44 | res.add( new ArrayList<>( path ) ); 45 | // 注意这里不要加return,要取树上的节点 46 | } 47 | int[] used = new int[201]; 48 | for ( int i = start; i < nums.length; i++ ) { 49 | 50 | if ( !path.isEmpty() && nums[i] < path.getLast() ) { 51 | continue; 52 | } 53 | 54 | if ( used[nums[i] + 100] == 1 ) { 55 | continue; 56 | } 57 | 58 | used[nums[i] + 100] = 1; 59 | 60 | path.add( nums[i] ); 61 | getSubsequences( nums, i + 1 ); 62 | path.removeLast(); 63 | } 64 | } 65 | 66 | 67 | // 全局变量,记录递归函数的递归层数 68 | int count = 0; 69 | 70 | 71 | // 输入 n,打印 n 个 tab 缩进 72 | void printIndent( int n ) { 73 | for ( int i = 0; i < n; i++ ) { 74 | System.out.printf( " " ); 75 | } 76 | } 77 | 78 | } 79 | /* 80 | i=1第1层 ,回溯前=[1] 81 | i=2第2层 ,回溯前=[1, 2] 82 | 进入收集,第2层 ,收集到结果=[1, 2] 83 | i=2第1层 ,回溯后=[1] 84 | i=3第2层 ,回溯前=[1, 3] 85 | 进入收集,第2层 ,收集到结果=[1, 3] 86 | i=3第1层 ,回溯后=[1] 87 | i=4第2层 ,回溯前=[1, 4] 88 | 进入收集,第2层 ,收集到结果=[1, 4] 89 | i=4第1层 ,回溯后=[1] 90 | i=1第0层 ,回溯后=[] 91 | i=2第1层 ,回溯前=[2] 92 | i=3第2层 ,回溯前=[2, 3] 93 | 进入收集,第2层 ,收集到结果=[2, 3] 94 | i=3第1层 ,回溯后=[2] 95 | i=4第2层 ,回溯前=[2, 4] 96 | 进入收集,第2层 ,收集到结果=[2, 4] 97 | i=4第1层 ,回溯后=[2] 98 | i=2第0层 ,回溯后=[] 99 | i=3第1层 ,回溯前=[3] 100 | i=4第2层 ,回溯前=[3, 4] 101 | 进入收集,第2层 ,收集到结果=[3, 4] 102 | i=4第1层 ,回溯后=[3] 103 | i=3第0层 ,回溯后=[] 104 | i=4第1层 ,回溯前=[4] 105 | i=4第0层 ,回溯后=[] 106 | 107 | */ 108 | 109 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeBacktracking/FindSubsequences.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeBacktracking; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * @ClassName: FindSubsequences 9 | * @Description: 10 | * @author: dk 11 | * @date: 2022/1/3 12:25 下午 12 | */ 13 | 14 | public class FindSubsequences { 15 | 16 | /** 17 | * https://leetcode-cn.com/problems/increasing-subsequences/ 18 | * 19 | * @param nums 20 | * @return 21 | */ 22 | //结果集合 23 | List> res = new ArrayList<>(); 24 | //路径集合 25 | LinkedList path = new LinkedList<>(); 26 | 27 | 28 | public List> findSubsequences( int[] nums ) { 29 | getSubsequences( nums, 0 ); 30 | return res; 31 | } 32 | 33 | 34 | private void getSubsequences( int[] nums, int start ) { 35 | if ( path.size() > 1 ) { 36 | res.add( new ArrayList<>( path ) ); 37 | return; 38 | } 39 | 40 | for ( int i = start; i < nums.length; i++ ) { 41 | 42 | if ( path.size() > 1 && path.getLast() < nums[i] ) { 43 | return; 44 | } 45 | if ( i > start && nums[i - 1] > nums[i] ) { 46 | return; 47 | } 48 | path.add( nums[i] ); 49 | getSubsequences( nums, i + 1 ); 50 | path.removeLast(); 51 | } 52 | } 53 | /** 使用map 54 | //结果集合 55 | List> res = new ArrayList<>(); 56 | //路径集合 57 | LinkedList path = new LinkedList<>(); 58 | public List> findSubsequences(int[] nums) { 59 | getSubsequences(nums,0); 60 | return res; 61 | } 62 | private void getSubsequences( int[] nums, int start ) { 63 | if(path.size()>1 ){ 64 | res.add( new ArrayList<>(path) ); 65 | // 注意这里不要加return,要取树上的节点 66 | } 67 | HashMap map = new HashMap<>(); 68 | for(int i=start ;i < nums.length ;i++){ 69 | if(!path.isEmpty() && nums[i]< path.getLast()){ 70 | continue; 71 | } 72 | if ( map.getOrDefault( nums[i],0 ) >=1 ){ 73 | continue; 74 | } 75 | map.put(nums[i],map.getOrDefault( nums[i],0 )+1); 76 | path.add( nums[i] ); 77 | getSubsequences( nums,i+1 ); 78 | path.removeLast(); 79 | 80 | } 81 | } 82 | */ 83 | //TODO 为随想录添加新的解法 84 | //https://leetcode-cn.com/problems/increasing-subsequences/ 85 | //https://www.programmercarl.com/0491.%E9%80%92%E5%A2%9E%E5%AD%90%E5%BA%8F%E5%88%97.html#%E6%80%9D%E8%B7%AF 86 | 87 | /* 88 | i=0第1层 ,回溯前=[4] 89 | i=1第2层 ,回溯前=[4, 6] 90 | 进入收集,第2层 ,收集到结果=[4, 6] 91 | i=2第3层 ,回溯前=[4, 6, 7] 92 | 进入收集,第3层 ,收集到结果=[4, 6, 7] 93 | i=3第4层 ,回溯前=[4, 6, 7, 7] 94 | 进入收集,第4层 ,收集到结果=[4, 6, 7, 7] 95 | i=3第3层 ,回溯后=[4, 6, 7] 96 | i=2第2层 ,回溯后=[4, 6] 97 | i=3第2层 ,重复的元素是:7 98 | i=1第1层 ,回溯后=[4] 99 | i=2第2层 ,回溯前=[4, 7] 100 | 进入收集,第2层 ,收集到结果=[4, 7] 101 | i=3第3层 ,回溯前=[4, 7, 7] 102 | 进入收集,第3层 ,收集到结果=[4, 7, 7] 103 | i=3第2层 ,回溯后=[4, 7] 104 | i=2第1层 ,回溯后=[4] 105 | i=3第1层 ,重复的元素是:7 106 | i=0第0层 ,回溯后=[] 107 | i=1第1层 ,回溯前=[6] 108 | i=2第2层 ,回溯前=[6, 7] 109 | 进入收集,第2层 ,收集到结果=[6, 7] 110 | i=3第3层 ,回溯前=[6, 7, 7] 111 | 进入收集,第3层 ,收集到结果=[6, 7, 7] 112 | i=3第2层 ,回溯后=[6, 7] 113 | i=2第1层 ,回溯后=[6] 114 | i=3第1层 ,重复的元素是:7 115 | i=1第0层 ,回溯后=[] 116 | i=2第1层 ,回溯前=[7] 117 | i=3第2层 ,回溯前=[7, 7] 118 | 进入收集,第2层 ,收集到结果=[7, 7] 119 | i=3第1层 ,回溯后=[7] 120 | i=2第0层 ,回溯后=[] 121 | i=3第0层 ,重复的元素是:7 122 | 123 | */ 124 | 125 | 126 | } 127 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeBacktracking/Partition.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeBacktracking; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * @ClassName: Partition 9 | * @Description: 10 | * @author: dk 11 | * @date: 2022/1/2 9:40 上午 12 | */ 13 | 14 | public class Partition { 15 | 16 | 17 | 18 | 19 | /** 20 | * https://leetcode-cn.com/problems/palindrome-partitioning/ 21 | * @param s 22 | * @return 23 | */ 24 | List> res = new ArrayList<>(); 25 | LinkedList path = new LinkedList<>(); 26 | public List> partition(String s) { 27 | show(s,0); 28 | return res; 29 | } 30 | private void show( String s ,int start) { 31 | if ( start>=s.length() ){ 32 | res.add( new LinkedList<>(path) ); 33 | return; 34 | } 35 | for(int i=start;i> res = new LinkedList<>(); 21 | LinkedList path = new LinkedList<>(); 22 | 23 | 24 | public List> permute( int[] nums ) { 25 | //dfs( nums ); 26 | dfsTwo( nums, 0 ); 27 | return res; 28 | } 29 | 30 | 31 | private void dfs( int[] nums ) { 32 | if ( path.size() == nums.length ) { 33 | res.add( new LinkedList<>( path ) ); 34 | return; 35 | } 36 | for ( int i = 0; i < nums.length; i++ ) { 37 | if ( path.contains( nums[i] ) ) { 38 | continue; 39 | } 40 | path.add( nums[i] ); 41 | dfs( nums ); 42 | path.removeLast(); 43 | } 44 | } 45 | 46 | 47 | private void dfsTwo( int[] nums, int start ) { 48 | if ( start == nums.length ) { 49 | List list = new ArrayList<>(); 50 | for ( int i = 0; i < nums.length; i++ ) { 51 | list.add( nums[i] ); 52 | } 53 | res.add( new LinkedList<>( list ) ); 54 | return; 55 | } 56 | for ( int i = start; i < nums.length; i++ ) { 57 | swap( nums, i, start ); 58 | dfsTwo( nums, start + 1 ); 59 | swap( nums, i, start ); 60 | } 61 | } 62 | 63 | 64 | public static void swap( int[] arr, int i, int j ) { 65 | int tmp = arr[i]; 66 | arr[i] = arr[j]; 67 | arr[j] = tmp; 68 | } 69 | 70 | //TODO 为随想录添加新的解法 71 | //https://www.programmercarl.com/0046.%E5%85%A8%E6%8E%92%E5%88%97.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC 72 | 73 | 74 | 75 | 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeBacktracking/PermuteUnique.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeBacktracking; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * @ClassName: PermuteUnique 9 | * @Description: 10 | * @author: dk 11 | * @date: 2022/1/3 1:35 下午 12 | */ 13 | 14 | public class PermuteUnique { 15 | 16 | /** 17 | * https://leetcode-cn.com/problems/permutations-ii/ 18 | * 19 | * @param nums 20 | * @return 21 | */ 22 | //结果集合 23 | List> res = new ArrayList<>(); 24 | //路径集合 25 | LinkedList path = new LinkedList<>(); 26 | 27 | 28 | public List> permuteUnique( int[] nums ) { 29 | boolean[] used = new boolean[nums.length]; 30 | getPermute( nums, used, 0 ); 31 | return res; 32 | } 33 | 34 | 35 | private void getPermute( int[] nums, boolean[] used, int start ) { 36 | if ( path.size() == nums.length ) { 37 | res.add( new ArrayList<>( path ) ); 38 | return; 39 | } 40 | for ( int i = 0; i < nums.length; i++ ) { 41 | 42 | if ( i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false ) { 43 | continue; 44 | } 45 | if ( used[i] == false ) { 46 | used[i] = true; 47 | path.add( nums[i] ); 48 | getPermute( nums, used, i + 1 ); 49 | path.removeLast(); 50 | used[i] = false; 51 | 52 | } 53 | 54 | 55 | } 56 | } 57 | 58 | //TODO 随想录代码优化 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeBacktracking/RestoreIpAddresses.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeBacktracking; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * @ClassName: RestoreIpAddresses 9 | * @Description: 10 | * @author: dk 11 | * @date: 2022/1/2 10:12 上午 12 | */ 13 | 14 | public class RestoreIpAddresses { 15 | 16 | /** 17 | * https://leetcode-cn.com/problems/restore-ip-addresses/ 18 | * 19 | * @param s 20 | * @return 21 | */ 22 | List res = new ArrayList<>(); 23 | LinkedList path = new LinkedList<>(); 24 | 25 | 26 | public List restoreIpAddresses( String s ) { 27 | show( s, 0 ); 28 | return res; 29 | } 30 | 31 | 32 | String point = "."; 33 | 34 | 35 | private void show( String s, int start ) { 36 | if ( start >= s.length() && path.size() == 4 ) { 37 | String temp = ""; 38 | for ( int i = 0; i < path.size(); i++ ) { 39 | temp = temp + path.get( i ); 40 | if ( i != path.size() - 1 ) { 41 | temp = temp + point; 42 | } 43 | } 44 | res.add( temp ); 45 | return; 46 | } 47 | for ( int i = start; i < s.length(); i++ ) { 48 | String temp = s.substring( start, i + 1 ); 49 | if ( legal( temp ) ) { 50 | path.add( temp ); 51 | } else { 52 | continue; 53 | } 54 | show( s, i + 1 ); 55 | path.removeLast(); 56 | } 57 | } 58 | 59 | 60 | int illLegalNum = 255; 61 | 62 | 63 | private boolean legal( String temp ) { 64 | if ( temp.length() == 1 ) { 65 | return true; 66 | } 67 | //前导0 68 | if ( temp.length() > 1 && temp.charAt( 0 ) - '0' == 0 ) { 69 | return false; 70 | } 71 | if ( temp.length() >= 4 ) { 72 | return false; 73 | } 74 | int num = Integer.valueOf( temp ); 75 | if ( num > illLegalNum ) { 76 | return false; 77 | } 78 | return true; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeBacktracking/SubsetsWithDup.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeBacktracking; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | /** 9 | * @ClassName: SubsetsWithDup 10 | * @Description: 11 | * @author: dk 12 | * @date: 2022/1/2 10:50 上午 13 | */ 14 | 15 | public class SubsetsWithDup { 16 | 17 | /** 18 | * https://leetcode-cn.com/problems/subsets-ii/ 19 | * 20 | * @param nums 21 | * @return 22 | */ 23 | List> res = new ArrayList<>(); 24 | LinkedList path = new LinkedList<>(); 25 | 26 | 27 | public List> subsetsWithDup( int[] nums ) { 28 | Arrays.sort( nums ); 29 | show( nums, 0 ); 30 | return res; 31 | } 32 | 33 | 34 | private void show( int[] nums, int start ) { 35 | res.add( new ArrayList<>( path ) ); 36 | System.out.println( "进入收集,第" + count + "层 ,收集到结果=" + path.toString() ); 37 | 38 | for ( int i = start; i < nums.length; i++ ) { 39 | if ( i > start && nums[i - 1] == nums[i] ) { 40 | continue; 41 | } 42 | 43 | path.add( nums[i] ); 44 | printIndent( count++ ); 45 | System.out.println( "i=" + i + "第" + count + "层 ,回溯前=" + path.toString() ); 46 | show( nums, i + 1 ); 47 | path.removeLast(); 48 | printIndent( --count ); 49 | System.out.println( "i=" + i + "第" + count + "层 ,回溯后=" + path.toString() ); 50 | } 51 | 52 | } 53 | 54 | 55 | // 全局变量,记录递归函数的递归层数 56 | int count = 0; 57 | 58 | 59 | // 输入 n,打印 n 个 tab 缩进 60 | void printIndent( int n ) { 61 | for ( int i = 0; i < n; i++ ) { 62 | System.out.printf( " " ); 63 | } 64 | } 65 | 66 | } 67 | 68 | /* 69 | 进入收集,第0层 ,收集到结果=[] 70 | start=0 i=0第1层 ,回溯前=[1] 71 | 进入收集,第1层 ,收集到结果=[1] 72 | start=1 i=1第2层 ,回溯前=[1, 2] 73 | 进入收集,第2层 ,收集到结果=[1, 2] 74 | start=2 i=2第3层 ,回溯前=[1, 2, 2] 75 | 进入收集,第3层 ,收集到结果=[1, 2, 2] 76 | start=2 i=2第2层 ,回溯后=[1, 2] 77 | start=1 i=1第1层 ,回溯后=[1] 78 | start=0 i=0第0层 ,回溯后=[] 79 | start=0 i=1第1层 ,回溯前=[2] 80 | 进入收集,第1层 ,收集到结果=[2] 81 | start=2 i=2第2层 ,回溯前=[2, 2] 82 | 进入收集,第2层 ,收集到结果=[2, 2] 83 | start=2 i=2第1层 ,回溯后=[2] 84 | start=0 i=1第0层 ,回溯后=[] 85 | 86 | 87 | ----------------------------------不加去重 88 | 进入收集,第0层 ,收集到结果=[] 89 | start=0 i=0第1层 ,回溯前=[1] 90 | 进入收集,第1层 ,收集到结果=[1] 91 | start=1 i=1第2层 ,回溯前=[1, 2] 92 | 进入收集,第2层 ,收集到结果=[1, 2] 93 | start=2 i=2第3层 ,回溯前=[1, 2, 2] 94 | 进入收集,第3层 ,收集到结果=[1, 2, 2] 95 | start=2 i=2第2层 ,回溯后=[1, 2] 96 | start=1 i=1第1层 ,回溯后=[1] 97 | ----start=1 i=2第2层 ,回溯前=[1, 2]------ 98 | 进入收集,第2层 ,收集到结果=[1, 2]---------- 99 | start=1 i=2第1层 ,回溯后=[1] 100 | start=0 i=0第0层 ,回溯后=[] 101 | start=0 i=1第1层 ,回溯前=[2] 102 | 进入收集,第1层 ,收集到结果=[2] 103 | start=2 i=2第2层 ,回溯前=[2, 2] 104 | 进入收集,第2层 ,收集到结果=[2, 2] 105 | start=2 i=2第1层 ,回溯后=[2] 106 | start=0 i=1第0层 ,回溯后=[] 107 | start=0 i=2第1层 ,回溯前=[2]---------- 108 | 进入收集,第1层 ,收集到结果=[2]---------- 109 | start=0 i=2第0层 ,回溯后=[] 110 | 111 | 112 | */ 113 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeDynamicProgram/Bag/Bag.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeDynamicProgram.Bag; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @ClassName: Bag 7 | * @Description: 8 | * @author: dk 9 | * @date: 2022/2/26 6:40 下午 10 | */ 11 | 12 | public class Bag { 13 | 14 | //物品有3件 15 | static int N = 3; 16 | //背包容量为5 17 | static int W = 5; 18 | static int weight[] = { 1, 2, 3 }; 19 | static int value[] = { 6, 9, 13 }; 20 | 21 | 22 | public static void getValue() { 23 | //sum[i][j]意思是:背包容量为j时,在前i件物品中取小于等于i件物品,此时取得的物品的价值最大 24 | int sum[][] = new int[N + 1][W + 1]; 25 | 26 | for ( int i = 1; i <= N; i++ ) { 27 | for ( int j = 1; j <= W; j++ ) { 28 | if ( weight[i - 1] > j ) { 29 | //太重了,拿不了 30 | // 不拿: sum[i-1][j] 31 | sum[i][j] = sum[i - 1][j]; 32 | } else { 33 | //拿:sum[i-1][j-weight[i-1]]+value[i-1] 34 | 35 | //sum[i-1][j-weight[i-1]]可以理解为此时还没拿第i件的最大价值,要留weight[i]空间 36 | sum[i][j] = Math.max( sum[i - 1][j], sum[i - 1][j - weight[i - 1]] + value[i - 1] ); 37 | } 38 | } 39 | } 40 | for ( int i = 0; i < N + 1; i++ ) { 41 | for ( int j = 0; j < W + 1; j++ ) { 42 | System.out.print( " " + sum[i][j] ); 43 | } 44 | System.out.println(); 45 | } 46 | System.out.println( sum[N][W] ); 47 | } 48 | 49 | 50 | public static int getMaxValue( int[] w, int[] v, int bag ) { 51 | return process( w, v, 0, 0, bag ); 52 | } 53 | 54 | 55 | /** 56 | * 01 背包暴力递归代码 57 | * 58 | * 0--index-1 上做了的货物选择,使得当前已经达到的重量是 alreadyW 59 | * 60 | * @param w 61 | * @param v 62 | * @param index 63 | * @param alreadyW 64 | * @param bag 65 | * @return 66 | */ 67 | public static int process( int[] w, int[] v, int index, int alreadyW, int bag ) { 68 | // 认为此时没有方案 69 | if ( alreadyW > bag ) { 70 | return -1; 71 | } 72 | // 重量没抄 73 | if ( index == w.length ) { 74 | return 0; 75 | } 76 | // 没有选当前物品 77 | int p1 = process( w, v, index + 1, alreadyW, bag ); 78 | // 选择了当前位置的物品 79 | int p2Next = process( w, v, index + 1, alreadyW + w[index], bag ); 80 | int p2 = -1; 81 | // 如果选择了当前未知的物品,且最后有合理的方案,则p2Next不会是-1, 82 | if ( p2Next != -1 ) { 83 | p2 = v[index] + p2Next; 84 | } 85 | return Math.max( p1, p2 ); 86 | } 87 | 88 | 89 | /** 90 | * 只剩下了rest的空间 91 | * index..... 的货物自由选择,但是剩下的空间rest 不要小于 0 92 | * 返回 能够获得的最大价值 93 | * 94 | * @param w 95 | * @param v 96 | * @param index 97 | * @param rest 98 | * @return 99 | */ 100 | public static int process2( int[] w, int[] v, int index, int rest ) { 101 | // 认为此时没有方案 102 | if ( rest <= 0 ) { 103 | return 0; 104 | } 105 | // 重量没抄 且此时存在 rest>=0 106 | if ( index == w.length ) { 107 | return 0; 108 | } 109 | // 没有选当前物品 110 | int p1 = process2( w, v, index + 1, rest ); 111 | // 选择了当前位置的物品 112 | int p2 = Integer.MIN_VALUE; 113 | // 如果选择了当前位置的物品,且最后有合理的方案 114 | if ( rest >= w[index] ) { 115 | p2 = v[index] + process2( w, v, index + 1, rest - w[index] ); 116 | } 117 | return Math.max( p1, p2 ); 118 | } 119 | 120 | 121 | public static int dpWay( int[] w, int[] v, int bag ) { 122 | int N = w.length; 123 | int[][] dp = new int[N + 1][bag + 1]; 124 | // dp[N][...] = 0 125 | for ( int index = N - 1; index >= 0; index-- ) { 126 | // rest < 0 127 | for ( int rest = 0; rest <= bag; rest++ ) { 128 | 129 | int p1 = dp[index + 1][rest]; 130 | int p2 = -1; 131 | if ( rest - w[index] >= 0 ) { 132 | p2 = v[index] + dp[index + 1][rest - w[index]]; 133 | } 134 | dp[index][rest] = Math.max( p1, p2 ); 135 | 136 | // int p1 = process2( w, v, index + 1, rest ); 137 | // int p2 = Integer.MIN_VALUE; 138 | // if ( rest >= w[index] ) { 139 | // p2 = v[index] + process2( w, v, index + 1, rest - w[index] ); 140 | // } 141 | // return Math.max( p1, p2 ); 142 | 143 | } 144 | } 145 | for ( int i = 0; i < dp.length; i++ ) { 146 | for ( int j = 0; j < dp[0].length; j++ ) { 147 | System.out.printf( "%3d", dp[i][j] ); 148 | } 149 | System.out.println(); 150 | } 151 | return dp[0][bag]; 152 | } 153 | 154 | 155 | public static void dynamicByBag( int[] weight, int[] value, int index, int rest ) { 156 | int[][] dp = new int[N + 1][W + 1]; 157 | 158 | for ( int i = 1; i < N + 1; i++ ) { 159 | for ( int j = 1; j < W + 1; j++ ) { 160 | if ( j < weight[i - 1] ) { 161 | dp[i][j] = dp[i - 1][j]; 162 | } else { 163 | dp[i][j] = Math.max( dp[i - 1][j], dp[i - 1][j - weight[i - 1]] + value[i - 1] ); 164 | } 165 | } 166 | } 167 | System.out.println( "动态规划求解:" ); 168 | for ( int i = 0; i < dp.length; i++ ) { 169 | for ( int j = 0; j < dp[0].length; j++ ) { 170 | System.out.printf( "%3d", dp[i][j] ); 171 | } 172 | System.out.println(); 173 | } 174 | System.out.println( dp[N][W] ); 175 | } 176 | 177 | 178 | public static void testweightbagproblem( int[] weight, int[] value, int bagsize ) { 179 | int wlen = weight.length, value0 = 0; 180 | //定义dp数组:dp[i][j]表示背包容量为j时,前i个物品能获得的最大价值 181 | int[][] dp = new int[wlen + 1][bagsize + 1]; 182 | //初始化:背包容量为0时,能获得的价值都为0 183 | for ( int i = 0; i <= wlen; i++ ) { 184 | dp[i][0] = value0; 185 | } 186 | //遍历顺序:先遍历物品,再遍历背包容量 187 | for ( int i = 1; i <= wlen; i++ ) { 188 | for ( int j = 1; j <= bagsize; j++ ) { 189 | if ( j < weight[i - 1] ) { 190 | dp[i][j] = dp[i - 1][j]; 191 | } else { 192 | dp[i][j] = Math.max( dp[i - 1][j], dp[i - 1][j - weight[i - 1]] + value[i - 1] ); 193 | } 194 | } 195 | } 196 | //打印dp数组 197 | for ( int i = 0; i <= wlen; i++ ) { 198 | for ( int j = 0; j <= bagsize; j++ ) { 199 | System.out.print( dp[i][j] + " " ); 200 | } 201 | System.out.print( "\n" ); 202 | } 203 | } 204 | public static void getValueWrongWay() { 205 | int sum[] = new int[W+1]; 206 | 207 | for ( int i = 0; i = weight[i]; j-- ) { 221 | sum[j] = Math.max( sum[j], sum[j - weight[i]] + value[i] ); 222 | System.out.println("此时i="+ i + " j=" + j + " 整个数组情况为:" + Arrays.toString( sum ) ); 223 | } 224 | } 225 | System.out.println(sum[W]); 226 | } 227 | 228 | 229 | public static void main( String[] args ) { 230 | // getValue(); 231 | // System.out.println( getMaxValue( weight, value, W ) ); 232 | // System.out.println( process2( weight, value, 0, W ) ); 233 | 234 | // dynamicByBag( weight, value, 0, W ); 235 | 236 | // System.out.println("暴力递归"); 237 | // System.out.println( process2( weight, value, 0, W ) ); 238 | // System.out.println( "暴力递归改为动态规划" ); 239 | // System.out.println( dpWay( weight, value, 5 ) ); 240 | 241 | int[] weight = { 1, 5, 5, 11 }; 242 | int[] value = { 6, 9, 13, 15 }; 243 | int bagsize = 12; 244 | testweightbagproblem( weight, value, bagsize ); 245 | 246 | // System.out.println("一纬数组优化"); 247 | // getValue1(); 248 | // System.out.println("一纬数组优化错误示范"); 249 | // getValueWrongWay(); 250 | } 251 | 252 | } 253 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeDynamicProgram/Bag/CanPartition.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeDynamicProgram.Bag; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @ClassName: CanPartition 8 | * @Description: 9 | * @author: dk 10 | * @date: 2022/2/28 4:10 下午 11 | */ 12 | 13 | public class CanPartition { 14 | 15 | /** 16 | * https://leetcode-cn.com/problems/partition-equal-subset-sum/ 17 | * 18 | * @param nums 19 | * @return 20 | */ 21 | public boolean canPartition( int[] nums ) { 22 | return false; 23 | } 24 | 25 | 26 | public static boolean canPart( int[] nums ) { 27 | int sum = 0; 28 | for ( Integer i : nums ) { 29 | sum += i; 30 | } 31 | return dfs( nums, 0, 0, sum ); 32 | } 33 | 34 | 35 | private static boolean dfs( int[] nums, int index, int sum, int target ) { 36 | //base case 37 | if ( nums.length == index ) { 38 | if ( sum == target ) { 39 | return true; 40 | } else { 41 | return false; 42 | } 43 | } 44 | 45 | //对于任意一个数,可与选或者不选 46 | return dfs( nums, index + 1, sum + nums[index], target ) 47 | || 48 | dfs( nums, index + 1, sum, target ); 49 | } 50 | 51 | 52 | // 备忘录:也可用一个二维数组,一维表示元素和sum,一维表示当前索引index 53 | private Map map = new HashMap<>(); 54 | 55 | 56 | private boolean dfsAndMap( int[] nums, int index, int sum, int target ) { 57 | if ( nums.length == index ) { 58 | if ( sum == target ) { 59 | return true; 60 | } else { 61 | return false; 62 | } 63 | } 64 | 65 | //描述一个子问题的两个变量是 sum 和 index,组成 key 字符串 66 | String key = sum + "&" + index; 67 | if ( map.containsKey( key ) ) { 68 | return map.get( key ); 69 | } 70 | 71 | boolean ret = dfs( nums, index + 1, sum + nums[index], target ) || 72 | dfs( nums, index + 1, sum, target ); 73 | 74 | map.put( key, ret ); 75 | 76 | return ret; 77 | } 78 | 79 | // 作者:winlsr 80 | // 链接:https://leetcode-cn.com/problems/partition-equal-subset-sum/solution/dfs-dfs-bei-wang-lu-01bei-bao-dong-tai-g-4j1t/ 81 | // 来源:力扣(LeetCode) 82 | // 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 83 | 84 | 85 | public static boolean canPartion( int[] nums ) { 86 | int sum = 0; 87 | for ( Integer i : nums ) { 88 | sum += i; 89 | } 90 | if ( sum % 2 == 1 ) { 91 | return false; 92 | } 93 | int target = sum >> 1; 94 | int len = nums.length; 95 | boolean[][] dp = new boolean[target + 1][len + 1]; 96 | for (int i = 0; i < len + 1; i++) { 97 | dp[0][i] = true; 98 | } 99 | for (int i = 1; i < target + 1; i++) { 100 | for (int j = 1; j < len + 1 ; j++) { 101 | // 如果不能装下前j个物品中的最后一个 102 | if (i < nums[j - 1]) { 103 | dp[i][j] = dp[i][j - 1]; 104 | // 能装下,可以选择装或者不装 105 | } else if (i >= nums[j - 1]) { 106 | dp[i][j] = dp[i][j - 1] || dp[i - nums[j - 1]][j - 1]; 107 | } 108 | } 109 | } 110 | 111 | return dp[target][len]; 112 | } 113 | 114 | 115 | public static void main( String[] args ) { 116 | int[] nums = new int[]{ 1, 2, 11, 5 }; 117 | System.out.println( canPart( nums ) ); 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeDynamicProgram/Bag/FindTargetSumWays.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeDynamicProgram.Bag; 2 | 3 | import java.util.LinkedList; 4 | 5 | /** 6 | * @ClassName: FindTargetSumWays 7 | * @Description: 8 | * @author: dk 9 | * @date: 2022/3/2 1:08 下午 10 | */ 11 | 12 | public class FindTargetSumWays { 13 | 14 | /** 15 | * 494. 目标和 16 | * https://leetcode-cn.com/problems/target-sum/ 17 | * 18 | * @param nums 19 | * @param target 20 | * @return 21 | */ 22 | 23 | 24 | int res = 0; 25 | 26 | 27 | public int findTargetSumWaysByDFS( int[] nums, int target ) { 28 | int sum = 0; 29 | for ( Integer i : nums ) { 30 | sum += i; 31 | } 32 | if ( sum < target ) { 33 | return 0; 34 | } 35 | dfs( nums, target, 0, 0 ); 36 | return res; 37 | } 38 | 39 | 40 | public void dfs( int[] nums, int target, int sum, int index ) { 41 | if ( index == nums.length ) { 42 | if ( sum == target ) { 43 | res++; 44 | return; 45 | } 46 | } 47 | if ( index != nums.length ) { 48 | dfs( nums, target, sum - nums[index], index + 1 ); 49 | dfs( nums, target, sum + nums[index], index + 1 ); 50 | } 51 | } 52 | 53 | 54 | public int findTargetSumWays( int[] nums, int target ) { 55 | 56 | int res = 0; 57 | int sum = 0; 58 | for ( int i : nums ) { 59 | sum += i; 60 | } 61 | 62 | if ( Math.abs( target ) > sum || (sum + target) % 2 != 0 ) { 63 | return 0; 64 | } 65 | 66 | int mid = (sum + target) / 2; 67 | int N = nums.length; 68 | int[][] dp = new int[N + 1][mid + 1]; 69 | dp[0][0] = 1; 70 | 71 | for ( int i = 1; i <= N; i++ ) { 72 | for ( int j = 0; j <= mid; j++ ) { 73 | if ( j >= nums[i - 1] ) { 74 | // 两种选择的结果之和 75 | dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i - 1]]; 76 | } else { 77 | // 背包的空间不足,只能选择不装物品 i 78 | dp[i][j] = dp[i - 1][j]; 79 | } 80 | } 81 | } 82 | return dp[N][mid]; 83 | } 84 | 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeDynamicProgram/Bag/LastStoneWeightII.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeDynamicProgram.Bag; 2 | 3 | /** 4 | * @ClassName: LastStoneWeightII 5 | * @Description: 6 | * @author: dk 7 | * @date: 2022/3/2 1:07 下午 8 | */ 9 | 10 | public class LastStoneWeightII { 11 | 12 | /** 13 | * 1049. 最后一块石头的重量 II 14 | * https://leetcode-cn.com/problems/last-stone-weight-ii/ 15 | * @param stones 16 | * @return 17 | */ 18 | public int lastStoneWeightII(int[] stones) { 19 | int sum = 0; 20 | for (int s : stones) { 21 | sum += s; 22 | } 23 | 24 | int target = sum / 2; 25 | //初始化,dp[i][j]为可以放0-i物品,背包容量为j的情况下背包中的最大价值 26 | int[][] dp = new int[stones.length][target + 1]; 27 | //dp[i][0]默认初始化为0 28 | //dp[0][j]取决于stones[0] 29 | for (int j = stones[0]; j <= target; j++) { 30 | dp[0][j] = stones[0]; 31 | } 32 | 33 | for (int i = 1; i < stones.length; i++) { 34 | for (int j = 1; j <= target; j++) {//注意是等于 35 | if (j >= stones[i]) { 36 | //不放:dp[i - 1][j] 放:dp[i - 1][j - stones[i]] + stones[i] 37 | dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - stones[i]] + stones[i]); 38 | } else { 39 | dp[i][j] = dp[i - 1][j]; 40 | } 41 | } 42 | } 43 | 44 | // System.out.println(dp[stones.length - 1][target]); 45 | return (sum - dp[stones.length - 1][target]) - dp[stones.length - 1][target]; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeDynamicProgram/FullBag/Change.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeDynamicProgram.FullBag; 2 | 3 | import java.util.Arrays; 4 | import java.util.LinkedList; 5 | 6 | /** 7 | * @ClassName: Change 8 | * @Description: 9 | * @author: dk 10 | * @date: 2022/3/10 3:41 下午 11 | */ 12 | 13 | public class Change { 14 | 15 | public int change(int amount, int[] coins) { 16 | int []dp = new int[amount+1]; 17 | dp[0]=1; 18 | // 遍历 钱币 19 | for(int i=0;i= 0){ 66 | dp[j] += dp[j - coins[i]]; 67 | 68 | 69 | System.out.println("-----"); 70 | for(int index=0;index< dp.length;index++){ 71 | if(index==j){ 72 | System.out.print("*"+dp[index]+"*"); 73 | } 74 | else{ 75 | System.out.print(" "+dp[index]+" "); 76 | } 77 | } 78 | System.out.println(); 79 | System.out.println("i="+i+" "+"j="+j+" "+"面值 coins[i]="+coins[i]+" 要凑的target为 "+j); 80 | System.out.println("-----"); 81 | 82 | } 83 | 84 | } 85 | } 86 | return dp[amount]; 87 | } 88 | 89 | public static void main(String[] args) { 90 | int []coins = new int[]{1,2,5}; 91 | int amount = 5; 92 | //change1(amount,coins); 93 | // 组合数 回溯打印 94 | //System.out.println(changeBack(amount, coins)); 95 | // 此时dp[j]里算出来的就是排列数 96 | //change2(amount,coins); 97 | // 排列数 回溯打印 98 | //System.out.println(changeBack2(amount, coins)); 99 | } 100 | 101 | private static int res = 0; 102 | public static int changeBack(int amount, int[] coins) { 103 | Arrays.sort(coins); 104 | LinkedList list = new LinkedList<>(); 105 | back(coins,amount,0,list,0); 106 | return res; 107 | } 108 | 109 | public static int changeBack2(int amount, int[] coins) { 110 | Arrays.sort(coins); 111 | LinkedList list = new LinkedList<>(); 112 | back(coins,amount,0,list,0); 113 | return res; 114 | } 115 | 116 | private static void back(int[] nums,int target,int n,LinkedList list,int index){ 117 | if(n>target)return; 118 | if(n==target){ 119 | res++; 120 | System.out.println(list.toString()); 121 | return; 122 | } 123 | for(int i=0;itarget)return; 125 | n+=nums[i]; 126 | list.add(nums[i]); 127 | back(nums,target,n,list,0); 128 | n-=nums[i]; 129 | list.removeLast(); 130 | } 131 | } 132 | 133 | private static void back1(int[] nums,int target,int n,LinkedList list,int index){ 134 | if(n>target)return; 135 | if(n==target){ 136 | res++; 137 | System.out.println(list.toString()); 138 | return; 139 | } 140 | for(int i=index;itarget)return; 142 | n+=nums[i]; 143 | list.add(nums[i]); 144 | back(nums,target,n,list,i); 145 | n-=nums[i]; 146 | list.removeLast(); 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeDynamicProgram/FullBag/CoinChange.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeDynamicProgram.FullBag; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | import java.util.Scanner; 9 | import java.util.Set; 10 | 11 | /** 12 | * @ClassName: CoinChange 13 | * @Description: 14 | * @author: dk 15 | * @date: 2022/2/28 4:04 下午 16 | */ 17 | 18 | public class CoinChange { 19 | 20 | /** 21 | * 322. 零钱兑换 22 | * https://leetcode-cn.com/problems/coin-change/ 23 | * @param coins 24 | * @param amount 25 | * @return 26 | */ 27 | int res = Integer.MAX_VALUE ; 28 | public int coinChange(int[] coins, int amount) { 29 | back(coins,amount,0); 30 | return res == Integer.MAX_VALUE ? -1 :res; 31 | } 32 | public void back(int []coins,int amount,int index){ 33 | if(amount<0){ 34 | return; 35 | } 36 | if(amount==0){ 37 | if(index= 0 && res < min){ 72 | // 加1,是为了加上得到res结果的那个步骤中,兑换的一个硬币 73 | min = res + 1; 74 | } 75 | } 76 | memo[amount-1] = (min == Integer.MAX_VALUE ? -1 : min); 77 | return memo[amount-1]; 78 | } 79 | 80 | 81 | public int coinChangeByDp(int[] coins, int amount) { 82 | if(coins.length == 0){ 83 | return -1; 84 | } 85 | int []memo = new int[amount+1]; 86 | for(int i =1;i<=amount;i++){ 87 | int min = Integer.MAX_VALUE; 88 | for(int j=0;j=0 && memo[i-coins[j]] list = new LinkedList<>(); 105 | 106 | while ( n>0 ){ 107 | list.add( sc.nextInt()); 108 | n--; 109 | } 110 | int res = 0; 111 | int num = 0 ; 112 | System.out.println(list.size()); 113 | 114 | while ( !list.isEmpty()) { 115 | int index = (int) Math.pow( 2, num ); 116 | num++; 117 | int temp = 0; 118 | for ( int i = 0; i < index; i++ ) { 119 | temp = temp + list.get( i ); 120 | list.removeFirst(); 121 | } 122 | if(temp= num) { 24 | res += combinationSum4_1(nums, target - num); 25 | } 26 | } 27 | return res; 28 | } 29 | 30 | /** 31 | * 记忆化搜索 32 | */ 33 | private int[] memo; 34 | 35 | public int combinationSum4_2(int[] nums, int target) { 36 | memo = new int[target + 1]; 37 | Arrays.fill(memo, -1); 38 | memo[0] = 1; 39 | return search(nums, target); 40 | } 41 | 42 | private int search(int[] nums, int target) { 43 | if (memo[target] != -1) { 44 | return memo[target]; 45 | } 46 | int res = 0; 47 | for (int num : nums) { 48 | if (target >= num) { 49 | res += search(nums, target - num); 50 | } 51 | } 52 | memo[target] = res; 53 | return res; 54 | } 55 | 56 | /** 57 | * 动态规划 58 | */ 59 | public int combinationSum4(int[] nums, int target) { 60 | int[] memo = new int[target + 1]; 61 | memo[0] = 1; 62 | for (int i = 0; i < target; i++) { 63 | for (int num : nums) { 64 | if (i + num <= target) { 65 | memo[i + num] += memo[i]; 66 | } 67 | } 68 | } 69 | return memo[target]; 70 | } 71 | 72 | 73 | public int combinationSum4_3(int[] nums, int target) { 74 | 75 | 76 | int []dp= new int[target+1]; 77 | dp[0]=1; 78 | for(int j=0;j<=target;j++){ 79 | for(int i=0;i=0){ 81 | dp[j]+=dp[j-nums[i]]; 82 | } 83 | } 84 | } 85 | 86 | return dp[target]; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeGraph/Modle.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeGraph; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | /** 7 | * @ClassName: Modle 8 | * @Description: 9 | * @author: dk 10 | * @date: 2022/1/19 2:41 下午 11 | */ 12 | 13 | public class Modle { 14 | 15 | // 记录所有路径 16 | List> res = new LinkedList<>(); 17 | 18 | public List> allPathsSourceTarget( int[][] graph ) { 19 | // 维护递归过程中经过的路径 20 | LinkedList path = new LinkedList<>(); 21 | traverseAllGraph( graph, 0, path ); 22 | return res; 23 | } 24 | 25 | /* 图的遍历框架 */ 26 | void traverseAllGraph( int[][] graph, int s, LinkedList path ) { 27 | // 添加节点 s 到路径 28 | path.addLast( s ); 29 | int n = graph.length; 30 | if ( s == n - 1 ) { 31 | // 到达终点 32 | res.add( new LinkedList<>( path ) ); 33 | path.removeLast(); 34 | return; 35 | } 36 | // 递归每个相邻节点 37 | for ( int v : graph[s] ) { 38 | traverseAllGraph( graph, v, path ); 39 | } 40 | // 从路径移出节点 s 41 | path.removeLast(); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeGreedy/EraseOverlapIntervals.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeGreedy; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @ClassName: EraseOverlapIntervals 7 | * @Description: 8 | * @author: dk 9 | * @date: 2022/2/17 9:06 下午 10 | */ 11 | 12 | public class EraseOverlapIntervals { 13 | 14 | /** 15 | * 435. 无重叠区间 16 | * https://leetcode-cn.com/problems/non-overlapping-intervals/ 17 | * 18 | * @param intervals 19 | * @return 20 | */ 21 | public int eraseOverlapIntervals(int[][] intervals) { 22 | if (intervals.length == 0) return 0; 23 | Arrays.sort(intervals, (o1, o2) -> Integer.compare(o1[0], o2[0])); 24 | int res = 1; 25 | for (int i = 1; i < intervals.length; i++) { 26 | // 一个新的独立区间 27 | if (intervals[i][0] >= intervals[i - 1][1]) res++; 28 | else { 29 | //System.out.println("i="+ i +" intervals[i][1]="+intervals[i][1]); 30 | // 更新最右界限 31 | intervals[i][1] = Math.min(intervals[i][1], intervals[i - 1][1]); 32 | } 33 | } 34 | return intervals.length - res; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeGreedy/FindContentChildren.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeGreedy; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @ClassName: FindContentChildren 7 | * @Description: 8 | * @author: dk 9 | * @date: 2022/1/7 8:49 上午 10 | */ 11 | 12 | public class FindContentChildren { 13 | 14 | /** 15 | * https://leetcode-cn.com/problems/assign-cookies/ 16 | * 17 | * @param g 18 | * @param s 19 | * @return 20 | */ 21 | public int findContentChildren(int[] g, int[] s) { 22 | if (s.length == 0) { 23 | return 0; 24 | } 25 | int res = 0; 26 | Arrays.sort(g); 27 | Arrays.sort(s); 28 | int start = -1; 29 | for (int i = 0; i < g.length; i++) { 30 | for (int j = start + 1; j < s.length; j++) { 31 | if (g[i] <= s[j]) { 32 | res++; 33 | start = j; 34 | break; 35 | } 36 | } 37 | } 38 | return res; 39 | } 40 | 41 | 42 | public int findContentChildrenTwo(int[] g, int[] s) { 43 | if (s.length == 0) { 44 | return 0; 45 | } 46 | int res = 0; 47 | Arrays.sort(g); 48 | Arrays.sort(s); 49 | int index = 0; 50 | for (int i = 0; i < s.length; i++) { 51 | if (index < g.length && s[i] >= g[index]) { 52 | res++; 53 | index++; 54 | } 55 | } 56 | return res; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeGreedy/MaxSubArray.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeGreedy; 2 | 3 | /** 4 | * @ClassName: MaxSubArray 5 | * @Description: 6 | * @author: dk 7 | * @date: 2022/1/7 9:30 上午 8 | */ 9 | 10 | public class MaxSubArray { 11 | 12 | /** 13 | * https://leetcode-cn.com/problems/maximum-subarray/ 14 | * 15 | * @param nums 16 | * @return 17 | */ 18 | public int maxSubArray(int[] nums) { 19 | if (nums.length == 1) return nums[0]; 20 | int res = Integer.MIN_VALUE; 21 | int count = 0; 22 | for (int i = 0; i < nums.length; i++) { 23 | count = count + nums[i]; 24 | if (count > res) { 25 | res = count; 26 | } 27 | if (count <= 0) { 28 | count = 0; 29 | } 30 | } 31 | return res; 32 | } 33 | 34 | public int maxSubArrayTwo(int[] nums) { 35 | int res = nums[0]; 36 | int sum = 0; 37 | for (int i = 0; i < nums.length; i++) { 38 | if (sum < 0) { 39 | sum = nums[i]; 40 | } else { 41 | sum = sum + nums[i]; 42 | } 43 | res = Math.max(res, sum); 44 | } 45 | return res; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeGreedy/WiggleMaxLength.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeGreedy; 2 | 3 | /** 4 | * @ClassName: WiggleMaxLength 5 | * @Description: 6 | * @author: dk 7 | * @date: 2022/1/7 9:09 上午 8 | */ 9 | 10 | public class WiggleMaxLength { 11 | 12 | /** 13 | * https://leetcode-cn.com/problems/wiggle-subsequence/ 14 | * 15 | * @param nums 16 | * @return 17 | */ 18 | public int wiggleMaxLength( int[] nums ) { 19 | int res = 0; 20 | int curDiff = 0; // 当前一对差值 21 | int preDiff = 0; // 前一对差值 22 | int result = 1; // 记录峰值个数,序列默认序列最右边有一个峰值 23 | for ( int i = 0; i < nums.length - 1; i++ ) { 24 | curDiff = nums[i + 1] - nums[i]; 25 | // 出现峰值 26 | if ( (curDiff > 0 && preDiff <= 0) || (preDiff >= 0 && curDiff < 0) ) { 27 | result++; 28 | preDiff = curDiff; 29 | } 30 | } 31 | return result; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeHashMap/FourSum.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeHashMap; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * @ClassName: FourSum 9 | * @Description: 10 | * @author: dk 11 | * @date: 2021/12/26 10:21 上午 12 | */ 13 | 14 | public class FourSum { 15 | 16 | public List> fourSum( int[] nums, int target ) { 17 | List> result = new ArrayList<>(); 18 | Arrays.sort( nums ); 19 | 20 | for ( int i = 0; i < nums.length; i++ ) { 21 | 22 | if ( i > 0 && nums[i - 1] == nums[i] ) { 23 | continue; 24 | } 25 | 26 | for ( int j = i + 1; j < nums.length; j++ ) { 27 | 28 | if ( j > i + 1 && nums[j - 1] == nums[j] ) { 29 | continue; 30 | } 31 | 32 | int left = j + 1; 33 | int right = nums.length - 1; 34 | while ( right > left ) { 35 | int sum = nums[i] + nums[j] + nums[left] + nums[right]; 36 | if ( sum > target ) { 37 | right--; 38 | } else if ( sum < target ) { 39 | left++; 40 | } else { 41 | result.add( Arrays.asList( nums[i], nums[j], nums[left], nums[right] ) ); 42 | 43 | while ( right > left && nums[right] == nums[right - 1] ) { 44 | right--; 45 | } 46 | while ( right > left && nums[left] == nums[left + 1] ) { 47 | left++; 48 | } 49 | 50 | left++; 51 | right--; 52 | } 53 | } 54 | } 55 | } 56 | return result; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeHashMap/FourSumCount.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeHashMap; 2 | 3 | import java.util.HashMap; 4 | 5 | /** 6 | * @ClassName: FourSumCount 7 | * @Description: 8 | * @author: dk 9 | * @date: 2021/12/26 10:22 上午 10 | */ 11 | 12 | public class FourSumCount { 13 | 14 | /** 15 | * [454. 四数相加 II](https://leetcode-cn.com/problems/4sum-ii/) 16 | * 17 | * @param nums1 18 | * @param nums2 19 | * @param nums3 20 | * @param nums4 21 | * @return 22 | */ 23 | public int fourSumCount( int[] nums1, int[] nums2, int[] nums3, int[] nums4 ) { 24 | HashMap map = new HashMap<>(); 25 | for ( int i = 0; i < nums1.length; i++ ) { 26 | for ( int j = 0; j < nums2.length; j++ ) { 27 | map.put( 0 - (nums1[i] + nums2[j]), map.getOrDefault( 0 - (nums1[i] + nums2[j]), 0 ) + 1 ); 28 | } 29 | } 30 | int count = 0; 31 | for ( int i = 0; i < nums3.length; i++ ) { 32 | for ( int j = 0; j < nums4.length; j++ ) { 33 | int temp = nums3[i] + nums4[j]; 34 | if ( map.containsKey( temp ) ) { 35 | count = count + map.get( temp ); 36 | } 37 | } 38 | } 39 | return count; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeHashMap/IsHappy.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeHashMap; 2 | 3 | import java.util.HashSet; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | /** 8 | * @ClassName: IsHappy 9 | * @Description: 10 | * @author: dk 11 | * @date: 2021/12/26 7:58 上午 12 | */ 13 | 14 | public class IsHappy { 15 | 16 | public boolean isHappy( int n ) { 17 | if ( n == 1 ) { 18 | return true; 19 | } 20 | if ( n < 10 && n != 7 ) { 21 | return false; 22 | } else { 23 | int temp = 0; 24 | while ( n != 0 ) { 25 | temp = temp + (n % 10) * (n % 10); 26 | n = n / 10; 27 | } 28 | //System.out.println( temp ); 29 | return isHappy( temp ); 30 | } 31 | } 32 | 33 | 34 | /** 35 | * good way 36 | * 37 | * @param n 38 | * @return 39 | */ 40 | public boolean isHappyTwo( int n ) { 41 | Set record = new HashSet<>(); 42 | while ( n != 1 && !record.contains( n ) ) { 43 | record.add( n ); 44 | n = getNextNumber( n ); 45 | } 46 | return n == 1; 47 | } 48 | 49 | 50 | private int getNextNumber( int n ) { 51 | int res = 0; 52 | while ( n > 0 ) { 53 | int temp = n % 10; 54 | res += temp * temp; 55 | n = n / 10; 56 | } 57 | return res; 58 | } 59 | 60 | 61 | public static void main( String[] args ) { 62 | 63 | // System.out.println( isHappy( 19000 ) ); 64 | // int n = 10; 65 | // for ( int i = 1; i < Math.sqrt( n ); i++ ) { 66 | // for ( int j = 1; j < Math.sqrt( n ); j++ ) { 67 | // for ( int k = 1; k < Math.sqrt( n ); k++ ) { 68 | // if ( (i * i + j * j + k * k) == n ) { 69 | // System.out.println( i + " " + j + " " + k ); 70 | // } 71 | // } 72 | // } 73 | // } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeHashMap/ThreeSum.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeHashMap; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * @ClassName: ThreeSum 9 | * @Description: 10 | * @author: dk 11 | * @date: 2021/12/26 8:48 上午 12 | */ 13 | 14 | public class ThreeSum { 15 | 16 | public List> res = new ArrayList<>(); 17 | 18 | 19 | /** 20 | * @param nums 21 | * @return 22 | */ 23 | 24 | public List> threeSum( int[] nums ) { 25 | List> res = new ArrayList<>(); 26 | Arrays.sort( nums ); 27 | System.out.println(); 28 | for ( int i = 0; i < nums.length; i++ ) { 29 | if ( nums[i] > 0 ) { 30 | return res; 31 | } 32 | // 错误去重方法,将会漏掉-1,-1,2 这种情况 33 | /* 34 | if (nums[i] == nums[i + 1]) { 35 | continue; 36 | } 37 | */ 38 | // 正确去重方法 39 | if ( i > 0 && nums[i] == nums[i - 1] ) { 40 | continue; 41 | } 42 | int left = i + 1; 43 | int right = nums.length - 1; 44 | while ( right > left ) { 45 | int sum = nums[i] + nums[left] + nums[right]; 46 | // 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right<=left 了, 47 | // 从而漏掉了 0,0,0 这种三元组 48 | /* 49 | while (right > left && nums[right] == nums[right - 1]) right--; 50 | while (right > left && nums[left] == nums[left + 1]) left++; 51 | */ 52 | if ( sum > 0 ) { 53 | right--; 54 | } else if ( sum < 0 ) { 55 | left++; 56 | } else if ( sum == 0 ) { 57 | res.add( Arrays.asList( nums[i], nums[left], nums[right] ) ); 58 | // 去重逻辑应该放在找到一个三元组之后 59 | while ( right > left && nums[right] == nums[right - 1] ) { 60 | right--; 61 | } 62 | while ( right > left && nums[left] == nums[left + 1] ) { 63 | left++; 64 | } 65 | right--; 66 | left++; 67 | } 68 | } 69 | 70 | } 71 | return res; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeHashMap/ThreeSumClosest.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeHashMap; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashMap; 5 | 6 | /** 7 | * @ClassName: ThreeSumClosest 8 | * @Description: 9 | * @author: dk 10 | * @date: 2021/12/27 10:28 上午 11 | */ 12 | 13 | public class ThreeSumClosest { 14 | 15 | /** 16 | * [16. 最接近的三数之和](https://leetcode-cn.com/problems/3sum-closest/) 17 | * 18 | * @param nums 19 | * @param target 20 | * @return 21 | */ 22 | public int threeSumClosest( int[] nums, int target ) { 23 | Arrays.sort( nums ); 24 | int ans = nums[0] + nums[1] + nums[2]; 25 | for ( int i = 0; i < nums.length; i++ ) { 26 | if ( i > 0 && nums[i] == nums[i - 1] ) { 27 | continue; 28 | } 29 | int l = i + 1; 30 | int r = nums.length - 1; 31 | while ( l < r ) { 32 | int temp = nums[i] + nums[l] + nums[r]; 33 | if ( Math.abs( temp - target ) < Math.abs( ans - target ) ) { 34 | ans = temp; 35 | } 36 | if ( temp > target ) { 37 | r--; 38 | } else if ( temp < target ) { 39 | l++; 40 | } else if ( temp == target ) { 41 | // System.out.println("i: " + i + " l: " + l + "r : "+ r ); 42 | return temp; 43 | } 44 | } 45 | } 46 | 47 | return ans; 48 | } 49 | 50 | 51 | public int threeSumClosestTwo( int[] nums, int target ) { 52 | 53 | Arrays.sort( nums ); 54 | 55 | HashMap map = new HashMap<>(); 56 | for ( int i = 0; i < nums.length; i++ ) { 57 | if ( i > 0 && nums[i] == nums[i - 1] ) { 58 | continue; 59 | } 60 | 61 | int l = i + 1; 62 | int r = nums.length - 1; 63 | while ( l < r ) { 64 | int temp = nums[i] + nums[l] + nums[r]; 65 | map.put( temp - target, temp ); 66 | if ( temp > target ) { 67 | r--; 68 | } else if ( temp < target ) { 69 | l++; 70 | } else if ( temp == target ) { 71 | // System.out.println("i: " + i + " l: " + l + "r : "+ r ); 72 | return temp; 73 | } 74 | } 75 | } 76 | 77 | int index = Integer.MAX_VALUE; 78 | for ( Integer i : map.keySet() 79 | ) { 80 | int a = Math.abs( i ); 81 | int b = Math.abs( index ); 82 | if ( b > a ) { 83 | index = i; 84 | } 85 | // System.out.println("key: " + i + " value: " + map.get(i)); 86 | } 87 | System.out.println( "key: " + index ); 88 | return map.get( index ); 89 | } 90 | 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeListNode/DetectCycle.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeListNode; 2 | 3 | /** 4 | * @ClassName: DetectCycle 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/24 9:14 上午 8 | */ 9 | 10 | public class DetectCycle { 11 | 12 | /** 13 | * [142. 环形链表 II](https://leetcode-cn.com/problems/linked-list-cycle-ii/) 14 | * 15 | * @param head 16 | * @return 17 | */ 18 | public ListNode detectCycle( ListNode head ) { 19 | if ( head == null || head.next == null ) { 20 | return null; 21 | } 22 | ListNode slow = head; 23 | ListNode fast = head; 24 | ListNode node = null; 25 | 26 | while ( fast.next != null && fast.next.next != null ) { 27 | slow = slow.next; 28 | fast = fast.next.next; 29 | if ( slow == fast ) { 30 | node = slow; 31 | break; 32 | } 33 | } 34 | if ( node != null ) { 35 | ListNode temp = head; 36 | while ( temp != node ) { 37 | temp = temp.next; 38 | node = node.next; 39 | } 40 | return temp; 41 | } 42 | return null; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeListNode/GetIntersectionNode.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeListNode; 2 | 3 | /** 4 | * @ClassName: GetIntersectionNode 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/24 8:36 上午 8 | */ 9 | 10 | public class GetIntersectionNode { 11 | 12 | /** 13 | * [面试题 02.07. 链表相交](https://leetcode-cn.com/problems/intersection-of-two-linked-lists-lcci/) 14 | * 15 | * @param headA 16 | * @param headB 17 | * @return 18 | */ 19 | public ListNode getIntersectionNodeTwo( ListNode headA, ListNode headB ) { 20 | ListNode la = headA; 21 | ListNode lb = headB; 22 | while ( la != lb ) { 23 | //到达链表末尾时,重新走另一条链表的路 24 | la = la == null ? headB : la.next; 25 | lb = lb == null ? headA : lb.next; 26 | } 27 | return la; 28 | } 29 | 30 | 31 | public ListNode getIntersectionNode( ListNode headA, ListNode headB ) { 32 | if ( headA == null || headB == null ) { 33 | return null; 34 | } 35 | ListNode nodeA = headA; 36 | ListNode nodeB = headB; 37 | int a = 0; 38 | int b = 0; 39 | while ( nodeA != null ) { 40 | nodeA = nodeA.next; 41 | a++; 42 | } 43 | while ( nodeB != null ) { 44 | nodeB = nodeB.next; 45 | b++; 46 | } 47 | if ( a == b ) { 48 | return null; 49 | } else if ( a > b ) { 50 | int time = a - b; 51 | while ( time > 0 ) { 52 | headA = headA.next; 53 | time--; 54 | } 55 | } else if ( a < b ) { 56 | int time = a - b; 57 | while ( time > 0 ) { 58 | headB = headB.next; 59 | time--; 60 | } 61 | } 62 | while ( headA != null && headB != null ) { 63 | if ( headA == headB ) { 64 | return headA; 65 | } 66 | headA = headA.next; 67 | headB = headB.next; 68 | } 69 | return null; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeListNode/HasCycle.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeListNode; 2 | 3 | /** 4 | * @ClassName: HasCycle 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/24 9:08 上午 8 | */ 9 | 10 | public class HasCycle { 11 | 12 | /** 13 | * [141. 环形链表](https://leetcode-cn.com/problems/linked-list-cycle/) 14 | * 15 | * @param head 16 | * @return 17 | */ 18 | public boolean hasCycle( ListNode head ) { 19 | if ( head == null || head.next == null ) { 20 | return false; 21 | } 22 | ListNode slow = head; 23 | ListNode fast = head; 24 | 25 | while ( fast.next != null && fast.next.next != null ) { 26 | slow = slow.next; 27 | fast = fast.next.next; 28 | if ( slow == fast ) { 29 | return true; 30 | } 31 | } 32 | return false; 33 | } 34 | 35 | 36 | public static boolean hasCycleTestByTwo( ListNode head ) { 37 | if ( head == null || head.next == null ) { 38 | return false; 39 | } 40 | ListNode slow = head; 41 | ListNode fast = head; 42 | int slowNum = 0; 43 | int fastNum = 0; 44 | 45 | while ( fast.next != null && fast.next.next != null ) { 46 | System.out.println( "未相遇:slow.val=" + slow.val + " fast.val=" + fast.val ); 47 | 48 | slow = slow.next; 49 | slowNum++; 50 | fast = fast.next.next; 51 | fastNum += 2; 52 | if ( slow == fast ) { 53 | System.out.println( "slow.val=" + slow.val + " fast.val=" + fast.val ); 54 | System.out.println( slowNum + " " + fastNum ); 55 | return true; 56 | } 57 | } 58 | return false; 59 | } 60 | 61 | 62 | public static boolean hasCycleTestByThree( ListNode head ) { 63 | if ( head == null || head.next == null ) { 64 | return false; 65 | } 66 | ListNode slow = head; 67 | ListNode fast = head; 68 | 69 | int slowNum = 0; 70 | int fastNum = 0; 71 | while ( fast.next != null && fast.next.next != null && fast.next.next.next != null ) { 72 | 73 | System.out.println( "未相遇:slow.val=" + slow.val + " fast.val=" + fast.val ); 74 | 75 | slow = slow.next; 76 | slowNum++; 77 | 78 | fast = fast.next.next.next; 79 | fastNum += 3; 80 | 81 | if ( slow == fast ) { 82 | System.out.println( "slow.val=" + slow.val + " fast.val=" + fast.val ); 83 | System.out.println( slowNum + " " + fastNum ); 84 | return true; 85 | } 86 | } 87 | return false; 88 | } 89 | 90 | 91 | public static void main( String[] args ) { 92 | ListNode node1 = new ListNode( 1 ); 93 | ListNode node2 = new ListNode( 2 ); 94 | ListNode node3 = new ListNode( 3 ); 95 | ListNode node4 = new ListNode( 4 ); 96 | ListNode node5 = new ListNode( 5 ); 97 | ListNode node6 = new ListNode( 6 ); 98 | ListNode node7 = new ListNode( 7 ); 99 | ListNode node8 = new ListNode( 8 ); 100 | node1.next = node2; 101 | node2.next = node3; 102 | node3.next = node4; 103 | node4.next = node5; 104 | node5.next = node6; 105 | node6.next = node7; 106 | node7.next = node8; 107 | node8.next = node6; 108 | System.out.println( "此时环入口为 " + node6.val + "号节点" ); 109 | System.out.println( hasCycleTestByTwo( node1 ) ); 110 | System.out.println( "此时环入口为 " + node6.val + "号节点" ); 111 | System.out.println( hasCycleTestByThree( node1 ) ); 112 | } 113 | 114 | /** 115 | 1.判断是否有环用快慢指针,只要相遇即为环,不用说,好理解。 116 | 2.求环入口,就是一个数学问题转换为代码的问题。 117 | ------------------- 118 | | ^ 119 | v | 120 | 0->1->2->3-> …… -> A ->....... -> B 121 | 假设A为环入口,B为相遇点,设0到A距离为x,A到B距离为y,环的长度为c,快慢指针相遇是慢指针绕环n圈,快指针绕环m圈, 122 | 由条件得快慢指针相遇时快指针走的长度是慢指针的2倍,则: 123 | 2(x+nc+y)=x+mc+y; 124 | 化简得x+y=(m-2n)c; 125 | x= (m-2n)c- y 126 | 设相遇点到环入口距离为 z = c -y y= c -z 127 | x = (m-2n)c - (c-z) 128 | x = (m-2n-1)c + z 129 | 130 | 这意味着从起点0相遇点B的长度为环长度的正整数倍; 131 | 换句话说,就是现在让两个指针速度都变成1(重点!!!),第一个指针从起点0出发,第二个指针从相遇点B出发, 132 | 则两个指针最后一定会在B点相遇; 133 | 但这是两个指针第一次相遇吗? 134 | 不,因为两个指针速度是相同的,所以往前退一退,就会发现两个指针其实是在环的入口第一次相遇后,就一直重合了; 135 | 所以代码就转换成两个速度为1的指针,一个从起点出发,一个从B点出发,第一次相遇的节点即为入环点。 136 | 伪代码如下: 137 | ListNode q = head; 138 | while (p != q) { 139 | p = p.next; 140 | q = q.next; 141 | } 142 | return q;` 143 | **/ 144 | 145 | //TODO 146 | // 其他解题思路 147 | // https://leetcode-cn.com/problems/linked-list-cycle/solution/3chong-jie-jue-fang-shi-liang-chong-ji-bai-liao-10/ 148 | } 149 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeListNode/IsPalindrome.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeListNode; 2 | 3 | /** 4 | * @ClassName: IsPalindrome 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/24 11:48 上午 8 | */ 9 | 10 | public class IsPalindrome { 11 | 12 | /** 13 | * [234. 回文链表](https://leetcode-cn.com/problems/palindrome-linked-list/) 14 | * 15 | * @param head 16 | * @return 17 | */ 18 | public boolean isPalindrome( ListNode head ) { 19 | if ( head.next == null ) { 20 | return true; 21 | } 22 | ListNode slow = head; 23 | ListNode fast = head; 24 | while ( fast.next != null && fast.next.next != null ) { 25 | slow = slow.next; 26 | fast = fast.next.next; 27 | } 28 | ListNode reverseStart = slow; 29 | ListNode node = head; 30 | // 如果是奇数个节点,此时fast在最后一个节点 31 | // 可以用fast的下一个节点是否为空来判断整个链表节点个数是技术还是偶数 32 | if ( fast.next == null ) { 33 | // 需要将slow 指向下一个节点 再进行翻转 34 | slow = slow.next; 35 | ListNode temp = reverseList( slow ); 36 | while ( temp != null ) { 37 | if ( temp.val != node.val ) { 38 | // System.out.println(temp.val +"-"+ node.val); 39 | return false; 40 | } 41 | temp = temp.next; 42 | node = node.next; 43 | } 44 | reverseStart.next = reverseList( slow ); 45 | } else { 46 | // 若节点个数为偶数,则slow 在上中点 47 | // 需要返回以下中点为首的 翻转后的链表 48 | //返回 slow.next后半部分链表 49 | ListNode temp = reverseList( slow.next ); 50 | while ( temp != null ) { 51 | if ( temp.val != node.val ) { 52 | return false; 53 | } 54 | temp = temp.next; 55 | node = node.next; 56 | } 57 | reverseStart.next = reverseList( slow ); 58 | } 59 | 60 | return true; 61 | } 62 | 63 | 64 | public ListNode reverseList( ListNode head ) { 65 | if ( head == null ) { 66 | return head; 67 | } 68 | ListNode pre = null; 69 | ListNode cur = head; 70 | while ( cur != null ) { 71 | ListNode temp = cur.next; 72 | cur.next = pre; 73 | pre = cur; 74 | cur = temp; 75 | } 76 | return pre; 77 | } 78 | 79 | 80 | /** 81 | * 优秀的解法 82 | * https://labuladong.gitee.io/algo/2/17/19/ 83 | * 84 | * @param head 85 | * @return 86 | */ 87 | boolean isPalindromeByLa( ListNode head ) { 88 | ListNode slow, fast; 89 | slow = fast = head; 90 | while ( fast != null && fast.next != null ) { 91 | slow = slow.next; 92 | fast = fast.next.next; 93 | } 94 | 95 | if ( fast != null ) { 96 | slow = slow.next; 97 | } 98 | 99 | ListNode left = head; 100 | ListNode right = reverseList( slow ); 101 | while ( right != null ) { 102 | if ( left.val != right.val ) { 103 | return false; 104 | } 105 | left = left.next; 106 | right = right.next; 107 | } 108 | return true; 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeListNode/ListNode.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeListNode; 2 | 3 | /** 4 | * @ClassName: ListNode 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/21 3:57 下午 8 | */ 9 | 10 | public class ListNode { 11 | 12 | int val; 13 | ListNode next; 14 | 15 | 16 | ListNode() { 17 | } 18 | 19 | 20 | ListNode( int val ) { 21 | this.val = val; 22 | } 23 | 24 | 25 | ListNode( int val, ListNode next ) { 26 | this.val = val; 27 | this.next = next; 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeListNode/MyLinkedList.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeListNode; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @ClassName: MyLinkedList 7 | * @Description: 8 | * @author: dk 9 | * @date: 2021/12/21 4:36 下午 10 | */ 11 | 12 | public class MyLinkedList { 13 | 14 | 15 | static class ListNode { 16 | 17 | int val; 18 | ListNode next; 19 | 20 | 21 | ListNode() { 22 | } 23 | 24 | 25 | ListNode( int val ) { 26 | this.val = val; 27 | } 28 | 29 | } 30 | 31 | 32 | int size; 33 | public ListNode list; 34 | 35 | 36 | public MyLinkedList() { 37 | size = 0; 38 | list = new ListNode(); 39 | } 40 | 41 | 42 | public int get( int index ) { 43 | if ( list == null ) { 44 | return -1; 45 | } 46 | if ( index < 0 || index >= size ) { 47 | return -1; 48 | } 49 | ListNode currentNode = list; 50 | //包含一个虚拟头节点,所以查找第 index+1 个节点 51 | for ( int i = 0; i <= index; i++ ) { 52 | currentNode = currentNode.next; 53 | } 54 | return currentNode.val; 55 | 56 | } 57 | 58 | 59 | public void addAtHead( int val ) { 60 | addAtIndex( 0, val ); 61 | } 62 | 63 | 64 | public void addAtTail( int val ) { 65 | addAtIndex( size, val ); 66 | } 67 | 68 | 69 | public void addAtIndex( int index, int val ) { 70 | if ( index > size ) { 71 | return; 72 | } 73 | if ( index < 0 ) { 74 | index = 0; 75 | } 76 | size++; 77 | //找到要插入节点的前驱 78 | ListNode pred = list; 79 | for ( int i = 0; i < index; i++ ) { 80 | pred = pred.next; 81 | } 82 | ListNode toAdd = new ListNode( val ); 83 | toAdd.next = pred.next; 84 | pred.next = toAdd; 85 | } 86 | 87 | 88 | public void deleteAtIndex( int index ) { 89 | if ( index < 0 || index >= size ) { 90 | return; 91 | } 92 | size--; 93 | ListNode pred = list; 94 | for ( int i = 0; i < index; i++ ) { 95 | pred = pred.next; 96 | } 97 | pred.next = pred.next.next; 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeListNode/RemoveElements.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeListNode; 2 | 3 | /** 4 | * @ClassName: RemoveElements 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/21 3:58 下午 8 | */ 9 | 10 | public class RemoveElements { 11 | 12 | /** 13 | * [203. 移除链表元素](https://leetcode-cn.com/problems/remove-linked-list-elements/) 14 | * 15 | * @param head 16 | * @param val 17 | * @return 18 | */ 19 | public ListNode removeElements( ListNode head, int val ) { 20 | if ( head == null ) { 21 | return head; 22 | } 23 | ListNode node = new ListNode(); 24 | node.next = head; 25 | ListNode pre = node; 26 | ListNode cur = head; 27 | while ( cur != null ) { 28 | if ( cur.val == val ) { 29 | pre.next = cur.next; 30 | } else { 31 | pre = cur; 32 | } 33 | cur = cur.next; 34 | } 35 | return node.next; 36 | } 37 | 38 | } 39 | 40 | /** 41 | * ()中数字代表第几次出现,对应字母为当前指针指向这个节点 42 | * 43 | * (node-pre)-7(1-cur)-7(2)-8(1)-7(4)--9(1) 44 | * 45 | * (node-pre)-7(1-cur)-7(2)-8(1)-7(4)--9(1) 46 | * 47 | * cur.val==val 48 | * 49 | * (node-pre)--------7(2)-8(1)-7(4)--9(1) 50 | * 7(1-cur) 51 | * cur=cur.next; 52 | * 53 | * (node-pre)---7(2-cur)-8(1)-7(4)--9(1) 54 | * 55 | * cur.val==val 56 | * 57 | * (node-pre)----8(1)-7(4)--9(1) 58 | * 7(2-cur) 59 | * cur=cur.next; 60 | * 61 | * (node-pre)----8(1-cur)-7(4)--9(1) 62 | * cur.val!=val 63 | * pre = cur; 64 | * cur=cur.next; 65 | * 66 | * (node-pre)----8(1--pre)-7(4-cur)--9(1) 67 | * cur.val==val 68 | * 69 | * (node-pre)----8(1--pre)---------9(1) 70 | * 7(4-cur) 71 | * cur=cur.next; 72 | * 73 | * (node-pre)----8(1--pre)---------9(1-cur) 74 | * cur=cur.next; 75 | * 76 | * (node-pre)----8(1--pre)---------9(1-)-null(cur) 77 | * 退出循环 78 | * 79 | * node-8-9 80 | * return node.next; 81 | */ -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeListNode/ReverseBetween.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeListNode; 2 | 3 | /** 4 | * @ClassName: ReverseBetween 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/23 2:09 下午 8 | */ 9 | 10 | public class ReverseBetween { 11 | 12 | public ListNode reverseList( ListNode head ) { 13 | if ( head == null ) { 14 | return head; 15 | } 16 | ListNode pre = null; 17 | ListNode cur = head; 18 | while ( cur != null ) { 19 | ListNode temp = cur.next; 20 | cur.next = pre; 21 | pre = cur; 22 | cur = temp; 23 | } 24 | return pre; 25 | } 26 | 27 | 28 | public ListNode reverseBetween( ListNode head, int left, int right ) { 29 | if ( head == null || (left == right) ) { 30 | return head; 31 | } 32 | 33 | ListNode node = head; 34 | int size = 0; 35 | while ( node != null ) { 36 | size++; 37 | node = node.next; 38 | } 39 | 40 | if ( right == size ) { 41 | if ( left == 1 ) { 42 | return reverseList( head ); 43 | } 44 | ListNode start = head; 45 | int num = 1; 46 | while ( num < left - 1 ) { 47 | start = start.next; 48 | num++; 49 | } 50 | start.next = reverseList( start.next ); 51 | } else { 52 | int n = right - left + 1; 53 | ListNode start = head; 54 | ListNode end = head; 55 | int num = 1; 56 | while ( num < left - 1 ) { 57 | start = start.next; 58 | num++; 59 | } 60 | 61 | num = 1; 62 | while ( num < right + 1 ) { 63 | end = end.next; 64 | num++; 65 | } 66 | ListNode pre = null; 67 | ListNode cur = null; 68 | 69 | if ( left == 1 ) { 70 | cur = head; 71 | } else { 72 | cur = start.next; 73 | } 74 | 75 | while ( cur != null && n > 0 ) { 76 | ListNode temp = cur.next; 77 | cur.next = pre; 78 | pre = cur; 79 | cur = temp; 80 | n--; 81 | } 82 | 83 | if ( left == 1 ) { 84 | head.next = end; 85 | return pre; 86 | } else { 87 | //System.out.println(pre.val); 88 | ListNode temp = start.next; 89 | //System.out.println(temp.val); 90 | start.next = pre; 91 | temp.next = end; 92 | ; 93 | } 94 | } 95 | return head; 96 | } 97 | 98 | 99 | } 100 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeListNode/ReverseKGroup.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeListNode; 2 | 3 | /** 4 | * @ClassName: ReverseKGroup 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/23 3:04 下午 8 | */ 9 | 10 | public class ReverseKGroup { 11 | 12 | /** 13 | * [25. K 个一组翻转链表](https://leetcode-cn.com/problems/reverse-nodes-in-k-group/) 14 | * 15 | * @param head 16 | * @param k 17 | * @return 18 | */ 19 | ListNode reverseKGroup( ListNode head, int k ) { 20 | if ( head == null ) { 21 | return null; 22 | } 23 | // 区间 [a, b) 包含 k 个待反转元素 24 | ListNode a, b; 25 | a = b = head; 26 | for ( int i = 0; i < k; i++ ) { 27 | // 不足 k 个,不需要反转,base case 28 | if ( b == null ) { 29 | return head; 30 | } 31 | b = b.next; 32 | } 33 | // 反转前 k 个元素 34 | ListNode newHead = reverse( a, b ); 35 | // 递归反转后续链表并连接起来 36 | a.next = reverseKGroup( b, k ); 37 | return newHead; 38 | } 39 | 40 | 41 | ListNode reverse( ListNode a, ListNode b ) { 42 | ListNode pre, cur, nxt; 43 | pre = null; 44 | cur = a; 45 | nxt = a; 46 | // while 终止的条件改一下就行了 47 | while ( cur != b ) { 48 | nxt = cur.next; 49 | cur.next = pre; 50 | pre = cur; 51 | cur = nxt; 52 | } 53 | // 返回反转后的头结点 54 | return pre; 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeListNode/ReverseList.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeListNode; 2 | 3 | /** 4 | * @ClassName: ReverseList 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/23 1:54 下午 8 | */ 9 | 10 | public class ReverseList { 11 | 12 | /** 13 | * [206. 反转链表](https://leetcode-cn.com/problems/reverse-linked-list/) 14 | * 15 | * @param head 16 | * @return 17 | */ 18 | public static ListNode reverseList(ListNode head) { 19 | if ( head == null ) { 20 | return head; 21 | } 22 | ListNode pre = null; 23 | ListNode cur = head; 24 | while ( cur != null ) { 25 | ListNode temp = cur.next; 26 | cur.next = pre; 27 | pre = cur; 28 | cur = temp; 29 | } 30 | return pre; 31 | } 32 | public static void main(String[] args) { 33 | ListNode head = new ListNode(1); 34 | ListNode head1 = new ListNode(2); 35 | ListNode head2 = new ListNode(3); 36 | ListNode head3 = new ListNode(4); 37 | ListNode head4 = new ListNode(5); 38 | head.next=head1; 39 | head1.next=head2; 40 | head2.next=head3; 41 | head3.next=head4; 42 | ListNode node = reverseList(head); 43 | while (node!=null){ 44 | System.out.println(node.val+"--"); 45 | node=node.next; 46 | } 47 | } 48 | 49 | } 50 | 51 | /* 52 | 1-2-3-4-5 53 | 54 | 55 | pre-1(head-cur)-2-3 56 | 57 | 58 | temp=cur.next 59 | pre->1(head-cur)->2(temp)->3 60 | 61 | cur.next = pre; 62 | pre<-1(head-cur) 2(temp)->3 63 | 64 | pre = cur; 65 | pre<-1(head-cur) 2(temp)->3 66 | 67 | null<-1(head-cur-pre) 2(temp)->3 68 | 69 | cur = temp 70 | null<-1(head-pre) 2(cur)->3 71 | 72 | temp=cur.next 73 | null<-1(head-pre) 2(cur)->3(temp) 74 | 75 | cur.next = pre 76 | null<-1(head-pre)<-2(cur) 3(temp) 77 | 78 | pre = cur 79 | null<-1(head)<-2(pre-cur) 3(temp) 80 | 81 | cur =temp 82 | null<-1(head)<-2(pre) 3(cur)->null 83 | 84 | temp=cur.next 85 | null<-1(head-cur)<-2(pre) 3(cur)->null(temp) 86 | 87 | cur.next = pre 88 | null<-1(head)<-2(pre)<-3(cur) null(temp) 89 | 90 | pre = cur 91 | null<-1(head)<-2()<-3(pre-cur) null(temp) 92 | 93 | cur = temp 94 | null<-1(head)<-2()<-3(pre) null(cur) 95 | 96 | cur ==null 跳出循环 97 | 98 | null<-1(head)<-2()<-3(pre) 99 | 100 | 101 | return pre 102 | 103 | */ -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeListNode/SwapPairs.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeListNode; 2 | 3 | /** 4 | * @ClassName: SwapPairs 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/22 3:03 下午 8 | */ 9 | 10 | public class SwapPairs { 11 | 12 | public ListNode swapPairs( ListNode head ) { 13 | 14 | ListNode pre = new ListNode(); 15 | pre.next = head; 16 | ListNode temp = pre; 17 | 18 | while ( temp.next != null && temp.next.next != null ) { 19 | ListNode start = temp.next; 20 | ListNode end = temp.next.next; 21 | temp.next = end; 22 | start.next = end.next; 23 | end.next = start; 24 | temp = start; 25 | } 26 | return pre.next; 27 | } 28 | 29 | } 30 | /* 31 | 1 2 3 4 32 | 33 | (pre-temp)-1(head)-2-3-4 34 | 35 | (pre-temp)-1(head-start)-2(end)-3-4 36 | 37 | temp.next = end 38 | (pre-temp)-2(end)--3-4 39 | 1(head-start)- 40 | 41 | start.next=end.next; 42 | (pre-temp)-2(end)--3-4 43 | 1(head-start)--3-4 44 | 45 | end.next=start; 46 | (pre-temp)-2(end)-1(head-start)--3-4 47 | 48 | temp=start; 49 | (pre-)-2(end)-1(head-pre)--3-4 50 | 51 | 52 | */ 53 | 54 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeQueue/TopKFrequent.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeQueue; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * @ClassName: TopKFrequent 7 | * @Description: 8 | * @author: dk 9 | * @date: 2022/8/27 17:07 10 | */ 11 | 12 | public class TopKFrequent { 13 | 14 | /** 15 | * [347. 前 K 个高频元素](https://leetcode.cn/problems/top-k-frequent-elements/) 16 | * @param nums 17 | * @param k 18 | * @return 19 | */ 20 | public int[] topKFrequent(int[] nums, int k) { 21 | int[] result = new int[k]; 22 | HashMap map = new HashMap<>(); 23 | for (int num : nums) { 24 | map.put(num, map.getOrDefault(num, 0) + 1); 25 | } 26 | 27 | Set> entries = map.entrySet(); 28 | // 根据map的value值,构建于一个大顶堆(o1 - o2: 小顶堆, o2 - o1 : 大顶堆) 29 | PriorityQueue> queue = new 30 | PriorityQueue<>( 31 | (o1, o2) -> o2.getValue() - o1.getValue() 32 | ); 33 | for (Map.Entry entry : entries) { 34 | queue.offer(entry); 35 | } 36 | for (int i = k - 1; i >= 0; i--) { 37 | result[i] = queue.poll().getKey(); 38 | } 39 | return result; 40 | } 41 | class Solution { 42 | class Info{ 43 | int num; 44 | int times; 45 | public Info(int n,int t){ 46 | num = n; 47 | times = t; 48 | } 49 | } 50 | public int[] topKFrequent(int[] nums, int k) { 51 | ArrayList list = new ArrayList<>(); 52 | HashMap map = new HashMap<>(); 53 | for(Integer n:nums){ 54 | if(!map.containsKey(n)){ 55 | map.put(n,1); 56 | }else{ 57 | map.put(n,map.get(n)+1); 58 | } 59 | } 60 | for (Integer i : map.keySet()) { 61 | // System.out.println("key: " + i + " value: " + map.get(i)); 62 | list.add(new Info(i,map.get(i))); 63 | } 64 | list.sort(new Comparator() { 65 | @Override 66 | public int compare(Info o1, Info o2) { 67 | return o2.times-o1.times; 68 | } 69 | }); 70 | int []res = new int[k]; 71 | for(int i=0;i= (i + 2 * k) ) { 24 | reverse( arr, i, i + k ); 25 | } else if ( n - i < k ) { 26 | reverse( arr, i, n ); 27 | } else if ( n - i >= k && n - i < 2 * k ) { 28 | reverse( arr, i, i + k ); 29 | } 30 | } 31 | return String.valueOf( arr ); 32 | } 33 | 34 | 35 | public static void reverse( char[] arr, int start, int end ) { 36 | 37 | for ( int i = start, j = 0; i < (start + end) / 2; i++, j++ ) { 38 | char temp = arr[i]; 39 | arr[i] = arr[end - 1 - j]; 40 | arr[end - 1 - j] = temp; 41 | } 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeString/ReverseString.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeString; 2 | 3 | /** 4 | * @ClassName: ReverseString 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/28 1:09 下午 8 | */ 9 | 10 | public class ReverseString { 11 | 12 | /** 13 | * [344. 反转字符串](https://leetcode-cn.com/problems/reverse-string/) 14 | * 15 | * @param s 16 | */ 17 | public void reverseString( char[] s ) { 18 | int l = 0; 19 | int r = s.length - 1; 20 | while ( l < r ) { 21 | //构造 a ^ b 的结果,并放在 a 中 22 | s[l] ^= s[r]; 23 | //将 a ^ b 这一结果再 ^ b ,存入b中,此时 b = a, a = a ^ b 24 | s[r] ^= s[l]; 25 | //a ^ b 的结果再 ^ a ,存入 a 中,此时 b = a, a = b 完成交换 26 | s[l] ^= s[r]; 27 | l++; 28 | r--; 29 | } 30 | } 31 | 32 | 33 | public void reverseStringTwo( char[] arr ) { 34 | int start = 1; 35 | int end = arr.length; 36 | 37 | for ( int i = start - 1, j = 0; i < (start + end) / 2; i++, j++ ) { 38 | char temp = arr[i]; 39 | arr[i] = arr[end - 1 - j]; 40 | arr[end - 1 - j] = temp; 41 | } 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeString/ReverseWords.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeString; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @ClassName: ReverseWords 7 | * @Description: 8 | * @author: dk 9 | * @date: 2021/12/28 2:37 下午 10 | */ 11 | 12 | public class ReverseWords { 13 | 14 | /** 15 | * @param s 16 | * @return 17 | */ 18 | public String reverseWords( String s ) { 19 | //源字符数组 20 | char[] initialArr = s.toCharArray(); 21 | //新字符数组 22 | char[] newArr = new char[initialArr.length + 1]; 23 | int newArrPos = 0; 24 | //i来进行整体对源字符数组从后往前遍历 25 | int i = initialArr.length - 1; 26 | while ( i >= 0 ) { 27 | // 跳过空格,最后i停到最后一个单词的最后一个字母处 28 | while ( i >= 0 && initialArr[i] == ' ' ) { 29 | i--; 30 | } 31 | int right = i; 32 | // 找到单词的首字母 33 | while ( i >= 0 && initialArr[i] != ' ' ) { 34 | i--; 35 | } 36 | //指定区间单词取出(由于i为首字母的前一位,所以这里+1,) 37 | // 取出的每组末尾都带有一个空格 38 | for ( int j = i + 1; j <= right; j++ ) { 39 | newArr[newArrPos++] = initialArr[j]; 40 | if ( j == right ) { 41 | // 补空格 42 | newArr[newArrPos++] = ' '; 43 | } 44 | } 45 | } 46 | //若是原始字符串没有单词,直接返回空字符串; 47 | //若是有单词,返回0-末尾空格索引前范围的字符数组(转成String返回) 48 | if ( newArrPos == 0 ) { 49 | return ""; 50 | } else { 51 | return new String( newArr, 0, newArrPos - 1 ); 52 | } 53 | } 54 | 55 | 56 | public static void reverse( char[] arr, int start, int end ) { 57 | 58 | for ( int i = start, j = 0; i < (start + end) / 2; i++, j++ ) { 59 | char temp = arr[i]; 60 | arr[i] = arr[end - 1 - j]; 61 | arr[end - 1 - j] = temp; 62 | } 63 | 64 | } 65 | //TODO 双指针solution 66 | } 67 | 68 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeString/StrStr.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeString; 2 | 3 | import java.util.*; 4 | import java.util.function.ToIntFunction; 5 | 6 | /** 7 | * @ClassName: StrStr 8 | * @Description: 9 | * @author: dk 10 | * @date: 2021/12/30 5:05 下午 2022-08-25 16:12:30 11 | */ 12 | 13 | public class StrStr { 14 | 15 | /** 16 | * https://leetcode-cn.com/problems/implement-strstr/ 17 | * 18 | * @param haystack 19 | * @param needle 20 | * @return 21 | */ 22 | public static int strStr(String haystack, String needle) { 23 | if (needle.length() == 0) return 0; 24 | int[] next = new int[needle.length()]; 25 | getNext(next, needle); 26 | 27 | int j = 0; 28 | for (int i = 0; i < haystack.length(); i++) { 29 | while (j > 0 && needle.charAt(j) != haystack.charAt(i)) 30 | // 不对应时看前一位的位置 31 | j = next[j - 1]; 32 | if (needle.charAt(j) == haystack.charAt(i)) 33 | // 继续往后匹配 i 和 j 同时往后移动 34 | j++; 35 | if (j == needle.length()) 36 | return i - needle.length() + 1; 37 | } 38 | return -1; 39 | } 40 | 41 | private static void getNext(int[] next, String s) { 42 | int j = 0; 43 | next[0] = 0; 44 | for (int i = 1; i < s.length(); i++) { 45 | while (j > 0 && s.charAt(j) != s.charAt(i)) 46 | // 不相等时,回退到前一位 47 | j = next[j - 1]; 48 | if (s.charAt(j) == s.charAt(i)) 49 | // 相等时,前后缀长度+1 50 | j++; 51 | next[i] = j; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeTree/BinaryTreePaths.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeTree; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * @ClassName: BinaryTreePaths 9 | * @Description: 10 | * @author: dk 11 | * @date: 2022/2/8 6:42 下午 12 | */ 13 | 14 | public class BinaryTreePaths { 15 | public List list = new ArrayList<>(); 16 | public LinkedList link = new LinkedList<>(); 17 | public List binaryTreePaths(TreeNode root) { 18 | if(root.left==null && root.right==null){ 19 | list.add(new String(String.valueOf(root.val))); 20 | return list; 21 | } 22 | link.add(root); 23 | show(root); 24 | return list; 25 | } 26 | public void show(TreeNode root){ 27 | if(root.left==null && root.right==null){ 28 | List r = new ArrayList<>(link); 29 | String res = getRes(r); 30 | list.add(res); 31 | return; 32 | } 33 | if(root.left!=null){ 34 | link.add(root.left); 35 | show(root.left); 36 | link.removeLast(); 37 | } 38 | if(root.right!=null){ 39 | link.add(root.right); 40 | show(root.right); 41 | link.removeLast(); 42 | } 43 | } 44 | public String getRes(List resList){ 45 | String s =""; 46 | for(TreeNode r: resList){ 47 | s = s +"->"+ r.val ; 48 | } 49 | return s.substring(2,s.length()); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeTree/BuildTree.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeTree; 2 | 3 | /** 4 | * @ClassName: BuildTree 5 | * @Description: 6 | * @author: dk 7 | * @date: 2022/2/11 4:14 下午 8 | */ 9 | 10 | public class BuildTree { 11 | 12 | /** 13 | * 105. 从前序与中序遍历序列构造二叉树 14 | * https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/ 15 | * @param preorder 16 | * @param inorder 17 | * @return 18 | */ 19 | public TreeNode buildTreeByPreAndIno( int[] preorder, int[] inorder ) { 20 | if ( preorder.length == 0 && inorder.length == 0 ) { 21 | return null; 22 | } 23 | 24 | return build( preorder, 0, preorder.length, inorder, 0, inorder.length ); 25 | } 26 | public TreeNode build( int[] preorder, int pStart, int pEnd, 27 | int[] inorder, int iStart, int iEnd ) { 28 | if ( pEnd - pStart < 1 ) { 29 | return null; 30 | } 31 | 32 | int rootValue = preorder[pStart]; 33 | TreeNode node = new TreeNode( rootValue ); 34 | 35 | if ( pEnd - pStart == 1 ) { 36 | return node; 37 | } 38 | 39 | int index; 40 | for ( index = 0; index < inorder.length; index++ ) { 41 | if ( inorder[index] == rootValue ) { 42 | break; 43 | } 44 | } 45 | int preorderLeftStart = pStart + 1; 46 | int preorderLeftEnd = pStart + 1 + index - iStart; 47 | 48 | int preorderRightStart = pStart + 1 + index - iStart; 49 | int preorderRightEnd = pEnd; 50 | 51 | int inorderLeftStart = iStart; 52 | int inorderLeftEnd = index; 53 | 54 | int inorderRightStart = index + 1; 55 | int inorderRightEnd = iEnd; 56 | 57 | node.left = build( preorder, preorderLeftStart, preorderLeftEnd, 58 | inorder, inorderLeftStart, inorderLeftEnd ); 59 | node.right = build( preorder, preorderRightStart, preorderRightEnd, 60 | inorder, inorderRightStart, inorderRightEnd ); 61 | 62 | return node; 63 | } 64 | 65 | 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeTree/Connect.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeTree; 2 | 3 | import java.util.Arrays; 4 | import java.util.LinkedList; 5 | import java.util.Queue; 6 | 7 | /** 8 | * @ClassName: Connect 9 | * @Description: 10 | * @author: dk 11 | * @date: 2022/2/8 5:34 下午 12 | */ 13 | 14 | public class Connect { 15 | 16 | class Node { 17 | 18 | public int val; 19 | public Node left; 20 | public Node right; 21 | public Node next; 22 | 23 | 24 | public Node() { 25 | } 26 | 27 | 28 | public Node( int _val ) { 29 | val = _val; 30 | } 31 | 32 | 33 | public Node( int _val, Node _left, Node _right, Node _next ) { 34 | val = _val; 35 | left = _left; 36 | right = _right; 37 | next = _next; 38 | } 39 | 40 | } 41 | 42 | 43 | /** 44 | * 117. 填充每个节点的下一个右侧节点指针 II 45 | * https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node-ii/ 46 | * 47 | * @param root 48 | * @return 49 | */ 50 | public Node connect( Node root ) { 51 | if ( root == null ) { 52 | return null; 53 | } 54 | root.next = null; 55 | Queue qu = new LinkedList<>(); 56 | 57 | if ( root.left != null ) { 58 | qu.offer( root.left ); 59 | } 60 | if ( root.right != null ) { 61 | qu.offer( root.right ); 62 | } 63 | 64 | while ( !qu.isEmpty() ) { 65 | 66 | int size = qu.size(); 67 | Node node = null; 68 | Node preNode = null; 69 | 70 | for ( int i = 0; i < size; i++ ) { 71 | 72 | if ( i == 0 ) { 73 | preNode = qu.poll(); 74 | node = preNode; 75 | } else { 76 | node = qu.poll(); 77 | preNode.next = node; 78 | preNode = preNode.next; 79 | } 80 | 81 | if ( node.left != null ) { 82 | qu.offer( node.left ); 83 | } 84 | if ( node.right != null ) { 85 | qu.offer( node.right ); 86 | } 87 | 88 | } 89 | // 本层最后一个节点 next 指向 null 90 | preNode.next = null; 91 | } 92 | return root; 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeTree/ConstructMaximumBinaryTree.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeTree; 2 | 3 | /** 4 | * @ClassName: ConstructMaximumBinaryTree 5 | * @Description: 6 | * @author: dk 7 | * @date: 2022/2/10 6:52 下午 8 | */ 9 | 10 | public class ConstructMaximumBinaryTree { 11 | 12 | public TreeNode getTree( int[] nums, int left, int right ) { 13 | if ( left >= right ) { 14 | return null; 15 | } 16 | //if(left<0 || right >nums.length )return null; 17 | 18 | int maxIndex = left; 19 | for ( int i = left + 1; i < right; i++ ) { 20 | if ( nums[maxIndex] < nums[i] ) { 21 | maxIndex = i; 22 | } 23 | } 24 | TreeNode node = new TreeNode( nums[maxIndex] ); 25 | 26 | node.left = getTree( nums, left, maxIndex ); 27 | node.right = getTree( nums, maxIndex + 1, right ); 28 | 29 | return node; 30 | } 31 | 32 | 33 | public TreeNode constructMaximumBinaryTree( int[] nums ) { 34 | return getTree( nums, 0, nums.length ); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeTree/IsBalanced.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeTree; 2 | 3 | /** 4 | * @ClassName: IsBalanced 5 | * @Description: 6 | * @author: dk 7 | * @date: 2022/2/9 5:45 下午 8 | */ 9 | 10 | public class IsBalanced { 11 | 12 | class Info { 13 | 14 | public boolean isBalanced; 15 | public int height; 16 | 17 | public Info( boolean b, int h ) { 18 | isBalanced = b; 19 | height = h; 20 | } 21 | 22 | } 23 | 24 | 25 | public Info process( TreeNode node ) { 26 | if ( node == null ) { 27 | return new Info( true, 0 ); 28 | } 29 | Info left = process( node.left ); 30 | Info right = process( node.right ); 31 | 32 | int height = Math.max( left.height, right.height ) + 1; 33 | 34 | boolean isBalanced = true; 35 | 36 | if ( !left.isBalanced || !right.isBalanced 37 | || Math.abs( left.height - right.height ) > 1 38 | ) { 39 | isBalanced = false; 40 | } 41 | 42 | return new Info( isBalanced, height ); 43 | } 44 | 45 | 46 | /** 47 | * 110. 平衡二叉树 48 | * https://leetcode-cn.com/problems/balanced-binary-tree/ 49 | * @param root 50 | * @return 51 | */ 52 | public boolean isBalanced( TreeNode root ) { 53 | return process( root ).isBalanced; 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeTree/IsValidBST.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeTree; 2 | 3 | /** 4 | * @ClassName: IsValidBST 5 | * @Description: 6 | * @author: dk 7 | * @date: 2022/9/6 16:09 8 | */ 9 | 10 | public class IsValidBST { 11 | 12 | /** 13 | *[98. 验证二叉搜索树](https://leetcode.cn/problems/validate-binary-search-tree/) 14 | * @param root 15 | * @return 16 | */ 17 | public boolean isValidBST(TreeNode root) { 18 | return check(Long.MIN_VALUE, Long.MAX_VALUE, root); 19 | } 20 | boolean check(long lower, long upper, TreeNode root) { 21 | if (root == null) return true; 22 | if (root.val <= lower || root.val >= upper) return false; 23 | 24 | return check(lower, root.val, root.left) 25 | && 26 | check(root.val, upper, root.right); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeTree/MinDiffInBST.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeTree; 2 | 3 | /** 4 | * @ClassName: MinDiffInBST 5 | * @Description: 6 | * @author: dk 7 | * @date: 2022/2/12 4:20 下午 8 | */ 9 | 10 | public class MinDiffInBST { 11 | 12 | // 记录上一个遍历的结点 13 | TreeNode pre; 14 | public int res = Integer.MAX_VALUE; 15 | 16 | 17 | /** 18 | * 783. 二叉搜索树节点最小距离 19 | * https://leetcode-cn.com/problems/minimum-distance-between-bst-nodes/ 20 | * @param root 21 | * @return 22 | */ 23 | public int minDiffInBST( TreeNode root ) { 24 | show( root ); 25 | return res; 26 | } 27 | 28 | 29 | public void show( TreeNode root ) { 30 | if ( root == null ) { 31 | return; 32 | } 33 | show( root.left ); 34 | if ( pre != null ) { 35 | System.out.println( " root.val--" + root.val + " pre.val--" + pre.val ); 36 | res = Math.min( res, root.val - pre.val ); 37 | } 38 | pre = root; 39 | //右 40 | show( root.right ); 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeTree/TreeModle.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeTree; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | import java.util.Queue; 7 | 8 | 9 | /** 10 | * @ClassName: TreeModle 11 | * @Description: 12 | * @author: dk 13 | * @date: 2022/2/8 4:58 下午 14 | */ 15 | 16 | public class TreeModle { 17 | 18 | public List treeDFS( TreeNode root ) { 19 | List res = new ArrayList<>(); 20 | if ( root == null ) { 21 | return res; 22 | } 23 | Queue qu = new LinkedList<>(); 24 | 25 | res.add( root.val ); 26 | if ( root.left != null ) { 27 | qu.offer( root.left ); 28 | } 29 | if ( root.right != null ) { 30 | qu.offer( root.right ); 31 | } 32 | 33 | while ( !qu.isEmpty() ) { 34 | int size = qu.size(); 35 | for ( int i = 0; i < size; i++ ) { 36 | TreeNode node = qu.poll(); 37 | 38 | //do something 39 | 40 | if ( node.left != null ) { 41 | qu.offer( node.left ); 42 | } 43 | if ( node.right != null ) { 44 | qu.offer( node.right ); 45 | } 46 | } 47 | } 48 | return res; 49 | } 50 | 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/dailyExercise/LeetCodeTree/TreeNode.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.LeetCodeTree; 2 | 3 | /** 4 | * @ClassName: TreeNode 5 | * @Description: 6 | * @author: dk 7 | * @date: 2022/2/8 6:42 下午 8 | */ 9 | 10 | class TreeNode { 11 | 12 | int val; 13 | TreeNode left; 14 | TreeNode right; 15 | 16 | 17 | TreeNode() { 18 | } 19 | 20 | 21 | TreeNode( int val ) { 22 | this.val = val; 23 | } 24 | 25 | 26 | TreeNode( int val, TreeNode left, TreeNode right ) { 27 | this.val = val; 28 | this.left = left; 29 | this.right = right; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/dailyExercise/Lock/CreateLock.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.Lock; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | import java.util.concurrent.locks.AbstractQueuedSynchronizer; 5 | import java.util.concurrent.locks.Condition; 6 | import java.util.concurrent.locks.Lock; 7 | 8 | /** 9 | * @ClassName: CreateLock 10 | * @Description: 11 | * @author: dk 12 | * @date: 2022/9/22 16:55 13 | */ 14 | 15 | public class CreateLock implements Lock { 16 | 17 | /** 18 | * 3. 重写 aqs 里面的方法,完成需求 19 | * aqs 里只有五个方法可以被重写 20 | * tryAcquire tryRelease 排他锁 加锁、解锁 21 | * tryAcquireShared tryReleaseShared 共享锁 加锁 解锁 22 | * isHeldExclusively 当前线程是否被线程独占的方法 23 | */ 24 | private static class Sync extends AbstractQueuedSynchronizer { 25 | 26 | // 加锁 27 | protected boolean tryAcquire(int arg) { 28 | // 线程名字必须是 AQS-Lock 才能加锁 29 | if (!Thread.currentThread().getName().equals("AQS-Lock")) { 30 | return false; 31 | } 32 | if (compareAndSetState(0, arg)) { 33 | // 设置为当前线程 34 | setExclusiveOwnerThread(Thread.currentThread()); 35 | return true; 36 | } 37 | return false; 38 | } 39 | 40 | // 解锁 41 | protected boolean tryRelease(int arg) { 42 | if (getState() == 0) { 43 | throw new IllegalStateException(); 44 | } 45 | // 此处不用cas的原因是,既然要调用解锁,那自然是自身持有锁,有锁,代表自己有一个单独的私人线程 46 | // 所以不涉及多线程问题,无需cas 47 | setState(0); 48 | return true; 49 | } 50 | 51 | Condition getCondition(){ 52 | return new ConditionObject(); 53 | } 54 | } 55 | 56 | private Sync sync = new Sync(); 57 | 58 | @Override 59 | public void lock() { 60 | // 使用的是 AbstractQueuedSynchronizer 的acquire 方法 61 | sync.acquire(1); 62 | } 63 | 64 | @Override 65 | public boolean tryLock() { 66 | return sync.tryAcquire(1); 67 | } 68 | 69 | @Override 70 | public boolean tryLock(long time, TimeUnit unit) throws InterruptedException { 71 | return sync.tryAcquireNanos(1, unit.toNanos(time)); 72 | } 73 | 74 | @Override 75 | public void unlock() { 76 | sync.tryRelease(1); 77 | } 78 | 79 | @Override 80 | public Condition newCondition() { 81 | return sync.getCondition(); 82 | } 83 | 84 | @Override 85 | public void lockInterruptibly() throws InterruptedException { 86 | sync.acquireInterruptibly(1); 87 | } 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/dailyExercise/Lock/TestCreatLock.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.Lock; 2 | 3 | /** 4 | * @ClassName: TestCreatLock 5 | * @Description: 6 | * @author: dk 7 | * @date: 2022/9/22 16:56 8 | */ 9 | 10 | public class TestCreatLock { 11 | private static CreateLock createLock = new CreateLock(); 12 | 13 | public static void main(String[] args) { 14 | Thread A = new Thread(() -> { 15 | testLock(); 16 | while (true) { 17 | 18 | } 19 | }); 20 | Thread B = new Thread(() -> { 21 | testLock(); 22 | }); 23 | 24 | // 只有 A 能拿到锁,因为加锁限制了线程名字 25 | A.setName("AQS-Lock"); 26 | B.setName("Lock"); 27 | 28 | A.start(); 29 | B.start(); 30 | } 31 | 32 | private static void testLock() { 33 | createLock.lock(); 34 | try { 35 | System.out.println("当前获取到锁的线程名称是:" 36 | + Thread.currentThread().getName()); 37 | } catch (Exception e) { 38 | e.printStackTrace(); 39 | } finally { 40 | createLock.unlock(); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/dailyExercise/Thread/Demo.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.Thread; 2 | 3 | /** 4 | * @ClassName: 两个线程交替打印 5 | * @Description: 6 | * @author: dk 7 | * @date: 2022/9/8 18:13 8 | */ 9 | 10 | public class Demo { 11 | public static void main(String[] args) throws InterruptedException { 12 | Number number = new Number(); 13 | Thread t1 = new Thread(number,"线程1"); 14 | Thread t2 = new Thread(number,"线程2"); 15 | t1.start(); 16 | t2.start(); 17 | 18 | } 19 | static class Number implements Runnable{ 20 | 21 | private int i = 0; 22 | 23 | @Override 24 | public void run() { 25 | while (true){ 26 | synchronized (this) { 27 | notify(); 28 | if(i < 100){ 29 | i++; 30 | System.out.println(Thread.currentThread().getName()+"---"+i); 31 | }else{ 32 | break; 33 | } 34 | try { 35 | wait(); 36 | } catch (InterruptedException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/dailyExercise/lanqiaoTest1/LanQiaoTest2.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.lanqiaoTest1; 2 | 3 | /** 4 | * @ClassName: LanQiaoTest2 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/2 11:33 上午 8 | */ 9 | 10 | public class LanQiaoTest2 { 11 | 12 | public static void main( String[] args ) { 13 | String s = "123456789"; 14 | process( s.toCharArray(), 0 ); 15 | } 16 | 17 | 18 | private static void process( char[] ch, int i ) { 19 | if ( i == ch.length ) { 20 | System.out.println( String.valueOf( ch ) ); 21 | } 22 | for ( int j = i; j < ch.length; j++ ) { 23 | swap( ch, i, j ); 24 | process( ch, i + 1 ); 25 | swap( ch, i, j ); 26 | } 27 | } 28 | 29 | 30 | public static void swap( char[] chs, int i, int j ) { 31 | char tmp = chs[i]; 32 | chs[i] = chs[j]; 33 | chs[j] = tmp; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/dailyExercise/model/CombinationModle.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * @ClassName: CombinationModle 9 | * @Description: 组合问题模版 10 | * @author: dk 11 | * @date: 2021/11/27 11:57 上午 12 | */ 13 | 14 | public class CombinationModle { 15 | 16 | List> result = new ArrayList<>(); 17 | LinkedList path = new LinkedList<>(); 18 | 19 | 20 | public List> combine( int n, int k ) { 21 | combineHelper( n, k, 1 ); 22 | return result; 23 | } 24 | 25 | 26 | /** 27 | * 每次从集合中选取元素,可选择的范围随着选择的进行而收缩,调整可选择的范围,就是要靠startIndex 28 | * 29 | * @param startIndex 用来记录本层递归的中,集合从哪里开始遍历(集合就是[1,...,n] )。 30 | */ 31 | private void combineHelper( int n, int k, int startIndex ) { 32 | //终止条件 33 | if ( path.size() == k ) { 34 | result.add( new ArrayList<>( path ) ); 35 | return; 36 | } 37 | // n - (k - path.size()) + 1 剪枝操作 38 | for ( int i = startIndex; i <= n - (k - path.size()) + 1; i++ ) { 39 | path.add( i ); 40 | combineHelper( n, k, i + 1 ); 41 | path.removeLast(); 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/dailyExercise/model/Compare.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.model; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * @ClassName: Compare 7 | * @Description: 8 | * @author: dk 9 | * @date: 2021/12/3 11:24 上午 10 | */ 11 | class Student { 12 | 13 | int age; 14 | String name; 15 | int grade; 16 | 17 | 18 | Student( int a, String b, int g ) { 19 | this.age = a; 20 | this.name = b; 21 | this.grade = g; 22 | } 23 | 24 | } 25 | 26 | 27 | public class Compare { 28 | 29 | public static void main( String[] args ) { 30 | List list = new ArrayList<>(); 31 | list.sort( new Comparator() { 32 | @Override 33 | public int compare( Integer o1, Integer o2 ) { 34 | return o2.compareTo( o1 ); 35 | } 36 | } ); 37 | 38 | //创建学生对象数组 39 | Student s[] = new Student[4]; 40 | s[0] = new Student( 10, "1", 10 ); 41 | s[1] = new Student( 7, "2", 9 ); 42 | s[2] = new Student( 8, "3", 6 ); 43 | s[3] = new Student( 7, "4", 10 ); 44 | 45 | Arrays.sort( s, new Comparator() { 46 | @Override 47 | public int compare( Student a, Student b ) { 48 | if ( a.age == b.age ) { 49 | return b.grade - a.grade; 50 | } else { 51 | return a.age - b.age; 52 | } 53 | } 54 | } ); 55 | for ( Student p : s ) { 56 | System.out.println( p.age + " " + p.grade + "\n" ); 57 | } 58 | 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/dailyExercise/model/FullArrangement.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.model; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @ClassName: FullArrangement 8 | * @Description: 全排列 9 | * @author: dk 10 | * @date: 2021/11/27 11:49 上午 11 | */ 12 | 13 | public class FullArrangement { 14 | 15 | public static List list = new ArrayList<>(); 16 | 17 | 18 | private static void process( char[] ch, int start ) { 19 | if ( start == ch.length ) { 20 | System.out.println( String.valueOf( ch ) ); 21 | list.add( String.valueOf( ch ) ); 22 | } 23 | for ( int j = start; j < ch.length; j++ ) { 24 | swap( ch, start, j ); 25 | process( ch, start + 1 ); 26 | swap( ch, start, j ); 27 | } 28 | } 29 | 30 | 31 | public static void swap( char[] chs, int i, int j ) { 32 | char tmp = chs[i]; 33 | chs[i] = chs[j]; 34 | chs[j] = tmp; 35 | } 36 | 37 | 38 | public static void main( String[] args ) { 39 | String ch = "123"; 40 | process( ch.toCharArray(), 0 ); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/dailyExercise/model/FullCombination.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.model; 2 | 3 | import java.util.HashSet; 4 | 5 | /** 6 | * @ClassName: FullCombination 7 | * @Description: 全组合 (包含一个空字符串) 8 | * @author: dk 9 | * @date: 2021/11/27 11:53 上午 10 | */ 11 | 12 | public class FullCombination { 13 | 14 | public static HashSet set = new HashSet<>(); 15 | 16 | 17 | private static void print( char[] chs, int i, String s ) { 18 | if ( i == chs.length ) { 19 | if ( !set.contains( s ) ) { 20 | System.out.println( s ); 21 | return; 22 | } 23 | } 24 | print( chs, i + 1, s ); 25 | print( chs, i + 1, s + chs[i] ); 26 | } 27 | 28 | 29 | public static void main( String[] args ) { 30 | String s = "123"; 31 | print( s.toCharArray(), 0, "" ); 32 | } 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/dailyExercise/model/Input.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.model; 2 | 3 | /** 4 | * @ClassName: Input 5 | * @Description: 输入挂 6 | * @author: dk 7 | * @date: 2022/1/7 7:43 下午 8 | */ 9 | 10 | 11 | /* 12 | lrj书中原话:最常用的Scanner类通常比scanf系列慢5~10倍,应尽量避免;下面的代码包装了速度较快的 13 | BufferedReader和StringTokenizer(比split函数略快),推荐选手在比赛中使用。 14 | */ 15 | import java.io.*; 16 | import java.util.*; 17 | 18 | class Reader { 19 | static BufferedReader reader; 20 | static StringTokenizer tokenizer; 21 | static void init(InputStream input) { 22 | reader=new BufferedReader(new InputStreamReader(System.in)); 23 | tokenizer=new StringTokenizer(""); 24 | } 25 | static String next() throws IOException { 26 | while (!tokenizer.hasMoreTokens()) { 27 | tokenizer=new StringTokenizer(reader.readLine()); 28 | } 29 | return tokenizer.nextToken(); 30 | } 31 | static int nextInt() throws IOException { 32 | return Integer.parseInt(next()); 33 | } 34 | static double nextDouble() throws IOException { 35 | return Double.parseDouble(next()); 36 | } 37 | } 38 | 39 | 40 | /** 41 | * 然后接下来应用的时候,先要Reader.init(System.in); 42 | * 关于整数部分读入,直接用Reader.nextInt()方法,而浮点数读入用Reader.nextDouble()方法 43 | * 字符串读入,用Reader.next()方法 44 | */ 45 | public class Input { 46 | 47 | public static void main(String[] args) throws IOException { 48 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); 49 | String line; 50 | while((line = bufferedReader.readLine()) != null){ 51 | String[] elements = line.split(" "); 52 | int sum = 0; 53 | for (int i = 0; i < elements.length; i++) { 54 | int num = Integer.parseInt(elements[i]); 55 | sum += num; 56 | } 57 | System.out.println(sum); 58 | } 59 | 60 | 61 | 62 | //way Two 63 | 64 | // BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 65 | // String[] stoken = br.readLine().split(" "); 66 | // int n = Integer.parseInt(stoken[0]); 67 | // int m = Integer.parseInt(stoken[1]); 68 | // System.out.println(n+m); 69 | // 70 | // String x = br.readLine(); 71 | // System.out.println(x.indexOf( "t" )); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/dailyExercise/model/InputAndOutput.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.model; 2 | 3 | /** 4 | * @ClassName: InputAndOutput 5 | * @Description: 6 | * @author: dk 7 | * @date: 2022/1/7 8:03 下午 8 | */ 9 | import java.io.*; 10 | public class InputAndOutput { 11 | 12 | public static void main( String[] args ) throws IOException { 13 | 14 | StreamTokenizer in = new StreamTokenizer( new BufferedReader( new InputStreamReader( System.in ) ) ); 15 | PrintWriter out = new PrintWriter( new OutputStreamWriter( System.out ) ); 16 | 17 | //StreamTokenizer.TT_EOF这个是个参数,就是EOF 18 | while ( in.nextToken() != StreamTokenizer.TT_EOF ) { 19 | int n = (int) in.nval; 20 | int max = 0; 21 | for ( int i = 0; i < n; i++ ) { 22 | in.nextToken();//指向下一个 23 | if(in.nval>max){ 24 | max= (int)in.nval; 25 | } 26 | } 27 | out.println( max ); 28 | out.flush();//刷新,不然max会留在缓冲区 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/dailyExercise/model/InputModle.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.model; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.OutputStreamWriter; 7 | import java.io.PrintWriter; 8 | import java.util.Arrays; 9 | import java.util.Scanner; 10 | import java.lang.*; 11 | 12 | /** 13 | * @ClassName: InputModle 14 | * @Description: acm 笔试输入模版 15 | * @author: dk 16 | * @date: 2022/1/7 7:15 下午 17 | */ 18 | 19 | public class InputModle { 20 | 21 | 22 | public static void inputRow() { 23 | //链接:https://ac.nowcoder.com/acm/contest/27121/B 24 | //来源:牛客网 25 | // 26 | //输入第一行包括一个数据组数t(1 <= t <= 100) 27 | //接下来每行包括两个正整数a,b(1 <= a, b <= 1000) 28 | //输出描述: 29 | //输出a+b的结果 30 | //示例1 31 | //输入 32 | //复制 33 | //2 34 | //1 5 35 | //10 20 36 | Scanner in = new Scanner( System.in ); 37 | int num = in.nextInt(); 38 | while ( in.hasNext() ) { 39 | for ( int i = 0; i < num; i++ ) { 40 | System.out.println( in.nextInt() + in.nextInt() ); 41 | } 42 | 43 | } 44 | } 45 | public static void inputEnd(){ 46 | //链接:https://ac.nowcoder.com/acm/contest/27121/C 47 | //来源:牛客网 48 | // 49 | //输入包括两个正整数a,b(1 <= a, b <= 10^9),输入数据有多组, 如果输入为0 0则结束输入 50 | //输出描述: 51 | //输出a+b的结果 52 | //示例1 53 | //输入 54 | //复制 55 | //1 5 56 | //10 20 57 | //0 0 58 | Scanner in = new Scanner( System.in ); 59 | while ( in.hasNext() ) { 60 | int a = in.nextInt() ; 61 | int b = in.nextInt(); 62 | if ( a != 0 ) { 63 | System.out.println(a+b); 64 | } 65 | } 66 | } 67 | public static void inputOneRow(){ 68 | //链接:https://ac.nowcoder.com/acm/contest/27121/D 69 | //来源:牛客网 70 | // 71 | //输入数据包括多组。 72 | //每组数据一行,每行的第一个整数为整数的个数n(1 <= n <= 100), n为0的时候结束输入。 73 | //接下来n个正整数,即需要求和的每个正整数。 74 | //输出描述: 75 | //每组数据输出求和的结果 76 | //示例1 77 | //输入 78 | //复制 79 | //4 1 2 3 4 80 | //5 1 2 3 4 5 81 | //0 82 | Scanner sc=new Scanner(System.in); 83 | while(sc.hasNextLine()){ 84 | String str=sc.nextLine(); 85 | if("0".equals(str)) return; 86 | String[] strArr=str.split(" "); 87 | int sum=0; 88 | for(int i=1;i 0 ) { 50 | ListNode m = new ListNode(); 51 | for ( int i = 0; i < n; i++ ) { 52 | int temp = sc.nextInt(); 53 | m.addNode( temp ); 54 | } 55 | node = rever( head ); 56 | for ( int j = 0; j < n; j++ ) { 57 | System.out.print( node.val + " " ); 58 | node = node.next; 59 | } 60 | } 61 | } 62 | 63 | 64 | public static Node rever( Node head ) { 65 | if ( head == null || head.next == null ) { 66 | return head; 67 | } 68 | Node pre = null; 69 | Node cur = head; 70 | while ( cur != null ) { 71 | Node temp = cur.next; 72 | cur.next = pre; 73 | pre = cur; 74 | cur = temp; 75 | } 76 | return pre; 77 | } 78 | 79 | 80 | } 81 | 82 | 83 | -------------------------------------------------------------------------------- /src/dailyExercise/model/Mid0rUpMidNode.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.model; 2 | 3 | /** 4 | * @ClassName: mid0rUpMidNode 5 | * @Description: 链表相关 6 | * @author: dk 7 | * @date: 2021/11/27 5:14 下午 8 | */ 9 | 10 | public class Mid0rUpMidNode { 11 | 12 | static class Node { 13 | 14 | int val; 15 | Node next; 16 | 17 | } 18 | 19 | 20 | //输入链表头节点,奇数长度返回中点,偶数长度返回上中点 21 | public static Node mid0rUpMidNode( Node head ) { 22 | if ( head == null || head.next == null || head.next.next == null ) { 23 | return head; 24 | } 25 | Node slow = head.next; 26 | Node fast = head.next.next; 27 | while ( fast.next != null && fast.next.next != null ) { 28 | slow = slow.next; 29 | fast = fast.next.next; 30 | } 31 | return slow; 32 | } 33 | 34 | 35 | public static Node mid0rUpMidNode2( Node head ) { 36 | if ( head == null || head.next == null ) { 37 | return null; 38 | } 39 | Node n1 = head; 40 | Node n2 = head; 41 | while ( n2.next != null && n2.next.next != null ) { // find mid node 42 | n1 = n1.next; // n1 -》mid 43 | n2 = n2.next.next; // n2 -> end 44 | } 45 | return n1; 46 | } 47 | 48 | 49 | //输入链表头节点,奇数长度返回中点,偶数长度返回下中点 50 | public static Node mid0rDownMidNode( Node head ) { 51 | if ( head == null || head.next == null ) { 52 | return head; 53 | } 54 | Node slow = head.next; 55 | Node fast = head.next; 56 | while ( fast.next != null && fast.next.next != null ) { 57 | slow = slow.next; 58 | fast = fast.next.next; 59 | } 60 | return slow; 61 | } 62 | 63 | 64 | //输入链表头节点,奇数长度返回中点前一个,偶数长度返回.上中点前一个 65 | public static Node mid0rUpMidPreNode( Node head ) { 66 | if ( head == null || head.next == null || head.next.next == null ) { 67 | return null; 68 | } 69 | Node slow = head; 70 | Node fast = head.next.next; 71 | while ( fast.next != null && fast.next.next != null ) { 72 | slow = slow.next; 73 | fast = fast.next.next; 74 | } 75 | return slow; 76 | } 77 | 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/dailyExercise/model/QuickSort.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.model; 2 | 3 | /** 4 | * @ClassName: QuickSort 5 | * @Description: 快排 6 | * @author: dk 7 | * @date: 2021/11/27 4:48 下午 8 | */ 9 | 10 | public class QuickSort { 11 | 12 | public static void quickSort( int[] arr ) { 13 | if ( arr == null || arr.length < 2 ) { 14 | return; 15 | } 16 | quickSort( arr, 0, arr.length - 1 ); 17 | } 18 | 19 | 20 | public static void quickSort( int[] arr, int L, int R ) { 21 | if ( L < R ) { 22 | //先随机取出一个数放到最后 23 | //swap(arr, L + (int) (Math.random() * (R - L + 1)), R); 24 | int[] p = partition( arr, L, R ); 25 | quickSort( arr, L, p[0] - 1 ); 26 | quickSort( arr, p[1] + 1, R ); 27 | } 28 | } 29 | 30 | 31 | public static int[] partition( int[] arr, int l, int r ) { 32 | int less = l - 1; 33 | int more = r; 34 | while ( l < more ) { 35 | if ( arr[l] < arr[r] ) { 36 | swap( arr, ++less, l++ ); 37 | } else if ( arr[l] > arr[r] ) { 38 | swap( arr, --more, l ); 39 | } else { 40 | l++; 41 | } 42 | } 43 | swap( arr, more, r ); 44 | return new int[]{ less + 1, more }; 45 | } 46 | 47 | 48 | public static void swap( int[] arr, int i, int j ) { 49 | int tmp = arr[i]; 50 | arr[i] = arr[j]; 51 | arr[j] = tmp; 52 | } 53 | 54 | 55 | public static void main( String[] args ) { 56 | // int[] arr = { 3, 4, 5, 6, 1, 2, 3, 4, 5, 4, 3 }; 57 | // int num = 4; 58 | // printArray( arr ); 59 | // quickSort( arr ); 60 | // printArray( arr ); 61 | StringBuffer sb = new StringBuffer(); 62 | char a = 'a'; 63 | sb.append( a ); 64 | } 65 | 66 | 67 | private static void printArray( int[] arr ) { 68 | for ( Integer i : 69 | arr ) { 70 | System.out.print( i + " " ); 71 | } 72 | System.out.println(); 73 | } 74 | 75 | } 76 | 77 | -------------------------------------------------------------------------------- /src/dailyExercise/model/Reverse.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.model; 2 | 3 | /** 4 | * @ClassName: Reverse 5 | * @Description: 6 | * @author: dk 7 | * @date: 2021/12/27 1:10 下午 8 | */ 9 | 10 | public class Reverse { 11 | 12 | public static void reverse( char[] arr, int start, int end ) { 13 | 14 | for ( int i = start, j = end; i < j; i++, j-- ) { 15 | char temp = arr[i]; 16 | arr[i] = arr[j]; 17 | arr[j] = temp; 18 | } 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/dailyExercise/skillsContest/Main1.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.skillsContest; 2 | 3 | 4 | import java.util.Scanner; 5 | 6 | /** 7 | * @author dk 8 | */ 9 | public class Main1 { 10 | 11 | public static int result = 0; 12 | 13 | 14 | public static boolean like( String str, String expr ) { 15 | //str = str.toLowerCase(); // ignoring locale for now 16 | str = str.replace( ".", "\\." ); // "\\" is escaped to "\" (thanks, Alan M) 17 | // ... escape any other potentially problematic characters here 18 | str = str.replace( "?", "." ); 19 | str = str.replace( "_", "." ); 20 | str = str.replace( "%", ".*" ); 21 | //expr = expr.toLowerCase(); 22 | 23 | System.out.println( "str: " + str ); 24 | System.out.println( "expr: " + expr ); 25 | 26 | System.out.println( str.compareTo( expr ) ); 27 | 28 | return str.matches( expr ); 29 | } 30 | 31 | 32 | static String up( String s, int j ) { 33 | char[] arr = s.toCharArray(); 34 | if ( arr[j] == '9' ) { 35 | arr[j] = '0'; 36 | } else { 37 | arr[j] += 1; 38 | } 39 | return new String( arr ); 40 | } 41 | 42 | 43 | static String down( String s, int j ) { 44 | char[] arr = s.toCharArray(); 45 | if ( arr[j] == '0' ) { 46 | arr[j] = '9'; 47 | } else { 48 | arr[j] -= 1; 49 | } 50 | return new String( arr ); 51 | } 52 | 53 | 54 | // 方向数组,分别代表上、下、左、右 55 | static int[][] dirs = new int[][]{ { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } }; 56 | 57 | 58 | static void dfs( int[][] grid, int i, int j, boolean[][] visited ) { 59 | int m = grid.length, n = grid[0].length; 60 | if ( i < 0 || j < 0 || i >= m || j >= n ) { 61 | // 超出索引边界 62 | return; 63 | } 64 | if ( visited[i][j] ) { 65 | // 已遍历过 (i, j) 66 | return; 67 | } 68 | visited[i][j] = true; 69 | System.out.println( grid[i][j] ); 70 | for ( int[] d : dirs ) { 71 | int next_i = i + d[0]; 72 | int next_j = j + d[1]; 73 | dfs( grid, next_i, next_j, visited ); 74 | } 75 | } 76 | 77 | 78 | 79 | public static void main( String[] args ) { 80 | int a = 0, b = 0, c = 0; 81 | System.out.println( a ); 82 | System.out.println( b ); 83 | System.out.println( c ); 84 | 85 | int[][] grid = new int[][]{ 86 | { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } 87 | }; 88 | boolean[][] visited = new boolean[3][3]; 89 | dfs( grid, 0, 0, visited ); 90 | 91 | // Scanner sc = new Scanner( System.in ); 92 | // int n = sc.nextInt(); 93 | // int m = sc.nextInt(); 94 | // int[][] res = new int[n][m]; 95 | // for ( int i = 0; i < n; i++ ) { 96 | // for ( int j = 0; j < m; j++ ) { 97 | // res[i][j] = sc.nextInt(); 98 | // } 99 | // } 100 | // show( res ); 101 | // System.out.println( result ); 102 | } 103 | 104 | 105 | public static void show( int[][] grid ) { 106 | for ( int i = 0; i < grid.length; i++ ) { 107 | for ( int j = 0; j < grid[0].length; j++ ) { 108 | if ( grid[i][j] == 1 ) { 109 | sum( grid, i, j ); 110 | result++; 111 | } 112 | } 113 | } 114 | } 115 | 116 | 117 | public static void sum( int[][] grid, int i, int j ) { 118 | if ( i >= grid.length || i < 0 || j >= grid[0].length || j < 0 || grid[i][j] != 1 ) { 119 | return; 120 | } 121 | grid[i][j] = 0; 122 | sum( grid, i + 1, j ); 123 | sum( grid, i - 1, j ); 124 | sum( grid, i, j + 1 ); 125 | sum( grid, i, j - 1 ); 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/dailyExercise/skillsContest/Main2.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.skillsContest; 2 | 3 | 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.Scanner; 7 | 8 | /** 9 | * @author dk 10 | */ 11 | public class Main2 { 12 | 13 | public static int matrixScore( int[][] mar ) { 14 | if ( mar.length == 0 || mar[0].length == 0 ) { 15 | return 0; 16 | } 17 | int result = mar.length; 18 | for ( int i = 1; i < mar[0].length; i++ ) { 19 | int number = 0; 20 | for ( int j = 0; j < mar.length; j++ ) { 21 | if ( mar[j][i] == mar[j][0] ) { 22 | number++; 23 | } 24 | } 25 | result = (result << 1) + Math.max( number, mar.length - number ); 26 | } 27 | return result; 28 | } 29 | 30 | 31 | public static List list = new ArrayList<>(); 32 | 33 | 34 | public static void main( String[] args ) { 35 | Scanner sc = new Scanner( System.in ); 36 | int n = sc.nextInt(); 37 | for ( int i = 0; i < n; i++ ) { 38 | int m = sc.nextInt(); 39 | int[][] a = new int[m][m]; 40 | for ( int j = 0; j < m; j++ ) { 41 | for ( int k = 0; k < m; k++ ) { 42 | a[j][k] = sc.nextInt(); 43 | } 44 | } 45 | list.add( matrixScore( a ) ); 46 | } 47 | for ( Integer i : list 48 | ) { 49 | System.out.println( i ); 50 | } 51 | } 52 | 53 | } 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/dailyExercise/skillsContest/Main3.java: -------------------------------------------------------------------------------- 1 | package dailyExercise.skillsContest; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * @ClassName: Main3 7 | * @Description: 8 | * @author: dk 9 | * @date: 2021/11/27 11:50 上午 10 | */ 11 | 12 | public class Main3 { 13 | 14 | public static void main( String[] args ) { 15 | Scanner sc = new Scanner( System.in ); 16 | String s1 = sc.nextLine(); 17 | String s2 = sc.nextLine(); 18 | System.out.println( isScramble( s1, s2 ) ); 19 | } 20 | 21 | 22 | public static boolean isScramble( String s1, String s2 ) { 23 | if ( s1.length() != s2.length() ) { 24 | return false; 25 | } 26 | if ( s1.equals( s2 ) ) { 27 | return true; 28 | } 29 | 30 | int[] a = new int[26]; 31 | for ( int i = 0; i < s1.length(); i++ ) { 32 | a[s1.charAt( i ) - 'a']++; 33 | a[s2.charAt( i ) - 'a']--; 34 | } 35 | 36 | for ( int i = 0; i < 26; i++ ) { 37 | if ( a[i] != 0 ) { 38 | return false; 39 | } 40 | } 41 | 42 | for ( int i = 1; i < s1.length(); i++ ) { 43 | if ( isScramble( s1.substring( 0, i ), s2.substring( 0, i ) ) 44 | && isScramble( s1.substring( i ), s2.substring( i ) ) ) { 45 | return true; 46 | } 47 | if ( isScramble( s1.substring( i ), s2.substring( 0, s2.length() - i ) ) 48 | && 49 | isScramble( s1.substring( 0, i ), s2.substring( s2.length() - i ) ) 50 | ) { 51 | return true; 52 | } 53 | } 54 | return false; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/dailyStudy/TrieTreeModle.java: -------------------------------------------------------------------------------- 1 | package dailyStudy; 2 | 3 | /** 4 | * @ClassName: TrieTreeModle 5 | * @Description: 前缀树模版 6 | * @author: dk 7 | * @date: 2022/4/23 2:35 下午 8 | */ 9 | 10 | public class TrieTreeModle { 11 | 12 | public static class TrieNode { 13 | public int path; 14 | public int end; 15 | public TrieNode[] nexts; 16 | 17 | public TrieNode() { 18 | path = 0; //有多少个结点到达过 19 | end = 0; //有多少个字符串以这个结点结尾 20 | nexts = new TrieNode[26]; //通向子节点的路,如果题目所给的范围不确定就用map 21 | } 22 | } 23 | 24 | 25 | public static class Trie { 26 | 27 | private TrieNode root; 28 | 29 | 30 | public Trie() { 31 | //准备一个头结点 32 | root = new TrieNode(); 33 | } 34 | 35 | 36 | //将一个单词插入 37 | public void insert( String word ) { 38 | if ( word == null ) { 39 | return; 40 | } 41 | char[] chs = word.toCharArray(); 42 | TrieNode node = root; 43 | int index = 0; 44 | for ( int i = 0; i < chs.length; i++ ) { 45 | index = chs[i] - 'a'; 46 | if ( node.nexts[index] == null ) { 47 | node.nexts[index] = new TrieNode(); 48 | } 49 | node = node.nexts[index]; 50 | node.path++; 51 | } 52 | node.end++; 53 | } 54 | 55 | 56 | //在结构中删除这个单词 57 | public void delete( String word ) { 58 | if ( search( word ) != 0 ) { 59 | char[] chs = word.toCharArray(); 60 | TrieNode node = root; 61 | int index = 0; 62 | for ( int i = 0; i < chs.length; i++ ) { 63 | index = chs[i] - 'a'; 64 | if ( --node.nexts[index].path == 0 ) { 65 | //如果某个结点-1之后==0,则说明此节点之后的结点也是-1之后==0,因此直接=null即可。 66 | node.nexts[index] = null; 67 | return; 68 | } 69 | node = node.nexts[index]; 70 | } 71 | node.end--; 72 | } 73 | } 74 | 75 | 76 | //查找某个单词插入了几次 77 | public int search( String word ) { 78 | if ( word == null ) { 79 | return 0; 80 | } 81 | char[] chs = word.toCharArray(); 82 | TrieNode node = root; 83 | int index = 0; 84 | for ( int i = 0; i < chs.length; i++ ) { 85 | index = chs[i] - 'a'; 86 | if ( node.nexts[index] == null ) { 87 | return 0; 88 | } 89 | node = node.nexts[index]; 90 | } 91 | return node.end; 92 | } 93 | 94 | 95 | //查某个字符串前缀数量是多少 96 | public int prefixNumber( String pre ) { 97 | if ( pre == null ) { 98 | return 0; 99 | } 100 | char[] chs = pre.toCharArray(); 101 | TrieNode node = root; 102 | int index = 0; 103 | for ( int i = 0; i < chs.length; i++ ) { 104 | index = chs[i] - 'a'; 105 | if ( node.nexts[index] == null ) { 106 | return 0; 107 | } 108 | node = node.nexts[index]; 109 | } 110 | return node.path; 111 | } 112 | 113 | } 114 | 115 | 116 | public static void main( String[] args ) { 117 | Trie trie = new Trie(); 118 | System.out.println( trie.search( "zuo" ) ); 119 | trie.insert( "zuo" ); 120 | System.out.println( trie.search( "zuo" ) ); 121 | trie.delete( "zuo" ); 122 | System.out.println( trie.search( "zuo" ) ); 123 | trie.insert( "zuo" ); 124 | trie.insert( "zuo" ); 125 | trie.delete( "zuo" ); 126 | System.out.println( trie.search( "zuo" ) ); 127 | trie.delete( "zuo" ); 128 | System.out.println( trie.search( "zuo" ) ); 129 | trie.insert( "zuoa" ); 130 | trie.insert( "zuoac" ); 131 | trie.insert( "zuoab" ); 132 | trie.insert( "zuoad" ); 133 | trie.delete( "zuoa" ); 134 | System.out.println( trie.search( "zuoa" ) ); 135 | System.out.println( trie.prefixNumber( "zuo" ) ); 136 | 137 | } 138 | 139 | } 140 | --------------------------------------------------------------------------------