├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── notes ├── array.md ├── backTrack.md ├── bdInterview.md ├── design.md ├── dp.md ├── findTable.md ├── graph.md ├── greedy.md ├── linkedList.md ├── math.md ├── plan.md ├── queue.md ├── sql.md ├── stack.md ├── string.md ├── tencentInterview.md ├── top100.md ├── topInterview.md └── tree.md ├── pict ├── array_01.png ├── array_02.png ├── dp_01.png ├── find_01.png ├── find_03.png ├── find_04.png ├── find_05.png ├── linkedList_01.png ├── linkedList_02.png ├── linkedList_03.png ├── question_11.jpg ├── queue_01.png ├── queue_02.png ├── queue_03.png ├── queue_05.png ├── s17.png ├── stack_01.png ├── stack_02.png └── stack_03.png └── src ├── InterviewTest.java ├── Main.java ├── array ├── Solution11.java ├── Solution125.java ├── Solution128.java ├── Solution162.java ├── Solution167.java ├── Solution169.java ├── Solution179.java ├── Solution189.java ├── Solution209.java ├── Solution215.java ├── Solution229.java ├── Solution238.java ├── Solution239.java ├── Solution240.java ├── Solution26.java ├── Solution268.java ├── Solution27.java ├── Solution278.java ├── Solution28.java ├── Solution283.java ├── Solution287.java ├── Solution3.java ├── Solution324.java ├── Solution33.java ├── Solution334.java ├── Solution34.java ├── Solution344.java ├── Solution345.java ├── Solution35.java ├── Solution374.java ├── Solution4.java ├── Solution41.java ├── Solution42.java ├── Solution434.java ├── Solution438.java ├── Solution442.java ├── Solution48.java ├── Solution485.java ├── Solution54.java ├── Solution56.java ├── Solution59.java ├── Solution674.java ├── Solution704.java ├── Solution713.java ├── Solution717.java ├── Solution728.java ├── Solution73.java ├── Solution747.java ├── Solution75.java ├── Solution76.java ├── Solution80.java ├── Solution81.java ├── Solution852.java └── Solution88.java ├── backTrack ├── Solution10.java ├── Solution130.java ├── Solution131.java ├── Solution17.java ├── Solution200.java ├── Solution216.java ├── Solution22.java ├── Solution329.java ├── Solution37.java ├── Solution39.java ├── Solution40.java ├── Solution401.java ├── Solution417.java ├── Solution46.java ├── Solution47.java ├── Solution473.java ├── Solution51.java ├── Solution52.java ├── Solution690.java ├── Solution695.java ├── Solution733.java ├── Solution77.java ├── Solution78.java ├── Solution784.java ├── Solution79.java ├── Solution797.java ├── Solution89.java ├── Solution90.java └── Solution93.java ├── design ├── Solution146.java ├── Solution155.java ├── Solution225.java ├── Solution232.java ├── Solution384.java └── Solution432.java ├── dp ├── Fibonacci.java ├── LCS.java ├── Solution118.java ├── Solution119.java ├── Solution120.java ├── Solution121.java ├── Solution123.java ├── Solution139.java ├── Solution152.java ├── Solution188.java ├── Solution198.java ├── Solution213.java ├── Solution221.java ├── Solution279.java ├── Solution300.java ├── Solution309.java ├── Solution322.java ├── Solution337.java ├── Solution343.java ├── Solution354.java ├── Solution376.java ├── Solution377.java ├── Solution416.java ├── Solution435.java ├── Solution474.java ├── Solution494.java ├── Solution5.java ├── Solution518.java ├── Solution53.java ├── Solution600.java ├── Solution62.java ├── Solution63.java ├── Solution64.java ├── Solution647.java ├── Solution70.java ├── Solution714.java ├── Solution72.java ├── Solution85.java ├── Solution873.java ├── Solution91.java └── knapsack │ ├── Solution1.java │ └── Solution2.java ├── find ├── Solution1.java ├── Solution136.java ├── Solution137.java ├── Solution149.java ├── Solution15.java ├── Solution16.java ├── Solution18.java ├── Solution202.java ├── Solution204.java ├── Solution205.java ├── Solution217.java ├── Solution219.java ├── Solution220.java ├── Solution242.java ├── Solution260.java ├── Solution290.java ├── Solution299.java ├── Solution349.java ├── Solution350.java ├── Solution409.java ├── Solution447.java ├── Solution451.java ├── Solution454.java ├── Solution49.java ├── Solution719.java ├── Solution771.java ├── Solution804.java ├── Solution811.java ├── Solution819.java ├── Solution890.java └── Solution893.java ├── graph ├── Solution207.java ├── Solution210.java └── Solution785.java ├── greedy ├── Solution122.java ├── Solution134.java ├── Solution392.java ├── Solution435.java ├── Solution455.java ├── Solution55.java ├── Solution860.java └── Solution861.java ├── linkedList ├── LinkedListUtils.java ├── ListNode.java ├── Solution141.java ├── Solution142.java ├── Solution143.java ├── Solution147.java ├── Solution148.java ├── Solution160.java ├── Solution19.java ├── Solution2.java ├── Solution203.java ├── Solution206.java ├── Solution21.java ├── Solution234.java ├── Solution237.java ├── Solution24.java ├── Solution25.java ├── Solution328.java ├── Solution445.java ├── Solution61.java ├── Solution725.java ├── Solution817.java ├── Solution82.java ├── Solution83.java ├── Solution86.java ├── Solution876.java ├── Solution92.java └── Test.java ├── math ├── Solution12.java ├── Solution13.java ├── Solution231.java ├── Solution263.java ├── Solution29.java ├── Solution371.java ├── Solution50.java ├── Solution60.java ├── Solution66.java ├── Solution69.java ├── Solution7.java └── Solution754.java ├── other ├── Solution292.java └── Solution547.java ├── queue ├── Solution102.java ├── Solution103.java ├── Solution107.java ├── Solution126.java ├── Solution127.java ├── Solution199.java ├── Solution23.java ├── Solution279.java ├── Solution347.java ├── Solution621.java ├── Solution622.java ├── Solution933.java └── TreeNode.java ├── segTree └── Solution303.java ├── stack ├── Solution133.java ├── Solution144.java ├── Solution145.java ├── Solution150.java ├── Solution20.java ├── Solution227.java ├── Solution71.java ├── Solution84.java ├── Solution856.java ├── Solution901.java ├── Solution94.java └── TreeNode.java ├── string ├── Solution14.java ├── Solution151.java ├── Solution214.java ├── Solution38.java ├── Solution387.java ├── Solution389.java ├── Solution415.java ├── Solution43.java ├── Solution541.java ├── Solution557.java ├── Solution567.java ├── Solution58.java ├── Solution8.java └── Solution9.java ├── tree ├── CompeteTree.java ├── Solution100.java ├── Solution101.java ├── Solution104.java ├── Solution105.java ├── Solution106.java ├── Solution108.java ├── Solution109.java ├── Solution110.java ├── Solution111.java ├── Solution112.java ├── Solution113.java ├── Solution114.java ├── Solution124.java ├── Solution129.java ├── Solution173.java ├── Solution222.java ├── Solution226.java ├── Solution230.java ├── Solution235.java ├── Solution236.java ├── Solution257.java ├── Solution404.java ├── Solution437.java ├── Solution450.java ├── Solution530.java ├── Solution543.java ├── Solution572.java ├── Solution617.java ├── Solution654.java ├── Solution863.java ├── Solution865.java ├── Solution872.java ├── Solution889.java ├── Solution894.java ├── Solution897.java ├── Solution95.java ├── Solution96.java ├── Solution98.java ├── Solution99.java ├── TreeNode.java └── TreeNodeUtils.java ├── trie ├── Solution208.java └── Solution211.java └── utils ├── ArrayUtils.java ├── LinkedListUtils.java ├── ListNode.java └── TreeNodeUtils.java /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /out/** 2 | *.class 3 | *.iml 4 | /.idea/** 5 | *.xml 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ivan Lu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /pict/array_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/array_01.png -------------------------------------------------------------------------------- /pict/array_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/array_02.png -------------------------------------------------------------------------------- /pict/dp_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/dp_01.png -------------------------------------------------------------------------------- /pict/find_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/find_01.png -------------------------------------------------------------------------------- /pict/find_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/find_03.png -------------------------------------------------------------------------------- /pict/find_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/find_04.png -------------------------------------------------------------------------------- /pict/find_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/find_05.png -------------------------------------------------------------------------------- /pict/linkedList_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/linkedList_01.png -------------------------------------------------------------------------------- /pict/linkedList_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/linkedList_02.png -------------------------------------------------------------------------------- /pict/linkedList_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/linkedList_03.png -------------------------------------------------------------------------------- /pict/question_11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/question_11.jpg -------------------------------------------------------------------------------- /pict/queue_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/queue_01.png -------------------------------------------------------------------------------- /pict/queue_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/queue_02.png -------------------------------------------------------------------------------- /pict/queue_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/queue_03.png -------------------------------------------------------------------------------- /pict/queue_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/queue_05.png -------------------------------------------------------------------------------- /pict/s17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/s17.png -------------------------------------------------------------------------------- /pict/stack_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/stack_01.png -------------------------------------------------------------------------------- /pict/stack_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/stack_02.png -------------------------------------------------------------------------------- /pict/stack_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IvanLu1024/LeetCode/a09090cee9906cb424beb00fe359c0dcc25f4251/pict/stack_03.png -------------------------------------------------------------------------------- /src/array/Solution11.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。 7 | * 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 8 | * 9 | * 说明:你不能倾斜容器,且 n 的值至少为 2。 10 | * 11 | * 示例: 12 | * 13 | * 输入: [1,8,6,2,5,4,8,3,7] 14 | * 输出: 49 15 | */ 16 | public class Solution11 { 17 | public int maxArea(int[] height) { 18 | int l=0,h=height.length-1; 19 | int max=0; 20 | while (l='a'&&c<='z'){ 38 | return true; 39 | } 40 | if (c>='A'&&c<='Z'){ 41 | return true; 42 | } 43 | if (c>='0'&&c<='9'){ 44 | return true; 45 | } 46 | return false; 47 | } 48 | @Test 49 | public void test(){ 50 | String s="A man, a plan, a canal: Panama"; 51 | boolean res = isPalindrome(s); 52 | System.out.println(res); 53 | 54 | 55 | } 56 | 57 | 58 | 59 | 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/array/Solution128.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | 给定一个未排序的整数数组,找出最长连续序列的长度。 10 | 11 | 要求算法的时间复杂度为 O(n)。 12 | 13 | 示例: 14 | 15 | 输入: [100, 4, 200, 1, 3, 2] 16 | 输出: 4 17 | 解释: 最长连续序列是 [1, 2, 3, 4]。它的长度为 4。 18 | 19 | */ 20 | public class Solution128 { 21 | public int longestConsecutive(int[] nums) { 22 | if (nums==null||nums.length==0){ 23 | return 0; 24 | } 25 | //K:num,V:连续序列的长度 26 | Map map=new HashMap<>(); 27 | int maxLen=0; 28 | for(int num:nums){ 29 | //当前是新加入的数字的时候 30 | if (!map.containsKey(num)){ 31 | //左右的相邻数字 32 | int left=map.getOrDefault(num-1,0); 33 | int right=map.getOrDefault(num+1,0); 34 | //计算当前连续序列的长度 35 | int len=left+right+1; 36 | maxLen=Math.max(len,maxLen); 37 | map.put(num,len); 38 | //更新左右边界 39 | map.put(num-left,len); 40 | map.put(num+right,len); 41 | } 42 | } 43 | return maxLen; 44 | } 45 | @Test 46 | public void test(){ 47 | int[] nums={1,2,1,0}; 48 | int i = longestConsecutive(nums); 49 | System.out.println(i); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/array/Solution162.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 峰值元素是指其值大于左右相邻值的元素。 7 | * 8 | * 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。 9 | * 10 | * 数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。 11 | * 12 | * 你可以假设 nums[-1] = nums[n] = -∞。 13 | * 14 | * 示例 1: 15 | * 16 | * 输入: nums = [1,2,3,1] 17 | * 输出: 2 18 | * 解释: 3 是峰值元素,你的函数应该返回其索引 2。 19 | * 示例 2: 20 | * 21 | * 输入: nums = [1,2,1,3,5,6,4] 22 | * 输出: 1 或 5 23 | * 解释: 你的函数可以返回索引 1,其峰值元素为 2; 24 | * 或者返回索引 5, 其峰值元素为 6。 25 | * 说明: 26 | * 27 | * 你的解法应该是 O(logN) 时间复杂度的。 28 | * 29 | */ 30 | public class Solution162 { 31 | public int findPeakElement(int[] nums) { 32 | int l=0,r=nums.length-1; 33 | int mid=l+(r-l)/2; 34 | while (l<=r){ 35 | //当搜索区域只有一个元素的时候直接返回 36 | if (l==r){ 37 | return l; 38 | } 39 | //将搜索区域移动到较大的区域中搜索 40 | if (nums[mid]nums[i-1]&&nums[i]>nums[i+1]){ 53 | return i; 54 | } 55 | } 56 | return nums[0]>nums[nums.length-1]?0:nums.length-1; 57 | } 58 | 59 | @Test 60 | public void test(){ 61 | int[] nums={2,1}; 62 | int i = findPeakElement(nums); 63 | System.out.println(i); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/array/Solution167.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 输入: numbers = [2, 7, 11, 15], target = 9 7 | 输出: [1,2] 8 | 9 | 解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。 10 | 11 | 思路:对撞指针 12 | * 13 | */ 14 | public class Solution167 { 15 | 16 | 17 | public int[] twoSum(int[] numbers, int target) { 18 | int l=0,h=numbers.length-1; 19 | int[] res = new int[2]; 20 | while (lnums.length/2) 58 | return majortiy; 59 | else return 0; 60 | 61 | } 62 | @Test 63 | public void test(){ 64 | int[] nums={2,2,1,1,1,2,2}; 65 | int i = majorityElement(nums); 66 | System.out.println(i); 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/array/Solution179.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | import java.util.Comparator; 7 | 8 | public class Solution179 { 9 | private class my implements Comparator{ 10 | @Override 11 | public int compare(String i1, String i2) { 12 | String s1 = i1 + i2; 13 | String s2 = i2 + i1; 14 | return s2.compareTo(s1); 15 | } 16 | } 17 | 18 | public String largestNumber(int[] nums) { 19 | String[] snums=new String[nums.length]; 20 | for (int i = 0; i < nums.length; i++) { 21 | snums[i]=String.valueOf(nums[i]); 22 | } 23 | Arrays.sort(snums,new my()); 24 | StringBuilder sb=new StringBuilder(); 25 | for (int i = 0; i < nums.length; i++) { 26 | sb.append(snums[i]); 27 | } 28 | String res = sb.toString(); 29 | if (res.charAt(0)=='0'){ 30 | return "0"; 31 | } 32 | return res; 33 | } 34 | @Test 35 | public void test(){ 36 | int[] nums={999999998,999999997,999999999}; 37 | String s = largestNumber(nums); 38 | System.out.println(s); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/array/Solution209.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。 7 | * 8 | * 如果不存在符合条件的连续子数组,返回 0。 9 | 示例: 10 | 11 | 输入: s = 7, nums = [2,3,1,2,4,3] 12 | 输出: 2 13 | 解释: 子数组 [4,3] 是该条件下的长度最小的连续子数组。 14 | * 15 | */ 16 | public class Solution209 { 17 | 18 | public int minSubArrayLen(int s, int[] nums) { 19 | int i=0,j=-1;//滑动窗口num[i,j],由于初始化的时候没有数值,所以j=-1 20 | int sum=0; 21 | int minCount=nums.length+1; 22 | while (i=s){ 29 | if (j-i+1 pq=new PriorityQueue<>(Comparator.reverseOrder()); 17 | for (int i = 0; i <= n; i++) { 18 | if (i<=r){ 19 | pq.offer(nums[i]); 20 | }else if (i<=n-1){ 21 | res[i-k]=pq.peek(); 22 | r++; 23 | pq.remove(nums[l++]); 24 | pq.offer(nums[r]); 25 | }else { 26 | res[i-k]=pq.peek(); 27 | } 28 | } 29 | return res; 30 | } 31 | @Test 32 | public void test(){ 33 | int[] nums={1,3,-1,-3,5,3,6,7}; 34 | int k=3; 35 | int[] res = maxSlidingWindow(nums, k); 36 | for (int i:res){ 37 | System.out.print(i+","); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/array/Solution26.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 实例: 7 | * 给定 nums = [0,0,1,1,1,2,2,3,3,4], 8 | * 9 | * 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。 10 | * 11 | * 你不需要考虑数组中超出新长度后面的元素。 12 | * 13 | */ 14 | public class Solution26 { 15 | 16 | public int removeDuplicates(int[] nums) { 17 | if (nums == null || nums.length == 0) 18 | return 0; 19 | int count = 0; 20 | for (int i = 1; i < nums.length; i++) { 21 | if (nums[i - 1] != nums[i]) 22 | nums[count++] = nums[i - 1]; 23 | 24 | 25 | } 26 | nums[count]=nums[nums.length-1]; 27 | return count+1; 28 | 29 | } 30 | 31 | public int removeDuplicates1(int[] nums){ 32 | if (nums!=null&&nums.length!=0){ 33 | int cur=0; 34 | for (int i=1;i false 21 | * 调用 isBadVersion(5) -> true 22 | * 调用 isBadVersion(4) -> true 23 | * 24 | * 所以,4 是第一个错误的版本。 25 | * 26 | */ 27 | public class Solution278 { 28 | public int firstBadVersion(int n) { 29 | int l=1,r=n; 30 | int res=n; 31 | while (lhaystack.length()){ 31 | return -1; 32 | } 33 | char[] hChars = haystack.toCharArray(); 34 | char[] nChars = needle.toCharArray(); 35 | //i:表示母串中的子串的起始位置下标 36 | for (int i = 0; i <=hChars.length-nChars.length ; i++) { 37 | //j:子串的起始位置下标 38 | int j=0; 39 | //j=0:确保每次循环都是从needle的头开始 40 | for (j = 0; j num2>num1,即存在三元组 26 | return true; 27 | } 28 | } 29 | return false; 30 | } 31 | @Test 32 | public void test(){ 33 | int[] nums={1,2,3,4,5}; 34 | boolean b = increasingTriplet(nums); 35 | System.out.println(b); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/array/Solution344.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | import java.util.Collections; 7 | 8 | /** 9 | * 编写一个函数,其作用是将输入的字符串反转过来。 10 | * 11 | * 示例 1: 12 | * 13 | * 输入: "hello" 14 | * 输出: "olleh" 15 | * 16 | */ 17 | public class Solution344 { 18 | 19 | public String reverseString(String s) { 20 | if (s==null){ 21 | return null; 22 | } 23 | char[] chars = s.toCharArray(); 24 | int l=0,h=chars.length-1; 25 | while (ltarget){ 27 | h=mid-1; 28 | }else { 29 | l=mid+1; 30 | } 31 | } 32 | for (int i = 0; i < nums.length; i++) { 33 | if (nums[i]>=target){ 34 | return i; 35 | } 36 | } 37 | return nums.length; 38 | } 39 | @Test 40 | public void test(){ 41 | int[] nums={1,3,5,6}; 42 | int t=5; 43 | int i = searchInsert(nums, t); 44 | System.out.println(i); 45 | 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/array/Solution374.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | /** 4 | * 我们正在玩一个猜数字游戏。 游戏规则如下: 5 | * 我从 1 到 n 选择一个数字。 你需要猜我选择了哪个数字。 6 | * 每次你猜错了,我会告诉你这个数字是大了还是小了。 7 | * 你调用一个预先定义好的接口 guess(int num),它会返回 3 个可能的结果(-1,1 或 0): 8 | * 9 | * -1 : 我的数字比较小 10 | * 1 : 我的数字比较大 11 | * 0 : 恭喜!你猜对了! 12 | * 示例 : 13 | * 14 | * 输入: n = 10, pick = 6 15 | * 输出: 6 16 | * 17 | */ 18 | public class Solution374 { 19 | public int guessNumber(int n) { 20 | int l=0,h=n; 21 | while (l<=h){ 22 | int mid=l+(h-l)/2; 23 | int res = guess(mid); 24 | if (res==0){ 25 | return mid; 26 | }else if (res==-1){ 27 | h=mid-1; 28 | }else { 29 | l=mid+1; 30 | } 31 | } 32 | return -1; 33 | 34 | 35 | } 36 | private int guess(int num){ 37 | 38 | return 0; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/array/Solution41.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | 给定一个未排序的整数数组,找出其中没有出现的最小的正整数。 7 | 8 | 示例 1: 9 | 10 | 输入: [1,2,0] 11 | 输出: 3 12 | 示例 2: 13 | 14 | 输入: [3,4,-1,1] 15 | 输出: 2 16 | 示例 3: 17 | 18 | 输入: [7,8,9,11,12] 19 | 输出: 1 20 | 说明: 21 | 22 | 你的算法的时间复杂度应为O(n),并且只能使用常数级别的空间。 23 | 24 | 25 | * @create 2019-02-16 15:20 26 | **/ 27 | public class Solution41 { 28 | public int firstMissingPositive(int[] nums) { 29 | if (nums==null||nums.length==0){ 30 | return 0; 31 | } 32 | //遍历一遍数组将数组中的元素数组大于0 33 | // 并且小于等于数组长度的元素放置到数值减一下标对应的位置上 34 | for (int i = 0; i 0&&nums[i]<=nums.length&&nums[nums[i]-1]!=nums[i]){ 36 | int temp=nums[nums[i]-1]; 37 | nums[nums[i]-1]=nums[i]; 38 | nums[i]=temp; 39 | }else { 40 | i++; 41 | } 42 | } 43 | //再遍历一遍数组,若数组下标和数值不是对应的是数值相差为1的话, 44 | // 那么此时就是答案,若遍历完都没有结果则答案为数组长度加1 45 | for (int i = 0; i < nums.length; i++) { 46 | if (nums[i]!=i+1){ 47 | return i+1; 48 | } 49 | } 50 | return nums.length+1; 51 | } 52 | @Test 53 | public void test(){ 54 | int[] nums={7,8,9,11,12}; 55 | int i = firstMissingPositive(nums); 56 | System.out.println(i); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/array/Solution42.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 7 | 8 | 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。 9 | 10 | 示例: 11 | 12 | 输入: [0,1,0,2,1,0,1,3,2,1,2,1] 13 | 输出: 6 14 | 15 | 16 | */ 17 | public class Solution42 { 18 | public int trap(int[] height) { 19 | int n = height.length; 20 | if (n==0){ 21 | return 0; 22 | } 23 | int[] left,right; 24 | left=new int[n]; 25 | right=new int[n]; 26 | //先初始化左边界 27 | for (int i = 1; i < n; i++) { 28 | left[i]=Math.max(height[i-1],left[i-1]); 29 | } 30 | //初始化右边界 31 | for (int i = n-2; i >=0 ; i--) { 32 | right[i]=Math.max(height[i+1],right[i+1]); 33 | } 34 | int water=0; 35 | //计算雨水量,计算height[1,n-2]的范围,因为两边不能累积雨水 36 | for (int i = 1; i < n-1; i++) { 37 | int h=Math.min(left[i],right[i]); 38 | //累积雨水,当存在高度差的时候就可以累积雨水 39 | water+=Math.max(0,h-height[i]); 40 | } 41 | return water; 42 | } 43 | @Test 44 | public void test(){ 45 | int[] height={0,1,0,2,1,0,1,3,2,1,2,1}; 46 | int res = trap(height); 47 | System.out.println(res); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/array/Solution434.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 统计字符串中的单词个数,这里的单词指的是连续的不是空格的字符。 7 | * 8 | * 请注意,你可以假定字符串里不包括任何不可打印的字符。 9 | * 10 | * 示例: 11 | * 12 | * 输入: "Hello, my name is John" 13 | * 输出: 5 14 | * 15 | */ 16 | public class Solution434 { 17 | 18 | public int countSegments(String s) { 19 | int count=0; 20 | int start=0; 21 | if (s.length()==0||s==null){ 22 | return count; 23 | } 24 | //搜索起始位置 25 | while (start findAnagrams(String s, String p) { 34 | int[] pFreq=new int[26]; 35 | int[] sFreq=new int[26]; 36 | List res=new ArrayList(); 37 | //首先统计p中出现的字符频率 38 | int pLen = p.length(); 39 | for (int i=0;i=pLen){ 45 | sFreq[s.charAt(i-pLen)-'a']--; 46 | } 47 | if (Arrays.equals(sFreq,pFreq)){ 48 | res.add(i-pLen+1); 49 | } 50 | 51 | } 52 | return res; 53 | 54 | } 55 | @Test 56 | public void test(){ 57 | List list = findAnagrams("cbaebabacd", "abc"); 58 | for (Integer i:list){ 59 | System.out.println(i); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/array/Solution442.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashSet; 7 | import java.util.List; 8 | import java.util.Set; 9 | 10 | /** 11 | * 给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次。 12 | 13 | 找到所有出现两次的元素。 14 | 15 | 你可以不用到任何额外空间并在O(n)时间复杂度内解决这个问题吗? 16 | 17 | 示例: 18 | 19 | 输入: 20 | [4,3,2,7,8,2,3,1] 21 | 22 | 输出: 23 | [2,3] 24 | * 25 | */ 26 | public class Solution442 { 27 | //使用set的解法 28 | public List findDuplicates(int[] nums) { 29 | Set set = new HashSet<>(); 30 | List res = new ArrayList<>(); 31 | for (int i:nums){ 32 | if (!set.contains(i)){ 33 | set.add(i); 34 | }else { 35 | res.add(i); 36 | } 37 | } 38 | return res; 39 | } 40 | 41 | //**其中1 ≤ a[i] ≤ n (n为数组长度)** 42 | // 43 | public List findDuplicates1(int[] nums){ 44 | List res = new ArrayList<>(); 45 | if (nums==null||nums.length==0){ 46 | return res; 47 | } 48 | for (int i = 0; i < nums.length; i++) { 49 | //记录出现过的元素,将其作为数组的下标 50 | //将该下标的元素转变为其相反数 51 | int index = Math.abs(nums[i]) - 1; 52 | //若当前下标对应的数值小于0则说明该元素已经出现过了,记录到集合中。 53 | if (nums[index]<0){ 54 | res.add(index+1); 55 | }else { 56 | nums[index]=-nums[index]; 57 | } 58 | } 59 | return res; 60 | } 61 | @Test 62 | public void test(){ 63 | int[] nums={4,3,2,7,7,7,2,3,1}; 64 | List res = findDuplicates1(nums); 65 | System.out.println(res); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/array/Solution59.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | import utils.ArrayUtils; 5 | 6 | /** 7 | * 给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。 8 | * 9 | * 示例: 10 | * 11 | * 输入: 3 12 | * 输出: 13 | * [ 14 | * [ 1, 2, 3 ], 15 | * [ 8, 9, 4 ], 16 | * [ 7, 6, 5 ] 17 | * ] 18 | */ 19 | public class Solution59 { 20 | int[][] d={{0,1},{1,0},{0,-1},{-1,0}}; 21 | private int M,N; 22 | public int[][] generateMatrix(int n) { 23 | int[][] matrix=new int[n][n]; 24 | int curX=0,curY=0,curD=0; 25 | int i=1; 26 | M=n; 27 | N=n; 28 | while (i<=n*n){ 29 | if (matrix[curX][curY]==0){ 30 | matrix[curX][curY]=i++; 31 | } 32 | int newX = curX + d[curD][0]; 33 | int newY = curY + d[curD][1]; 34 | if (inArea(newX,newY)&&matrix[newX][newY]==0){ 35 | curX=newX; 36 | curY=newY; 37 | }else { 38 | curD=(curD+1)%4; 39 | } 40 | } 41 | return matrix; 42 | 43 | } 44 | 45 | private boolean inArea(int x,int y){ 46 | return 0<=x&&x>1; 34 | if (nums[mid]==target){ 35 | return mid; 36 | } 37 | else if (nums[mid]=k){ 54 | return false; 55 | } 56 | } 57 | return true; 58 | } 59 | @Test 60 | public void test(){ 61 | int[] nums={10,5,2,6}; 62 | int k=100; 63 | int res = numSubarrayProductLessThanK(nums, k); 64 | System.out.println(res); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/array/Solution717.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | public class Solution717 { 6 | //使用贪心策略:如果遇到1就将其当做2比特,若最后一位也当做2比特的话,i=n 7 | public boolean isOneBitCharacter(int[] bits) { 8 | int n = bits.length; 9 | int i = 0; 10 | for (; i < n-1; ) { 11 | if (bits[i]==1){ 12 | i+=2; 13 | }else { 14 | i++; 15 | } 16 | } 17 | return i==n-1; 18 | } 19 | 20 | //从倒数第二个位置开始看连续1的数量,如果为奇数个表明最后一位0要和倒数第二位组成2比特(10) 21 | //如果是偶数个,则前面的这些1可以组成若干个2比特,最后一位组成1比特 22 | public boolean isOneBitCharacter1(int[] bits){ 23 | int n = bits.length; 24 | int count=0; 25 | for (int i = n-2; i >=0; i--) { 26 | if (bits[i]==1){ 27 | count++; 28 | }else { 29 | break; 30 | } 31 | } 32 | return count%2==0; 33 | } 34 | @Test 35 | public void test(){ 36 | int[] bits={1, 1, 1, 0}; 37 | boolean res = isOneBitCharacter(bits); 38 | System.out.println(res); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/array/Solution728.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * 自除数 是指可以被它包含的每一位数除尽的数。 10 | * 11 | * 例如,128 是一个自除数,因为 128 % 1 == 0,128 % 2 == 0,128 % 8 == 0。 12 | * 13 | * 还有,自除数不允许包含 0 。 14 | * 15 | * 给定上边界和下边界数字,输出一个列表,列表的元素是边界(含边界)内所有的自除数。 16 | * 17 | * 示例 1: 18 | * 19 | * 输入: 20 | * 上边界left = 1, 下边界right = 22 21 | * 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 15, 22] 22 | * 注意: 23 | * 24 | * 每个输入参数的边界满足 1 <= left <= right <= 10000。 25 | * 26 | */ 27 | public class Solution728 { 28 | public List selfDividingNumbers(int left, int right) { 29 | List res=new ArrayList<>(); 30 | for (int i = left; i <=right ; i++) { 31 | if (isSelfDividing(i)){ 32 | res.add(i); 33 | } 34 | } 35 | return res; 36 | } 37 | //判断是否为自除数 38 | private boolean isSelfDividing(int n){ 39 | if (n<10){ 40 | return true; 41 | } 42 | int nexN=n; 43 | while (nexN>0){ 44 | //取出各位的值 45 | int i=nexN%10; 46 | //包含0 47 | if (i==0){ 48 | return false; 49 | } 50 | //不满足条件 51 | if (n%i!=0){ 52 | return false; 53 | } 54 | nexN=nexN/10; 55 | } 56 | return true; 57 | } 58 | @Test 59 | public void test(){ 60 | boolean flag = isSelfDividing(10000); 61 | System.out.println(flag); 62 | 63 | int left=1; 64 | int right=10000; 65 | List list = selfDividingNumbers(left, right); 66 | System.out.println(list); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/array/Solution747.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 在一个给定的数组nums中,总是存在一个最大元素 。 7 | * 8 | * 查找数组中的最大元素是否至少是数组中每个其他数字的两倍。 9 | * 10 | * 如果是,则返回最大元素的索引,否则返回-1。 11 | * 12 | * 示例 1: 13 | * 14 | * 输入: nums = [3, 6, 1, 0] 15 | * 输出: 1 16 | * 解释: 6是最大的整数, 对于数组中的其他整数, 17 | * 6大于数组中其他元素的两倍。6的索引是1, 所以我们返回1. 18 | * 19 | * 20 | * 示例 2: 21 | * 22 | * 输入: nums = [1, 2, 3, 4] 23 | * 输出: -1 24 | * 解释: 4没有超过3的两倍大, 所以我们返回 -1. 25 | * 26 | * 27 | * 提示: 28 | * 29 | * nums 的长度范围在[1, 50]. 30 | * 每个 nums[i] 的整数范围在 [0, 99]. 31 | * 32 | */ 33 | public class Solution747 { 34 | public int dominantIndex(int[] nums) { 35 | int index=0; 36 | for (int i = 1; i < nums.length; i++) { 37 | if (nums[i]>nums[index]){ 38 | index=i; 39 | } 40 | } 41 | for (int i = 0; i < nums.length; i++) { 42 | if (i==index) 43 | continue; 44 | if (nums[index]>=2*nums[i]) 45 | continue; 46 | else { 47 | return -1; 48 | } 49 | } 50 | return index; 51 | } 52 | @Test 53 | public void test(){ 54 | int[] nums={1, 2, 3, 4}; 55 | int i = dominantIndex(nums); 56 | System.out.println(i); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/array/Solution80.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 26题的变式 7 | * 8 | * 给定 nums = [0,0,1,1,1,1,2,3,3], 9 | * 10 | * 函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。 11 | * 12 | * 你不需要考虑数组中超出新长度后面的元素。 13 | * 14 | */ 15 | public class Solution80 { 16 | 17 | public int removeDuplicates(int[] nums) { 18 | if (nums!=null&&nums.length!=0){ 19 | int cur=0,count=1; 20 | for (int i=1;inums[count-2]) 46 | nums[count++]=num; 47 | 48 | } 49 | return count; 50 | 51 | 52 | 53 | } 54 | else 55 | return 0; 56 | 57 | } 58 | 59 | 60 | 61 | @Test 62 | public void test() { 63 | int[] ints = {0,0,1,1,1,1,2,3,3}; 64 | int i = removeDuplicates1(ints); 65 | System.out.println(i); 66 | for (int t : ints) { 67 | System.out.print(t + " "); 68 | } 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/array/Solution852.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 我们把符合下列属性的数组 A 称作山脉: 7 | * 8 | * A.length >= 3 9 | * 存在 0 < i < A.length - 1 使得A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1] 10 | * 给定一个确定为山脉的数组,返回任何满足 A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1] 的 i 的值。 11 | * 12 | * 13 | * 14 | * 示例 1: 15 | * 16 | * 输入:[0,1,0] 17 | * 输出:1 18 | * 示例 2: 19 | * 20 | * 输入:[0,2,1,0] 21 | * 输出:1 22 | * 23 | * 24 | * 提示: 25 | * 26 | * 3 <= A.length <= 10000 27 | * 0 <= A[i] <= 10^6 28 | * A 是如上定义的山脉 29 | * 30 | * 31 | */ 32 | public class Solution852 { 33 | //对撞指针法 34 | public int peakIndexInMountainArray(int[] A) { 35 | int l=0,r=A.length-1; 36 | while (lA[mid+1]){ 53 | return mid; 54 | } 55 | //峰值在右侧部分 56 | if (A[mid-1]>A[mid]){ 57 | r=mid; 58 | }else { 59 | l=mid; 60 | } 61 | mid=l+(r-l)/2; 62 | } 63 | return mid; 64 | 65 | } 66 | @Test 67 | public void test(){ 68 | /* 1,2,3,4,5,3,2,1*/ 69 | int[] nums={0,2,1,0 }; 70 | int i = peakIndexInMountainArray1(nums); 71 | System.out.println(i); 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/array/Solution88.java: -------------------------------------------------------------------------------- 1 | package array; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 示例: 7 | 8 | 输入: 9 | nums1 = [1,2,3,0,0,0], m = 3 10 | nums2 = [2,5,6], n = 3 11 | 12 | 输出: [1,2,2,3,5,6] 13 | * 14 | */ 15 | 16 | public class Solution88 { 17 | private int[] aux; 18 | 19 | 20 | public void merge(int[] nums1, int m, int[] nums2, int n) { 21 | if (nums2.length==0||nums1.length==0) 22 | return; 23 | if (nums1.length==1) 24 | nums1[0]=nums2[0]; 25 | 26 | int index1=m-1,index2=n-1; 27 | int last=m+n-1; 28 | 29 | 30 | while (index1>=0&&index2>=0){ 31 | if (nums1[index1]=0){ 40 | nums1[last--]=nums2[index2--]; 41 | } 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | } 52 | @Test 53 | public void test(){ 54 | int[] nums1 = {1,2,3,0,0,0}; 55 | int[] nums2 = {2,5,6}; 56 | merge(nums1,3,nums2,3); 57 | for (int i:nums1){ 58 | System.out.print(i+" "); 59 | } 60 | 61 | } 62 | 63 | 64 | 65 | 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/backTrack/Solution131.java: -------------------------------------------------------------------------------- 1 | package backTrack; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class Solution131 { 9 | private List> res=new ArrayList<>(); 10 | public List> partition(String s) { 11 | if (s==null||s.length()==0){ 12 | return res; 13 | } 14 | generatePart(s,0,new ArrayList<>()); 15 | return res; 16 | 17 | } 18 | private void generatePart(String s,int index,List list){ 19 | if (index==s.length()){ 20 | System.out.println("completed is:"+list); 21 | res.add(new ArrayList<>(list)); 22 | return; 23 | } 24 | for (int i = index; i < s.length(); i++) { 25 | if (isHuiwen(s,index,i)){ 26 | System.out.println("current Huiwen:"+s.substring(index,i+1)+"->"+list); 27 | list.add(s.substring(index,i+1)); 28 | //下次递归从i+1开始搜索 29 | generatePart(s,i+1,list); 30 | list.remove(list.size()-1); 31 | System.out.println("backTracking...list:"+list); 32 | } 33 | 34 | } 35 | } 36 | 37 | private boolean isHuiwen(String s,int l,int h){ 38 | while (l=0&&s.charAt(l++)!=s.charAt(h--)){ 40 | return false; 41 | } 42 | } 43 | return true; 44 | } 45 | @Test 46 | public void test(){ 47 | String s="aab"; 48 | List> r = partition(s); 49 | System.out.println(r); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/backTrack/Solution17.java: -------------------------------------------------------------------------------- 1 | package backTrack; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。 10 | * 11 | * 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 12 | * 13 | * 示例: 14 | * 15 | * 输入:"23" 16 | * 输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]. 17 | * 说明: 18 | * 尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。 19 | * 20 | */ 21 | public class Solution17 { 22 | 23 | private String letterMap[] = { 24 | " ", //0 25 | "", //1 26 | "abc", //2 27 | "def", //3 28 | "ghi", //4 29 | "jkl", //5 30 | "mno", //6 31 | "pqrs", //7 32 | "tuv", //8 33 | "wxyz" //9 34 | }; 35 | 36 | private List res; 37 | 38 | private void findCombination(String digits, int index, String s){ 39 | if (digits.length()==index){ 40 | res.add(s); 41 | return; 42 | } 43 | 44 | char c = digits.charAt(index); 45 | String letters = letterMap[c - '0']; 46 | for (int i = 0; i < letters.length(); i++) { 47 | findCombination(digits,index+1,s+letters.charAt(i)); 48 | } 49 | } 50 | public List letterCombinations(String digits) { 51 | res=new ArrayList<>(); 52 | if (digits.equals("")){ 53 | return res; 54 | } 55 | findCombination(digits,0,""); 56 | return res; 57 | } 58 | @Test 59 | public void test(){ 60 | String digits="23"; 61 | List re = letterCombinations(digits); 62 | System.out.println(re); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/backTrack/Solution216.java: -------------------------------------------------------------------------------- 1 | package backTrack; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * 找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。 10 | 11 | 说明: 12 | 13 | 所有数字都是正整数。 14 | 解集不能包含重复的组合。 15 | 示例 1: 16 | 17 | 输入: k = 3, n = 7 18 | 输出: [[1,2,4]] 19 | 示例 2: 20 | 21 | 输入: k = 3, n = 9 22 | 输出: [[1,2,6], [1,3,5], [2,3,4]] 23 | */ 24 | public class Solution216 { 25 | private List> res=new ArrayList<>(); 26 | public List> combinationSum3(int k, int n) { 27 | if (k==0||n==0){ 28 | return res; 29 | } 30 | generate(k,n,0,1,new ArrayList<>()); 31 | return res; 32 | 33 | } 34 | private void generate(int k,int target,int index,int start,List list){ 35 | if (index==k&&target==0){ 36 | res.add(new ArrayList<>(list)); 37 | return; 38 | } 39 | for (int i = start; i <= 9; i++) { 40 | if (i<=target){ 41 | list.add(i); 42 | generate(k,target-i,index+1,i+1,list); 43 | list.remove(list.size()-1); 44 | } 45 | } 46 | } 47 | @Test 48 | public void test(){ 49 | int k=3; 50 | int n=15; 51 | List> lists = combinationSum3(k, n); 52 | /*[[1,5,9],[1,6,8],[2,4,9],[2,5,8],[2,6,7],[3,4,8],[3,5,7],[4,5,6]]*/ 53 | System.out.println(lists); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/backTrack/Solution22.java: -------------------------------------------------------------------------------- 1 | package backTrack; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Stack; 8 | 9 | /** 10 | * 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。 11 | * 12 | * 例如,给出 n = 3,生成结果为: 13 | * 14 | * [ 15 | * "((()))", 16 | * "(()())", 17 | * "(())()", 18 | * "()(())", 19 | * "()()()" 20 | * ] 21 | * 22 | */ 23 | public class Solution22 { 24 | private List res; 25 | //回溯法 26 | public List generateParenthesis(int n) { 27 | res=new ArrayList<>(); 28 | generate(n,n,""); 29 | return res; 30 | } 31 | //left:剩余的左括号的数量 32 | //right:剩余的右括号的数量 33 | private void generate(int left,int right,String s){ 34 | if (left==0&&right==0){ 35 | System.out.println("finished : "+s); 36 | res.add(s); 37 | return; 38 | } 39 | //填充左括号 40 | if (left>0){ 41 | System.out.println("add left -> "+s); 42 | generate(left-1,right,s+"("); 43 | } 44 | //当前的左括号数量大于当前的右括号的数量的时候,填充右括号 45 | if (left "+s); 47 | generate(left,right-1,s+")"); 48 | } 49 | } 50 | @Test 51 | public void test(){ 52 | int n=3; 53 | List list = generateParenthesis(n); 54 | System.out.println(list); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/backTrack/Solution329.java: -------------------------------------------------------------------------------- 1 | package backTrack; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * @Author Ivan 16:06 7 | * @Description TODO 8 | */ 9 | public class Solution329 { 10 | private int[][] d={{-1,0},{0,1},{1,0},{0,-1}}; 11 | private int m,n; 12 | private int maxLen=0; 13 | private int[][] visited; 14 | 15 | public int longestIncreasingPath(int[][] matrix) { 16 | m = matrix.length; 17 | if (m==0){ 18 | return 0; 19 | } 20 | n = matrix[0].length; 21 | visited=new int[m][n]; 22 | for (int i = 0; i < m; i++) { 23 | for (int j = 0; j < n; j++) { 24 | if (visited[i][j]!=0) continue; 25 | dfs(matrix,i,j); 26 | } 27 | } 28 | return maxLen; 29 | } 30 | 31 | private int dfs(int[][] matrix,int x,int y){ 32 | if (visited[x][y]!=0){ 33 | return visited[x][y]; 34 | } 35 | 36 | visited[x][y]=1; 37 | for (int i = 0; i < 4; i++) { 38 | int x1=x+d[i][0]; 39 | int y1=y+d[i][1]; 40 | if (inArea(x1,y1)&&matrix[x][y]=0&&x=0&&y subordinates; 17 | }; 18 | 19 | //K:id;V:Employee 20 | private Map importanceMap=new HashMap<>(); 21 | public int getImportance(List employees, int id) { 22 | for (Employee e:employees){ 23 | importanceMap.put(e.id,e); 24 | } 25 | return dfs(id); 26 | } 27 | 28 | //深度遍历 29 | private int dfs(int id){ 30 | int res = importanceMap.get(id).importance; 31 | for (Integer sid:importanceMap.get(id).subordinates){ 32 | res+=dfs(sid); 33 | } 34 | return res; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/backTrack/Solution77.java: -------------------------------------------------------------------------------- 1 | package backTrack; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * 给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。 10 | 11 | 示例: 12 | 13 | 输入: n = 4, k = 2 14 | 输出: 15 | [ 16 | [2,4], 17 | [3,4], 18 | [2,3], 19 | [1,2], 20 | [1,3], 21 | [1,4], 22 | ] 23 | * 24 | * @author 25 | * @create 2018-11-24 14:51 26 | **/ 27 | public class Solution77 { 28 | private List> res=new ArrayList<>(); 29 | public List> combine(int n, int k) { 30 | if (n<=0||n c=new ArrayList<>(); 34 | generateCombine(n,k,1,c); 35 | return res; 36 | 37 | } 38 | 39 | private void generateCombine(int n, int k, int start, List c) { 40 | if (c.size()==k){ 41 | System.out.println("Completed "+c); 42 | res.add(new ArrayList<>(c)); 43 | return; 44 | } 45 | //此时有(k-c.size())个空位需要填充,那么[i...n]中至少要有(k-c.size())个元素 46 | //则n-i>=(k-c.size())-1确保[i...n]中至少要有(k-c.size())个元素 47 | // --> i<=n-(k-c.size())+1 48 | for (int i = start; i <=n-(k-c.size())+1; i++) { 49 | c.add(i); 50 | System.out.println(i+"-> c:"+c); 51 | generateCombine(n,k,i+1,c); 52 | c.remove(c.size()-1); 53 | System.out.println("backTracking..."+c); 54 | } 55 | } 56 | @Test 57 | public void test(){ 58 | int n=4,k=4; 59 | List> r = combine(n, k); 60 | System.out.println(r); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/backTrack/Solution78.java: -------------------------------------------------------------------------------- 1 | package backTrack; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | *给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。 10 | 11 | 说明:解集不能包含重复的子集。 12 | 13 | 示例: 14 | 15 | 输入: nums = [1,2,3] 16 | 输出: 17 | [ 18 | [3], 19 | [1], 20 | [2], 21 | [1,2,3], 22 | [1,3], 23 | [2,3], 24 | [1,2], 25 | [] 26 | ] 27 | * 28 | */ 29 | public class Solution78 { 30 | private List> res=new ArrayList<>(); 31 | public List> subsets(int[] nums) { 32 | if (nums==null||nums.length==0){ 33 | return res; 34 | } 35 | generate(nums,0,new ArrayList<>()); 36 | return res; 37 | 38 | } 39 | private void generate(int[] nums,int index,List list){ 40 | //当满足条件就加入结果的集合中,确保子集的长度不超过原始集合 41 | if (index<=nums.length){ 42 | System.out.println(list+"-> res"); 43 | res.add(new ArrayList<>(list)); 44 | } 45 | for (int i = index; i "+list); 48 | generate(nums,i+1,list); 49 | list.remove(list.size()-1); 50 | System.out.println("backTracking..."+list); 51 | } 52 | return; 53 | } 54 | @Test 55 | public void test(){ 56 | int[] nums={1,2,3}; 57 | List> subsets = subsets(nums); 58 | System.out.println(subsets); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/backTrack/Solution797.java: -------------------------------------------------------------------------------- 1 | package backTrack; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class Solution797 { 9 | //典型的回溯法来求解 10 | public List> allPathsSourceTarget(int[][] graph) { 11 | List> res=new ArrayList<>(); 12 | List list=new ArrayList<>(); 13 | list.add(0); 14 | generate(graph,0,list,res); 15 | return res; 16 | } 17 | 18 | //生成结果 19 | private void generate(int[][] graph, int index, List list,List> res){ 20 | 21 | //若搜索到终点的时候,此时将可行的解加入集合中 22 | if (index==graph.length-1){ 23 | res.add(new ArrayList<>(list)); 24 | } 25 | //从当前位置可达的位置中进行搜索 26 | for (int i = 0; i > res = allPathsSourceTarget(graph); 39 | System.out.println(res); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/backTrack/Solution90.java: -------------------------------------------------------------------------------- 1 | package backTrack; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | public class Solution90 { 10 | private List> res=new ArrayList<>(); 11 | 12 | public List> subsetsWithDup(int[] nums) { 13 | if (nums==null||nums.length==0){ 14 | return res; 15 | } 16 | Arrays.sort(nums); 17 | generate(nums,0,new ArrayList<>()); 18 | return res; 19 | } 20 | 21 | private void generate(int[] nums,int index,List list){ 22 | //当满足条件就加入结果的集合中,确保子集的长度不超过原始集合 23 | if (index<=nums.length){ 24 | res.add(new ArrayList<>(list)); 25 | } 26 | for (int i = index; i index&&nums[i]==nums[i-1]){ 29 | continue; 30 | } 31 | list.add(nums[i]); 32 | generate(nums,i+1,list); 33 | list.remove(list.size()-1); 34 | } 35 | return; 36 | } 37 | 38 | @Test 39 | public void test(){ 40 | int[] nums={1,2,2}; 41 | List> subsets = subsetsWithDup(nums); 42 | System.out.println(subsets); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/design/Solution225.java: -------------------------------------------------------------------------------- 1 | package design; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | public class Solution225 { 7 | 8 | class MyStack { 9 | 10 | Queue queue; 11 | /** Initialize your data structure here. */ 12 | public MyStack() { 13 | queue =new LinkedList<>(); 14 | } 15 | 16 | /** Push element x onto stack. */ 17 | //将入队顺序逆序 18 | public void push(int x) { 19 | queue.offer(x); 20 | for (int i = 0; i < queue.size() - 1; i++) { 21 | queue.offer(queue.poll()); 22 | } 23 | } 24 | 25 | /** Removes the element on top of the stack and returns that element. */ 26 | public int pop() { 27 | return queue.poll(); 28 | } 29 | 30 | /** Get the top element. */ 31 | public int top() { 32 | return queue.peek(); 33 | } 34 | 35 | /** Returns whether the stack is empty. */ 36 | public boolean empty() { 37 | return queue.isEmpty(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/design/Solution384.java: -------------------------------------------------------------------------------- 1 | package design; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * @Author Ivan 15:22 7 | * @Description TODO 8 | */ 9 | public class Solution384 { 10 | 11 | class Solution { 12 | private int[] nums; 13 | private int[] cloneNums; 14 | private int len; 15 | private Random random; 16 | 17 | public Solution(int[] nums) { 18 | this.len=nums.length; 19 | this.cloneNums=nums.clone(); 20 | this.nums=nums; 21 | this.random=new Random(); 22 | } 23 | 24 | /** Resets the array to its original configuration and return it. */ 25 | public int[] reset() { 26 | return this.nums; 27 | } 28 | 29 | /** Returns a random shuffling of the array. */ 30 | public int[] shuffle() { 31 | for(int i=len-1;i>=0;i--){ 32 | int j = random.nextInt(i+1); 33 | swap(cloneNums,j,i); 34 | } 35 | return cloneNums; 36 | 37 | } 38 | private void swap(int[] nums,int i,int j){ 39 | int t = nums[i]; 40 | nums[i] = nums[j]; 41 | nums[j] = t; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/dp/Fibonacci.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | import java.util.Date; 7 | 8 | public class Fibonacci { 9 | 10 | //原始写法 11 | public int Fi(int n){ 12 | if (n==0){ 13 | return 0; 14 | } 15 | if (n==1){ 16 | return 1; 17 | } 18 | return Fi(n-1)+Fi(n-2); 19 | } 20 | 21 | //带有记忆化搜索 22 | private int[] memo; 23 | public int Fi1(int n){ 24 | if (n==0){ 25 | return 0; 26 | } 27 | if (n==1){ 28 | return 1; 29 | } 30 | if (memo[n]==-1){ 31 | memo[n]=Fi1(n-1)+Fi1(n-2); 32 | return memo[n]; 33 | } 34 | 35 | return memo[n]; 36 | } 37 | 38 | //自底向上 39 | public int Fi2(int n){ 40 | int[] m=new int[n+1]; 41 | m[0]=0; 42 | m[1]=1; 43 | for (int i = 2; i <=n ; i++) { 44 | m[i]=m[i-1]+m[i-2]; 45 | 46 | } 47 | return m[n]; 48 | } 49 | 50 | @Test 51 | public void test(){ 52 | int n=43; 53 | memo= new int[n+1]; 54 | Arrays.fill(memo,-1); 55 | long start = System.currentTimeMillis(); 56 | int r = Fi2(n); 57 | long end = System.currentTimeMillis(); 58 | System.out.println("result:"+r+" costs "+(end-start)); 59 | 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/dp/LCS.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * @Author Ivan 15:21 7 | * @Description TODO 8 | */ 9 | public class LCS { 10 | 11 | public int lengthOfLCS(String s1,String s2){ 12 | int m = s1.length(); 13 | int n = s2.length(); 14 | if(m==0||n==0){ 15 | return 0; 16 | } 17 | int[][] memo = new int[m+1][n+1]; 18 | char[] chars1 = s1.toCharArray(); 19 | char[] chars2 = s2.toCharArray(); 20 | for(int i=1;i<=m;i++){ 21 | for(int j=1;j<=n;j++){ 22 | if(chars1[i-1]==chars2[j-1]){ 23 | memo[i][j]=1+memo[i-1][j-1]; 24 | }else{ 25 | memo[i][j]=Math.max(memo[i-1][j],memo[i][j-1]); 26 | } 27 | } 28 | } 29 | int len = memo[m][n]; 30 | return len; 31 | } 32 | @Test 33 | public void test(){ 34 | String s1= "ABCDbb"; 35 | String s2= "AEECDvb"; 36 | int i = lengthOfLCS(s1, s2); 37 | char[] chars = s1.toCharArray(); 38 | System.out.println(i); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/dp/Solution118.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | public class Solution118 { 10 | public List> generate(int numRows) { 11 | List> res=new ArrayList<>(); 12 | if (numRows<=0){ 13 | return res; 14 | } 15 | res.add(Arrays.asList(new Integer[]{1})); 16 | for (int i = 1; i < numRows; i++) { 17 | List row=new ArrayList<>(); 18 | row.add(1); 19 | for (int j = 1; j > res = generate(rows); 31 | System.out.println(res); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/dp/Solution119.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | 9 | public class Solution119 { 10 | public List getRow(int rowIndex) { 11 | int[][] memo=new int[rowIndex+1][rowIndex+1]; 12 | List res=new ArrayList<>(); 13 | memo[0][0]=1; 14 | if (rowIndex<0){ 15 | return res; 16 | } 17 | for (int i = 1; i <= rowIndex; i++) { 18 | memo[i][0]=1; 19 | for (int j = 1; j getRow1(int rowIndex) { 33 | int[] memo=new int[rowIndex+1]; 34 | List res=new ArrayList<>(); 35 | memo[0]=1; 36 | if (rowIndex<0){ 37 | return res; 38 | } 39 | for (int i = 1; i <= rowIndex; i++) { 40 | //必须从右到左进行递推,不然会造成中间结果的丢失 41 | for (int j = i; j >=1 ; j--) { 42 | memo[j]=memo[j-1]+memo[j]; 43 | } 44 | } 45 | for (int i = 0; i <= rowIndex; i++) { 46 | res.add(memo[i]); 47 | } 48 | 49 | return res; 50 | } 51 | @Test 52 | public void test(){ 53 | int rowIndex=3; 54 | List row = getRow1(rowIndex); 55 | System.out.println(row); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/dp/Solution123.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * @author 7 | * @create 2018-12-05 21:44 8 | **/ 9 | public class Solution123 { 10 | public int maxProfit(int[] prices) { 11 | int n=prices.length; 12 | if (n==0||n==1){ 13 | return 0; 14 | } 15 | //第一次交易 16 | int hold1=Integer.MIN_VALUE; 17 | int unhold1=0; 18 | //第二次交易 19 | int hold2=Integer.MIN_VALUE; 20 | int unhold2=0; 21 | for (int i = 0; i < n; i++) { 22 | hold1=Math.max(hold1,-prices[i]); 23 | unhold1=Math.max(unhold1,hold1+prices[i]); 24 | hold2=Math.max(hold2,unhold1-prices[i]); 25 | unhold2=Math.max(unhold2,hold2+prices[i]); 26 | } 27 | return unhold2; 28 | } 29 | 30 | @Test 31 | public void test(){ 32 | int[] p={3,3,5,0,0,3,1,4}; 33 | int r = maxProfit(p); 34 | System.out.println(r); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/dp/Solution152.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | 给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。 7 | 8 | 示例 1: 9 | 10 | 输入: [2,3,-2,4] 11 | 输出: 6 12 | 解释: 子数组 [2,3] 有最大乘积 6。 13 | 示例 2: 14 | 15 | 输入: [-2,0,-1] 16 | 输出: 0 17 | 解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。 18 | 19 | */ 20 | public class Solution152 { 21 | public int maxProduct(int[] nums) { 22 | if (nums==null||nums.length==0){ 23 | return 0; 24 | } 25 | int max=1,min=1; 26 | int res=Integer.MIN_VALUE; 27 | for (int i = 0; i < nums.length; i++) { 28 | //若当前数值为负数则将最大值和最小值数值交换,以便得到更大的乘积 29 | if (nums[i]<0){ 30 | max=max^min; 31 | min=max^min; 32 | max=max^min; 33 | } 34 | max=Math.max(max*nums[i],nums[i]); 35 | min=Math.min(min*nums[i],nums[i]); 36 | 37 | res=Math.max(res,max); 38 | } 39 | return res; 40 | } 41 | @Test 42 | public void test(){ 43 | int[] nums={2,3,-2,4}; 44 | int i = maxProduct(nums); 45 | System.out.println(i); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/dp/Solution188.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | 7 | public class Solution188 { 8 | //122题+123题 9 | public int maxProfit(int k, int[] prices) { 10 | int n=prices.length; 11 | if (n==0||n==1||k==0){ 12 | return 0; 13 | } 14 | //当2k>n,相当于可以进行不限次数的交易 15 | //退化为122题 16 | if (k>n/2){ 17 | return maxProfit(prices); 18 | } 19 | int[] holds=new int[k]; 20 | int[] unholds=new int[k]; 21 | Arrays.fill(holds,Integer.MIN_VALUE); 22 | Arrays.fill(unholds,0); 23 | for (int i = 0; i < n; i++) { 24 | for (int j = 0; j < k; j++) { 25 | unholds[j] = Math.max(unholds[j], holds[j] + prices[i]); 26 | if (j==0){ 27 | holds[j]=Math.max(holds[j],-prices[i]); 28 | }else { 29 | holds[j] = Math.max(holds[j], unholds[j-1] - prices[i]); 30 | } 31 | } 32 | } 33 | return Math.max(unholds[k-1],holds[k-1]); 34 | } 35 | 36 | private int maxProfit(int[] prices){ 37 | int n=prices.length; 38 | if (n==0||n==1){ 39 | return 0; 40 | } 41 | int res=0; 42 | for (int i = 1; i prices[i-1]){ 44 | res+=prices[i]-prices[i-1]; 45 | } 46 | } 47 | return res; 48 | } 49 | @Test 50 | public void test(){ 51 | int[] p={3,3,5,0,0,3,1,4}; 52 | int k=2; 53 | int r = maxProfit(k, p); 54 | System.out.println(r); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/dp/Solution213.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * @author 7 | * @create 2018-12-04 21:31 8 | **/ 9 | public class Solution213 { 10 | //与198题类似,相当于做两次抢劫,一次的范围是[0,n-2], 11 | // 另一次的范围是[1,n-1],取两次抢劫的最大值即可 12 | public int rob(int[] nums) { 13 | if(nums==null||nums.length==0) 14 | return 0; 15 | int n=nums.length; 16 | if(n==1) 17 | return nums[0]; 18 | if(n==2) 19 | return Math.max(nums[0],nums[1]); 20 | int res=Math.max(rob(nums,0,n-2),rob(nums,1,n-1)); 21 | return res; 22 | } 23 | //抢劫:起始点为l,终点为h的最大收益 24 | private int rob(int[] nums,int l,int h){ 25 | int[] memo=new int[h-l+1]; 26 | memo[0]=nums[l]; 27 | memo[1]=Math.max(nums[l],nums[l+1]); 28 | for(int i=2;i<=h-l;i++){ 29 | memo[i]=Math.max(nums[i+l]+memo[i-2],memo[i-1]); 30 | } 31 | return memo[h-l]; 32 | } 33 | @Test 34 | public void test(){ 35 | int[] nums={2,3,2}; 36 | int res = rob(nums); 37 | System.out.println(res); 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/dp/Solution279.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import org.junit.Test; 4 | 5 | import java.lang.ref.PhantomReference; 6 | import java.util.Arrays; 7 | 8 | /** 9 | * 给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。 10 | * 11 | * 示例 1: 12 | * 13 | * 输入: n = 12 14 | * 输出: 3 15 | * 解释: 12 = 4 + 4 + 4. 16 | * 示例 2: 17 | * 18 | * 输入: n = 13 19 | * 输出: 2 20 | * 解释: 13 = 4 + 9. 21 | * 22 | */ 23 | public class Solution279 { 24 | private int[] memo; 25 | public int numSquares(int n) { 26 | memo=new int[n+1]; 27 | Arrays.fill(memo,-1); 28 | return findNumSquares(n); 29 | } 30 | private int findNumSquares(int n){ 31 | if (n==0){ 32 | return 0; 33 | } 34 | if (memo[n]!=-1){ 35 | return memo[n]; 36 | } 37 | 38 | int min=Integer.MAX_VALUE; 39 | for (int i = 1; n-i*i>=0; i++) { 40 | min=Math.min(min,1+findNumSquares(n-i*i)); 41 | } 42 | memo[n]=min; 43 | return min; 44 | } 45 | 46 | public int numSquares1(int n){ 47 | if (n==0){ 48 | return 0; 49 | } 50 | memo=new int[n+1]; 51 | Arrays.fill(memo,Integer.MAX_VALUE); 52 | memo[0]=0; 53 | for (int i = 1; i <= n; i++) { 54 | for (int j = 1; i-j*j>=0 ; j++) { 55 | memo[i]=Math.min(memo[i],1+memo[i-j*j]); 56 | } 57 | } 58 | return memo[n]; 59 | } 60 | 61 | @Test 62 | public void test(){ 63 | int n=13; 64 | int i = numSquares1(n); 65 | System.out.println(i); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/dp/Solution309.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​ 7 | * 8 | * 设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票): 9 | * 10 | * 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 11 | * 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。 12 | * 示例: 13 | * 14 | * 输入: [1,2,3,0,2] 15 | * 输出: 3 16 | * 解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出] 17 | * 18 | */ 19 | public class Solution309 { 20 | public int maxProfit(int[] prices) { 21 | int n=prices.length; 22 | if (n<=1){ 23 | return 0; 24 | } 25 | int[] hold=new int[n]; //hold[i]:第i天持有股票的最大收益 26 | int[] unhold=new int[n]; //unhold[i]:第i天不持有股票的最大收益 27 | 28 | 29 | hold[0]=-prices[0]; 30 | hold[1]=Math.max(hold[0],-prices[1]); 31 | unhold[1]=Math.max(unhold[0],hold[0]+prices[1]); 32 | for (int i = 2; i < n; i++) { 33 | //没有买入和买入 34 | hold[i] = Math.max(hold[i-1], unhold[i-2] - prices[i]); 35 | //没有卖出和卖出 36 | unhold[i] = Math.max(unhold[i-1], hold[i-1] + prices[i]); 37 | 38 | } 39 | return unhold[n-1]; 40 | } 41 | @Test 42 | public void test(){ 43 | int[] p={1,2,3,0,2}; 44 | int r = maxProfit(p); 45 | System.out.println(r); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/dp/Solution337.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import org.junit.Test; 4 | import tree.TreeNode; 5 | import tree.TreeNodeUtils; 6 | 7 | 8 | public class Solution337 { 9 | 10 | 11 | public int rob(TreeNode root) { 12 | return tryRob(root,true); 13 | 14 | } 15 | 16 | private int tryRob(TreeNode root,boolean include){ 17 | if (root==null){ 18 | return 0; 19 | } 20 | 21 | //不选择当前结点 22 | int res=tryRob(root.right,true)+tryRob(root.left,true); 23 | if (include){ 24 | //选择当前结点 25 | res=Math.max(res,root.val+tryRob(root.left,false)+tryRob(root.right,false)); 26 | } 27 | return res; 28 | } 29 | 30 | public int rob1(TreeNode root) { 31 | int[] res = tryRob(root); 32 | return Math.max(res[0],res[1]); 33 | 34 | } 35 | 36 | //res[0]:不选择根节点的最大收益,res[1]:选择根节点的最大收益 37 | private int[] tryRob(TreeNode root){ 38 | if (root==null){ 39 | return new int[2]; 40 | } 41 | int[] leftResult = tryRob(root.left); 42 | int[] rightResult = tryRob(root.right); 43 | int[] res=new int[2]; 44 | 45 | //下标为0,表示不选当前结点的最大收益 46 | res[0]=Math.max(leftResult[1],leftResult[0])+Math.max(rightResult[1],rightResult[0]); 47 | //下标为1,表示选择当前结点的最大收益 48 | res[1]=root.val+leftResult[0]+rightResult[0]; 49 | return res; 50 | } 51 | @Test 52 | public void test(){ 53 | int[] pre={3,2,3,3,1}; 54 | int[] in={2,3,3,3,1}; 55 | TreeNode root = TreeNodeUtils.ConstructBinaryTree(pre, in); 56 | int r = rob1(root); 57 | System.out.println(r); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/dp/Solution376.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。 7 | * 8 | * 例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 是正负交替出现的。相反, [1,4,7,2,5] 和 [1,7,4,5,5] 不是摆动序列, 9 | * 10 | * 第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。 11 | * 12 | * 给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。 13 | * 14 | * 示例 1: 15 | * 16 | * 输入: [1,7,4,9,2,5] 17 | * 输出: 6 18 | * 解释: 整个序列均为摆动序列。 19 | * 示例 2: 20 | * 21 | * 输入: [1,17,5,10,13,15,10,5,16,8] 22 | * 输出: 7 23 | * 解释: 这个序列包含几个长度为 7 摆动序列,其中一个可为[1,17,10,13,10,16,8]。 24 | * 示例 3: 25 | * 26 | * 输入: [1,2,3,4,5,6,7,8,9] 27 | * 输出: 2 28 | * 29 | */ 30 | public class Solution376 { 31 | 32 | public int wiggleMaxLength(int[] nums) { 33 | int n = nums.length; 34 | if (n==0||n==1){ 35 | return n; 36 | } 37 | int[] up=new int[n]; 38 | int[] down=new int[n]; 39 | up[0]=1; 40 | down[0]=1; 41 | for (int i = 1; i < n; i++) { 42 | if (nums[i]>nums[i-1]){ 43 | //上升的时候 44 | up[i]=down[i-1]+1; 45 | down[i]=down[i-1]; 46 | }else if (nums[i]>bitCount)>0){ 35 | bitCount++; 36 | } 37 | if ((num>>(bitCount-2))==3){ 38 | return fi(bitCount); 39 | }else { 40 | int mask=(1<<(bitCount-1))-1; 41 | return fi(bitCount-1)+findIntegers(num&mask); 42 | } 43 | } 44 | 45 | private int fi(int n){ 46 | if(n==0){ 47 | return 0; 48 | } 49 | if(n==1){ 50 | return 2; 51 | } 52 | if(n==2){ 53 | return 3; 54 | } 55 | int[] memo=new int[n+1]; 56 | memo[1]=2; 57 | memo[2]=3; 58 | for(int i=3;i<=n;i++){ 59 | memo[i]=memo[i-1]+memo[i-2]; 60 | } 61 | return memo[n]; 62 | } 63 | @Test 64 | public void test(){ 65 | int num=4; 66 | int res = findIntegers(num); 67 | System.out.println(res); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/dp/Solution62.java: -------------------------------------------------------------------------------- 1 | package dp; 2 | 3 | import org.junit.Test; 4 | 5 | public class Solution62 { 6 | public int uniquePaths(int m, int n) { 7 | if (m==0){ 8 | return 0; 9 | } 10 | int[][] memo=new int[m][n]; 11 | for (int i = 0; i < n; i++) { 12 | memo[0][i]=1; 13 | } 14 | for (int i = 0; i < m; i++) { 15 | memo[i][0]=1; 16 | } 17 | for (int i = 1; i =0; i--) { 46 | for (int j = i+2; j indexMap=new HashMap<>(); 12 | for (int i = 0; i < A.length; i++) { 13 | indexMap.put(A[i],i); 14 | } 15 | int res=0; 16 | int n =A.length; 17 | //表示从i到j的斐波那契子数列的长度 18 | int[][] memo=new int[n][n]; 19 | 20 | for (int i = n-1; i >=0 ; i--) { 21 | for (int j = i; j 1 9 | * 'B' -> 2 10 | * ... 11 | * 'Z' -> 26 12 | * 给定一个只包含数字的非空字符串,请计算解码方法的总数。 13 | * 14 | * 示例 1: 15 | * 16 | * 输入: "12" 17 | * 输出: 2 18 | * 解释: 它可以解码为 "AB"(1 2)或者 "L"(12)。 19 | * 示例 2: 20 | * 21 | * 输入: "226" 22 | * 输出: 3 23 | * 解释: 它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。 24 | * 25 | */ 26 | public class Solution91 { 27 | public int numDecodings(String s) { 28 | int n = s.length(); 29 | if (n==0){ 30 | return 0; 31 | } 32 | //memo[i]表示字符串s中下标为(i-1)的解码方法次数 33 | int[] memo=new int[n+1]; 34 | memo[0]=1; 35 | if (s.charAt(0)>'0'){ 36 | memo[1]=1; 37 | } 38 | char[] chars = s.toCharArray(); 39 | for (int i = 2; i <= n; i++) { 40 | int one = chars[i-1]-'0'; 41 | //如果一个字符满足(1-9)则记录 42 | if (one>0){ 43 | memo[i]+=memo[i-1]; 44 | } 45 | int two = 10*(chars[i-2]-'0')+(chars[i-1]-'0'); 46 | //如果两个字符满足(10-26)则记录 47 | if (two <= 26 && two >= 10) { 48 | memo[i] += memo[i - 2]; 49 | } 50 | 51 | } 52 | return memo[n]; 53 | } 54 | @Test 55 | public void test(){ 56 | String s="226"; 57 | int i = numDecodings(s); 58 | System.out.println(i); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/dp/knapsack/Solution1.java: -------------------------------------------------------------------------------- 1 | package dp.knapsack; 2 | 3 | public class Solution1 { 4 | 5 | //记忆化搜索 6 | private int[][] memo; 7 | public int knapsack(int[] w, int[] v, int C){ 8 | int n=w.length; 9 | if (n==0||C==0){ 10 | return 0; 11 | } 12 | memo=new int[n][C+1]; 13 | return bestValue(w,v,n-1,C); 14 | 15 | 16 | } 17 | 18 | // 用 [0...index]的物品,填充容积为c的背包的最大价值 19 | private int bestValue(int[] w,int[] v,int index,int C){ 20 | if (index<0||C<0){ 21 | return 0; 22 | } 23 | if (memo[index][C]!=-1){ 24 | return memo[index][C]; 25 | } 26 | 27 | //不选择当前物品的价值 28 | int res = bestValue(w, v, index - 1, C); 29 | if (w[index]<=C){ 30 | res=Math.max(res,v[index]+bestValue(w,v,index-1,C-w[index])); 31 | } 32 | memo[index][C]=res; 33 | return res; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/find/Solution1.java: -------------------------------------------------------------------------------- 1 | package find; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。 10 | 11 | 你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。 12 | 13 | 示例: 14 | 15 | 给定 nums = [2, 7, 11, 15], target = 9 16 | 17 | 因为 nums[0] + nums[1] = 2 + 7 = 9 18 | 所以返回 [0, 1] 19 | * 20 | * @author IvanLu 21 | * @create 2018-10-21 16:43 22 | **/ 23 | public class Solution1 { 24 | 25 | public int[] twoSum(int[] nums, int target) { 26 | int[] res = new int[2]; 27 | if (nums==null||nums.length==0){ 28 | return res; 29 | } 30 | //Key:nums[i]数值中的数值,Value:i,下标 31 | Map map = new HashMap<>(); 32 | for (int i = 0; i < nums.length; i++) { 33 | int com = target - nums[i]; 34 | //每次搜索当前的情况,避免了一次性放入所有的元素,导致覆盖了相同元素的下标 35 | if (map.containsKey(com)) { 36 | //获取到目标下标 37 | res[0] = map.get(com); 38 | res[1] = i; 39 | return res; 40 | } 41 | map.put(nums[i], i); 42 | } 43 | return res; 44 | } 45 | 46 | @Test 47 | public void test() { 48 | int[] nums1 = {2, 7, 11, 15}; 49 | int[] res = twoSum(nums1, 18); 50 | for (int i:res){ 51 | System.out.print(i+" "); 52 | } 53 | 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/find/Solution136.java: -------------------------------------------------------------------------------- 1 | package find; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 10 | * 11 | * 说明: 12 | * 13 | * 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 14 | * 15 | * 示例 1: 16 | * 17 | * 输入: [2,2,1] 18 | * 输出: 1 19 | * 示例 2: 20 | * 21 | * 输入: [4,1,2,1,2] 22 | * 输出: 4 23 | * 24 | */ 25 | public class Solution136 { 26 | //利用map 27 | public int singleNumber(int[] nums) { 28 | Map record=new HashMap<>(); 29 | for (int i = 0; i < nums.length; i++) { 30 | record.put(nums[i],record.getOrDefault(nums[i],0)+1); 31 | } 32 | int res=-1; 33 | for (Integer i:record.keySet()){ 34 | if (record.get(i)==1){ 35 | res=i; 36 | } 37 | } 38 | return res; 39 | } 40 | 41 | //利用异或运算的性质 42 | // ^:为异或运算(性质:对于任何数x,都有x^x=0,x^0=x) 43 | public int singleNumber1(int[] nums){ 44 | int res=0; 45 | for (int i : nums) { 46 | res^=i; 47 | } 48 | return res; 49 | } 50 | @Test 51 | public void test(){ 52 | int[] nums={2,2,1}; 53 | int i = singleNumber1(nums); 54 | System.out.println(i); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/find/Solution137.java: -------------------------------------------------------------------------------- 1 | package find; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。 10 | * 11 | * 说明: 12 | * 13 | * 你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗? 14 | * 15 | * 示例 1: 16 | * 17 | * 输入: [2,2,3,2] 18 | * 输出: 3 19 | * 示例 2: 20 | * 21 | * 输入: [0,1,0,1,0,1,99] 22 | * 输出: 99 23 | * 24 | */ 25 | public class Solution137 { 26 | public int singleNumber(int[] nums) { 27 | Map record=new HashMap<>(); 28 | for (int i = 0; i < nums.length; i++) { 29 | record.put(nums[i],record.getOrDefault(nums[i],0)+1); 30 | } 31 | int res=-1; 32 | for (Integer i:record.keySet()){ 33 | if (record.get(i)==1){ 34 | res=i; 35 | } 36 | } 37 | return res; 38 | } 39 | 40 | // 对int类型的每个数每一位单独统计出现1的次数, 如果出现的次数不能整除3 41 | // 则说明唯一存在的数在这一位上为1 42 | public int singleNumber1(int[] nums){ 43 | int res=0; 44 | for(int i=0;i<32;i++){ 45 | int bit=1<target){ 34 | h--; 35 | } 36 | else 37 | l++; 38 | } 39 | } 40 | } 41 | return res; 42 | } 43 | @Test 44 | public void test(){ 45 | int[] nums={-1,0,1,1,55}; 46 | int t=3; 47 | int res = threeSumClosest(nums, t); 48 | System.out.println(res); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/find/Solution202.java: -------------------------------------------------------------------------------- 1 | package find; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | /** 9 | * 编写一个算法来判断一个数是不是“快乐数”。 10 | * 11 | * 一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1, 12 | * 也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。 13 | * 14 | * 示例: 15 | * 16 | * 输入: 19 17 | * 输出: true 18 | * 解释: 19 | * 1^2 + 9^2 = 82 20 | * 8^2 + 2^2 = 68 21 | * 6^2 + 8^2 = 100 22 | * 1^2 + 0^2 + 0^2 = 1 23 | */ 24 | public class Solution202 { 25 | public boolean isHappy(int n) { 26 | if (n<1){ 27 | return false; 28 | } 29 | Set set=new HashSet<>(); 30 | while (!set.contains(n)){ 31 | if (n==1){ 32 | return true; 33 | } 34 | set.add(n); 35 | n=getHappy(n); 36 | } 37 | return false; 38 | } 39 | 40 | //使用快慢指针 41 | public boolean isHappy1(int n) { 42 | if(n<1){ 43 | return false; 44 | } 45 | int slow=n; 46 | int fast=n; 47 | do{ 48 | slow=getHappy(slow); 49 | fast=getHappy(getHappy(fast)); 50 | }while(fast!=slow); 51 | if(fast==1){ 52 | return true; 53 | } 54 | return false; 55 | } 56 | 57 | private int getHappy(int n) { 58 | int t,sum=0; 59 | while (n>0){ 60 | t=n%10; 61 | n/=10; 62 | sum+=t*t; 63 | } 64 | return sum; 65 | } 66 | @Test 67 | public void test(){ 68 | int n=11; 69 | boolean r = isHappy(n); 70 | System.out.println(r); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/find/Solution204.java: -------------------------------------------------------------------------------- 1 | package find; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | 7 | /** 8 | * 统计所有小于非负整数 n 的质数的数量。 9 | * 10 | * 示例: 11 | * 12 | * 输入: 10 13 | * 输出: 4 14 | * 解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。 15 | * 16 | */ 17 | public class Solution204 { 18 | //使用 埃拉托斯特尼筛法 19 | public int countPrimes(int n) { 20 | boolean[] memo=new boolean[n]; 21 | Arrays.fill(memo,true); 22 | for (int i = 2; i*i sMap=new HashMap<>(); 37 | for (int i = 0; i < s.length(); i++) { 38 | char sChar = s.charAt(i); 39 | char tChar = t.charAt(i); 40 | if (!sMap.containsKey(sChar)){ 41 | if (sMap.containsValue(tChar)){ 42 | return false; 43 | } 44 | sMap.put(sChar,tChar); 45 | }else { 46 | if (!sMap.get(sChar).equals(tChar)){ 47 | return false; 48 | } 49 | } 50 | } 51 | return true; 52 | } 53 | @Test 54 | public void test(){ 55 | String s="paper"; 56 | String t="title"; 57 | boolean b = isIsomorphic(s, t); 58 | System.out.println(b); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/find/Solution217.java: -------------------------------------------------------------------------------- 1 | package find; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.*; 6 | 7 | /** 8 | * 给定一个整数数组,判断是否存在重复元素。 9 | 10 | 如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。 11 | * @author 12 | * @create 2018-10-27 15:34 13 | **/ 14 | public class Solution217 { 15 | 16 | public boolean containsDuplicate(int[] nums) { 17 | Set record=new HashSet<>(); 18 | for (int i = 0; i < nums.length; i++) { 19 | if (record.contains(nums[i])){ 20 | return true; 21 | }else { 22 | record.add(nums[i]); 23 | } 24 | } 25 | return false; 26 | 27 | } 28 | public boolean containsDuplicate1(int[] nums) { 29 | List record=new ArrayList<>(); 30 | for (int i = 0; i < nums.length; i++) { 31 | if (record.contains(nums[i])){ 32 | return true; 33 | }else { 34 | record.add(nums[i]); 35 | } 36 | } 37 | return false; 38 | } 39 | 40 | //通过排序的方法 41 | public boolean containsDuplicate2(int[] nums){ 42 | Arrays.sort(nums); 43 | for (int i = 1; i < nums.length; i++) { 44 | if (nums[i]==nums[i-1]){ 45 | return true; 46 | } 47 | } 48 | return false; 49 | } 50 | 51 | @Test 52 | public void test(){ 53 | int[] nums={1,2,4,5,1}; 54 | int k=1; 55 | boolean res = containsDuplicate2(nums); 56 | System.out.println(res); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/find/Solution220.java: -------------------------------------------------------------------------------- 1 | package find; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | import java.util.TreeSet; 8 | 9 | /** 10 | * 示例 1: 11 | 12 | 输入: nums = [1,2,3,1], k = 3, t = 0 13 | 输出: true 14 | 示例 2: 15 | 16 | 输入: nums = [1,0,1,1], k = 1, t = 2 17 | 输出: true 18 | 示例 3: 19 | 20 | 输入: nums = [1,5,9,1,5,9], k = 2, t = 3 21 | 输出: false 22 | * 23 | * @author 24 | * @create 2018-10-27 21:46 25 | **/ 26 | public class Solution220 { 27 | public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { 28 | 29 | TreeSet record=new TreeSet<>(); 30 | for (int i = 0; i < nums.length; i++) { 31 | long n=nums[i]; 32 | if (record.ceiling(n)!=null&&record.ceiling(n)<=(long)(n+t)|| 33 | record.floor(n)!=null&&record.floor(n)>=(long)(n-t)){ 34 | return true; 35 | }else { 36 | record.add((long)nums[i]); 37 | } 38 | //确保查找表的长度为k 39 | if (record.size()==k+1){ 40 | record.remove((long)nums[i-k]); 41 | } 42 | 43 | } 44 | return false; 45 | } 46 | @Test 47 | public void test(){ 48 | int[] nums={1,5,9,1,5,9}; 49 | int k=2; 50 | int t=3; 51 | boolean flag = containsNearbyAlmostDuplicate(nums, k, t); 52 | System.out.println(flag); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/find/Solution260.java: -------------------------------------------------------------------------------- 1 | package find; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | public class Solution260 { 10 | public int[] singleNumber(int[] nums) { 11 | int[] res=new int[2]; 12 | if (nums.length==2){ 13 | res[0]=nums[0]; 14 | res[1]=nums[1]; 15 | return res; 16 | } 17 | Map record=new HashMap<>(); 18 | for (int i = 0; i < nums.length; i++) { 19 | record.put(nums[i],record.getOrDefault(nums[i],0)+1); 20 | } 21 | int j=0; 22 | for (int i:record.keySet()){ 23 | if (record.get(i)==1){ 24 | res[j++]=i; 25 | } 26 | } 27 | return res; 28 | } 29 | public int[] singleNumber1(int[] nums){ 30 | int diff=0; 31 | for (int i:nums){ 32 | diff^=i; 33 | } 34 | 35 | int mask=1; 36 | //取异或值最后一个二进制位为1的数字作为mask,如果是1则表示两个数字在这一位上不同 37 | while ((diff&1)==0){ 38 | mask=mask<<1; 39 | diff=diff>>1; 40 | 41 | } 42 | int[] res=new int[2]; 43 | //利用mask将原数组分成两个只有一个数字是出现一次其余都是出现两次的数组 44 | for(int i:nums){ 45 | if ((i&mask)==0){ 46 | res[0]^=i; 47 | }else { 48 | res[1]^=i; 49 | } 50 | } 51 | return res; 52 | } 53 | 54 | @Test 55 | public void test(){ 56 | int[] nums={1,2,1,3,2,5}; 57 | int[] re = singleNumber1(nums); 58 | System.out.println(re[0]+","+re[1]); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/find/Solution349.java: -------------------------------------------------------------------------------- 1 | package find; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | 8 | /** 9 | * 给定两个数组,编写一个函数来计算它们的交集。 10 | 11 | 示例 1: 12 | 13 | 输入: nums1 = [1,2,2,1], nums2 = [2,2] 14 | 输出: [2] 15 | 示例 2: 16 | 17 | 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] 18 | 输出: [9,4] 19 | 说明: 20 | 21 | 输出结果中的每个元素一定是唯一的。 22 | 我们可以不考虑输出结果的顺序。 23 | * 24 | */ 25 | public class Solution349 { 26 | public int[] intersection(int[] nums1, int[] nums2) { 27 | Set record=new HashSet<>(); 28 | Set res=new HashSet(); 29 | for (int i:nums1){ 30 | record.add(i); 31 | } 32 | for (int i:nums2){ 33 | if ( record.contains(i)){ 34 | res.add(i); 35 | } 36 | } 37 | int[] reslut = new int[res.size()]; 38 | int j=0; 39 | for (Integer i:res){ 40 | reslut[j++]=i; 41 | } 42 | return reslut; 43 | 44 | } 45 | @Test 46 | public void test(){ 47 | int[] nums1 = {4,9,5}; 48 | int[] nums2 = {9,4,9,8,4}; 49 | int[] res = intersection(nums1, nums2); 50 | for (int i:res){ 51 | System.out.print(i+" "); 52 | } 53 | 54 | } 55 | 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/find/Solution350.java: -------------------------------------------------------------------------------- 1 | package find; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * 给定两个数组,编写一个函数来计算它们的交集。 12 | 13 | 示例 1: 14 | 15 | 输入: nums1 = [1,2,2,1], nums2 = [2,2] 16 | 输出: [2,2] 17 | 示例 2: 18 | 19 | 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] 20 | 输出: [4,9] 21 | 说明: 22 | 23 | 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。 24 | 我们可以不考虑输出结果的顺序。 25 | * 26 | */ 27 | public class Solution350 { 28 | public int[] intersect(int[] nums1, int[] nums2) { 29 | //K:数组元素;V:出现次数 30 | Map record=new HashMap<>(); 31 | for (int i:nums1){ 32 | Integer count = record.get(i); 33 | record.put(i,count==null?1:count+1); 34 | } 35 | List res=new ArrayList<>(); 36 | for (int i:nums2){ 37 | int c=record.get(i)==null?0:record.get(i); 38 | if (c>0){ 39 | res.add(i); 40 | record.put(i,record.get(i)-1); 41 | } 42 | } 43 | int[] reslut = new int[res.size()]; 44 | for (int i=0;i> groupAnagrams(String[] strs) { 30 | List> res=new ArrayList<>(); 31 | if (strs==null||strs.length==0){ 32 | return res; 33 | } 34 | //用于记录字母异位词集合的map 35 | Map> record=new HashMap<>(); 36 | for (String s:strs){ 37 | char[] chars = s.toCharArray(); 38 | //将字符串做排序处理后,字母异位词就可以映射到一起 39 | Arrays.sort(chars); 40 | String sortedStr = String.valueOf(chars); 41 | if (record.containsKey(sortedStr)){ 42 | record.get(sortedStr).add(s); 43 | }else { 44 | List list=new ArrayList<>(); 45 | list.add(s); 46 | record.put(sortedStr,list); 47 | } 48 | } 49 | res.addAll(record.values()); 50 | return res; 51 | 52 | } 53 | @Test 54 | public void test(){ 55 | String[] strings={"eat", "tea", "tan", "ate", "nat", "bat"}; 56 | List> res = groupAnagrams(strings); 57 | System.out.println(res); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/find/Solution771.java: -------------------------------------------------------------------------------- 1 | package find; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。 S 中每个字符代表了一种你拥有的石头的类型, 7 | * 8 | * 你想知道你拥有的石头中有多少是宝石。 9 | 10 | J 中的字母不重复,J 和 S中的所有字符都是字母。字母区分大小写,因此"a"和"A"是不同类型的石头。 11 | 12 | 示例 1: 13 | 14 | 输入: J = "aA", S = "aAAbbbb" 15 | 输出: 3 16 | 示例 2: 17 | 18 | 输入: J = "z", S = "ZZ" 19 | 输出: 0 20 | 注意: 21 | 22 | S 和 J 最多含有50个字母。 23 | J 中的字符不重复。 24 | * 25 | * @create 2019-02-15 15:08 26 | **/ 27 | public class Solution771 { 28 | public int numJewelsInStones(String J, String S) { 29 | boolean[] freq=new boolean[128]; 30 | for (int i = 0; i < J.length(); i++) { 31 | freq[J.charAt(i)]=true; 32 | } 33 | int count=0; 34 | for (int i = 0; i < S.length(); i++) { 35 | if (freq[S.charAt(i)]){ 36 | count++; 37 | } 38 | } 39 | return count; 40 | } 41 | @Test 42 | public void test(){ 43 | String j="z"; 44 | String s="ZZ"; 45 | int i = numJewelsInStones(j, s); 46 | System.out.println(i); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/find/Solution804.java: -------------------------------------------------------------------------------- 1 | package find; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.HashSet; 6 | import java.util.Set; 7 | import java.util.TreeSet; 8 | 9 | public class Solution804 { 10 | public int uniqueMorseRepresentations(String[] words) { 11 | String[] codes={".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."}; 12 | Set codeSet=new HashSet<>(); 13 | for (String word:words){ 14 | char[] chars = word.toCharArray(); 15 | StringBuilder sb=new StringBuilder(); 16 | for (int i = 0; i < chars.length; i++) { 17 | sb.append(codes[chars[i]-'a']); 18 | } 19 | codeSet.add(sb.toString()); 20 | } 21 | return codeSet.size(); 22 | } 23 | @Test 24 | public void test(){ 25 | String[] words={"gin", "zen", "gig", "msg"}; 26 | int r = uniqueMorseRepresentations(words); 27 | System.out.println(r); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/graph/Solution207.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * @Author Ivan 15:03 10 | * @Description TODO 11 | */ 12 | public class Solution207 { 13 | 14 | public boolean canFinish(int numCourses, int[][] prerequisites) { 15 | //将prerequisites构建成邻接表 16 | List[] graph=new List[numCourses]; 17 | for (int i = 0; i < numCourses; i++) { 18 | graph[i]=new ArrayList<>(); 19 | } 20 | for (int[] pre:prerequisites){ 21 | graph[pre[0]].add(pre[1]); 22 | } 23 | //设置标记数组 24 | //0:none-visited;1:visiting;-1:visited 25 | int[] flag=new int[numCourses]; 26 | 27 | //深度遍历 dfs 28 | for (int i = 0; i < numCourses; i++) { 29 | if (hasCycle(graph,flag,i)){ 30 | return false; 31 | } 32 | } 33 | return true; 34 | } 35 | 36 | private boolean hasCycle(List[] graph,int[] flag,int curNode){ 37 | if (flag[curNode]==1){ 38 | return true; 39 | } 40 | if (flag[curNode]==-1){ 41 | return false; 42 | } 43 | flag[curNode]=1; 44 | for (int i:graph[curNode]){ 45 | if (hasCycle(graph,flag,i)){ 46 | return true; 47 | } 48 | } 49 | flag[curNode]=-1; 50 | return false; 51 | } 52 | 53 | @Test 54 | public void test(){ 55 | int num=2; 56 | int[][] pres={{0,1}}; 57 | boolean b = canFinish(num, pres); 58 | System.out.println(b); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/greedy/Solution122.java: -------------------------------------------------------------------------------- 1 | package greedy; 2 | 3 | import org.junit.Test; 4 | 5 | public class Solution122 { 6 | //贪心策略:只要有上升就进行交易 7 | public int maxProfit(int[] prices) { 8 | int n = prices.length; 9 | if (n==0||n==1){ 10 | return 0; 11 | } 12 | int max=0; 13 | for (int i = 1; i < n; i++) { 14 | if (prices[i]>prices[i-1]){ 15 | max+=prices[i]-prices[i-1]; 16 | } 17 | } 18 | return max; 19 | } 20 | @Test 21 | public void tset(){ 22 | int[] p={7,1,5,3,6,4}; 23 | int r = maxProfit(p); 24 | System.out.println(r); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/greedy/Solution392.java: -------------------------------------------------------------------------------- 1 | package greedy; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 给定字符串 s 和 t ,判断 s 是否为 t 的子序列。 7 | * 8 | * 你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 <=100)。 9 | * 10 | * 字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。 11 | * 12 | * 示例 1: 13 | * s = "abc", t = "ahbgdc" 14 | * 15 | * 返回 true. 16 | * 17 | * 示例 2: 18 | * s = "axc", t = "ahbgdc" 19 | * 20 | * 返回 false. 21 | * 22 | * 后续挑战 : 23 | * 24 | * 如果有大量输入的 S,称作S1, S2, ... , Sk 其中 k >= 10亿,你需要依次检查它们是否为 T 的子序列。在这种情况下,你会怎样改变代码? 25 | * 26 | */ 27 | public class Solution392 { 28 | //贪心策略:只比较第一个相等的元素 29 | public boolean isSubsequence(String s, String t) { 30 | int sLen = s.length(); 31 | int tLen = t.length(); 32 | if (sLen==0){ 33 | return true; 34 | } 35 | for (int i = 0,j=0; i < tLen; i++) { 36 | if (s.charAt(j)==t.charAt(i)){ 37 | j++; 38 | } 39 | if (j==sLen){ 40 | return true; 41 | } 42 | } 43 | return false; 44 | } 45 | @Test 46 | public void test(){ 47 | /*"acb" 48 | "ahbgdc"*/ 49 | String s="abc"; 50 | String t="ahbgdc"; 51 | boolean res = isSubsequence(s, t); 52 | System.out.println(res); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/greedy/Solution455.java: -------------------------------------------------------------------------------- 1 | package greedy; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Arrays; 6 | 7 | /** 8 | * 假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi , 9 | * 10 | * 这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i , 11 | * 12 | * 这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。 13 | * 14 | * 注意: 15 | * 16 | * 你可以假设胃口值为正。 17 | * 一个小朋友最多只能拥有一块饼干。 18 | * 19 | * 示例 1: 20 | * 21 | * 输入: [1,2,3], [1,1] 22 | * 23 | * 输出: 1 24 | * 25 | * 解释: 26 | * 你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。 27 | * 虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。 28 | * 所以你应该输出1。 29 | * 示例 2: 30 | * 31 | * 输入: [1,2], [1,2,3] 32 | * 33 | * 输出: 2 34 | * 35 | * 解释: 36 | * 你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。 37 | * 你拥有的饼干数量和尺寸都足以让所有孩子满足。 38 | * 所以你应该输出2. 39 | * 40 | */ 41 | public class Solution455 { 42 | //贪心策略:尽可能满足最大的孩子的贪心值 43 | public int findContentChildren(int[] g, int[] s) { 44 | Arrays.sort(g); 45 | Arrays.sort(s); 46 | int gi=g.length-1; 47 | int si=s.length-1; 48 | int count=0; 49 | //从大到小遍历 50 | while (gi>=0&&si>=0){ 51 | if (s[si]>=g[gi]){ 52 | count++; 53 | gi--; 54 | si--; 55 | }else { 56 | gi--; 57 | } 58 | } 59 | return count; 60 | } 61 | @Test 62 | public void test(){ 63 | int[] g={1,2}; 64 | int[] s={1,2,3}; 65 | int res = findContentChildren(g, s); 66 | System.out.println(res); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/greedy/Solution55.java: -------------------------------------------------------------------------------- 1 | package greedy; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 给定一个非负整数数组,你最初位于数组的第一个位置。 7 | 8 | 数组中的每个元素代表你在该位置可以跳跃的最大长度。 9 | 10 | 判断你是否能够到达最后一个位置。 11 | 12 | 示例 1: 13 | 14 | 输入: [2,3,1,1,4] 15 | 输出: true 16 | 解释: 从位置 0 到 1 跳 1 步, 然后跳 3 步到达最后一个位置。 17 | 示例 2: 18 | 19 | 输入: [3,2,1,0,4] 20 | 输出: false 21 | 解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。 22 | * 23 | * @author 24 | * @create 2019-01-27 21:41 25 | **/ 26 | public class Solution55 { 27 | //贪心策略:每次都走能走的最大范围 28 | public boolean canJump(int[] nums) { 29 | if (nums==null||nums.length==0){ 30 | return true; 31 | } 32 | //最大范围 33 | int maxReach = nums[0]; 34 | //确保最大范围要不小于当前位置的下标; 35 | for (int i = 1; i < nums.length-1&&maxReach>=i; i++) { 36 | //如果当前位置跳跃以后能够超过最大范围就更新最大范围 37 | if (i+nums[i]>maxReach){ 38 | maxReach = i+nums[i]; 39 | } 40 | } 41 | return maxReach>=nums.length-1; 42 | } 43 | 44 | @Test 45 | public void test(){ 46 | int[] nums = {1,2,3}; 47 | boolean f = canJump(nums); 48 | System.out.println(f); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/linkedList/LinkedListUtils.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | /** 4 | * 链表的测试类 5 | * 6 | * @author 7 | * @create 2018-10-28 22:04 8 | **/ 9 | public class LinkedListUtils { 10 | 11 | public static ListNode createLinkedList(int[] arr,int n){ 12 | if (n==0){ 13 | return null; 14 | } 15 | ListNode head = new ListNode(arr[0]); 16 | ListNode cur=head; 17 | for (int i = 1; i < n; i++) { 18 | cur.next=new ListNode(arr[i]); 19 | cur=cur.next; 20 | } 21 | return head; 22 | } 23 | 24 | public static void printLinkedList(ListNode head){ 25 | ListNode cur=head; 26 | while (cur!=null){ 27 | System.out.print(cur.val+" -> "); 28 | cur=cur.next; 29 | } 30 | System.out.println("Null"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/linkedList/ListNode.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | /** 4 | * 链表的结点 5 | * 6 | * @author 7 | * @create 2018-10-28 20:18 8 | **/ 9 | public class ListNode { 10 | public int val; 11 | public ListNode next; 12 | 13 | public ListNode(int val) { 14 | this.val = val; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/linkedList/Solution141.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | public class Solution141 { 4 | public boolean hasCycle(ListNode head) { 5 | if (head==null||head.next==null){ 6 | return false; 7 | } 8 | ListNode slow=head; 9 | ListNode fast=head.next; 10 | while (slow!=null&&fast!=null&&fast.next!=null){ 11 | if (slow==fast){ 12 | return true; 13 | } 14 | slow=slow.next; 15 | fast=fast.next.next; 16 | } 17 | return false; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/linkedList/Solution142.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | import org.junit.Test; 4 | 5 | public class Solution142 { 6 | public ListNode detectCycle(ListNode head) { 7 | if (head==null||head.next==null){ 8 | return null; 9 | } 10 | ListNode slow=head; 11 | ListNode fast=head.next; 12 | int slowCount=1,fastCount=2; 13 | while (slow!=null&&fast!=null&&fast.next!=null){ 14 | if (slow==fast){ 15 | //cycleLen=fastCount-slowCount,一圈的长度 16 | return getCycleTail(head,fastCount-slowCount); 17 | } 18 | slow=slow.next; 19 | slowCount++; 20 | fast=fast.next.next; 21 | fastCount+=2; 22 | } 23 | return null; 24 | } 25 | //根据循环部分的长度来获取循环的头结点 26 | private ListNode getCycleTail(ListNode head,int cycleLen){ 27 | //利用两个指针,间隔保持cycleLen 28 | ListNode slow=head; 29 | ListNode fast=head; 30 | for (int i = 0; i < cycleLen; i++) { 31 | fast=fast.next; 32 | } 33 | while (fast!=slow){ 34 | fast=fast.next; 35 | slow=slow.next; 36 | } 37 | //当两个指针指向同一个结点的时候,表明快指针正好比慢指针快了整整一圈 38 | return fast; 39 | } 40 | 41 | @Test 42 | public void test(){ 43 | /*3,2,0,-4*/ 44 | ListNode l1 = new ListNode(3); 45 | ListNode l2 = new ListNode(2); 46 | ListNode l3 = new ListNode(0); 47 | ListNode l4 = new ListNode(4); 48 | l1.next=l2; 49 | l2.next=l3; 50 | l3.next=l4; 51 | l4.next=l2; 52 | ListNode res = detectCycle(l1); 53 | System.out.println(res.val); 54 | 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/linkedList/Solution143.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 7 | */ 8 | public class Solution143 { 9 | public void reorderList(ListNode head) { 10 | if (head==null||head.next==null||head.next.next==null){ 11 | return ; 12 | } 13 | ListNode fast=head,slow=head; 14 | while (fast.next!=null&&fast.next.next!=null){ 15 | fast=fast.next.next; 16 | slow=slow.next; 17 | } 18 | ListNode secend=slow.next; 19 | slow.next=null; 20 | secend=reverse(secend); 21 | 22 | ListNode first=head; 23 | while (secend!=null){ 24 | ListNode next=first.next; 25 | first.next=secend; 26 | secend=secend.next; 27 | first = first.next; 28 | first.next = next; 29 | first = first.next; 30 | } 31 | } 32 | 33 | private ListNode reverse(ListNode head){ 34 | if (head==null||head.next==null){ 35 | return head; 36 | } 37 | ListNode pre=null; 38 | ListNode cur=head; 39 | while (cur!=null){ 40 | ListNode next=cur.next; 41 | cur.next=pre; 42 | pre=cur; 43 | cur=next; 44 | } 45 | return pre; 46 | } 47 | @Test 48 | public void test(){ 49 | int[] arr={1,2,3,4,5}; 50 | ListNode head = LinkedListUtils.createLinkedList(arr, arr.length); 51 | reorderList(head); 52 | LinkedListUtils.printLinkedList(head); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/linkedList/Solution147.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 插入排序算法: 7 | * 8 | * 插入排序是迭代的,每次只移动一个元素,直到所有元素可以形成一个有序的输出列表。 9 | * 每次迭代中,插入排序只从输入数据中移除一个待排序的元素,找到它在序列中适当的位置,并将其插入。 10 | * 重复直到所有输入数据插入完为止。 11 | * 12 | * 13 | * 示例 1: 14 | * 15 | * 输入: 4->2->1->3 16 | * 输出: 1->2->3->4 17 | * 示例 2: 18 | * 19 | * 输入: -1->5->3->4->0 20 | * 输出: -1->0->3->4->5 21 | * 22 | */ 23 | public class Solution147 { 24 | public ListNode insertionSortList(ListNode head) { 25 | if(head == null||head.next == null) 26 | return head; 27 | //虚拟头节点指向已排序好的部分 28 | ListNode sortedlisthead = new ListNode(0); 29 | //指向当前位置的指针 30 | ListNode cur = head; 31 | while (cur != null) { 32 | ListNode next = cur.next; 33 | //pre:指向待排序的部分的头指针 34 | ListNode pre = sortedlisthead; 35 | //在已排序的部分寻找可以插入的位置 36 | while (pre.next != null && cur.val > pre.next.val) { 37 | pre = pre.next; 38 | } 39 | //将待排序的结点插入已排序的部分 40 | cur.next = pre.next; 41 | //继续指向未排序的部分 42 | pre.next = cur; 43 | cur = next; 44 | } 45 | return sortedlisthead.next; 46 | } 47 | /* @Test 48 | public void test(){ 49 | int[] arr={4,2,1,3}; 50 | ListNode head = LinkedListUtils.createLinkedList(arr, arr.length); 51 | ListNode res = insertionSortList(head); 52 | LinkedListUtils.printLinkedList(res); 53 | }*/ 54 | } 55 | -------------------------------------------------------------------------------- /src/linkedList/Solution19.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。 7 | 8 | 示例: 9 | 10 | 给定一个链表: 1->2->3->4->5, 和 n = 2. 11 | 12 | 当删除了倒数第二个节点后,链表变为 1->2->3->5. 13 | 说明: 14 | 15 | 给定的 n 保证是有效的。 16 | 17 | 进阶: 18 | 19 | 你能尝试使用一趟扫描实现吗? 20 | * 21 | * @author 22 | * @create 2018-11-05 21:24 23 | **/ 24 | public class Solution19 { 25 | public ListNode removeNthFromEnd(ListNode head, int n) { 26 | ListNode dummyHead=new ListNode(0); 27 | dummyHead.next=head; 28 | ListNode fastNode=dummyHead; 29 | ListNode slowNode=dummyHead; 30 | //快指针先移动n+1个位置,由于添加了一个虚拟头结点 31 | for (int i = 0; i <= n; i++) { 32 | fastNode=fastNode.next; 33 | } 34 | //两个指针同时运动 35 | while (fastNode!=null){ 36 | fastNode=fastNode.next; 37 | slowNode=slowNode.next; 38 | } 39 | //此时慢指针指向的则是倒数第n个元素 40 | ListNode delNode=slowNode.next; 41 | slowNode.next=delNode.next; 42 | delNode=null; 43 | 44 | return dummyHead.next; 45 | 46 | } 47 | @Test 48 | public void test(){ 49 | int[] arr={1,2,3,4,5}; 50 | ListNode head = linkedList.Test.createLinkedList(arr, arr.length); 51 | linkedList.Test.printLinkedList(head); 52 | int n=2; 53 | ListNode res = removeNthFromEnd(head, n); 54 | linkedList.Test.printLinkedList(res); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/linkedList/Solution203.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 删除链表中等于给定值 val 的所有节点。 7 | * 8 | * 示例: 9 | * 10 | * 输入: 1->2->6->3->4->5->6, val = 6 11 | * 输出: 1->2->3->4->5 12 | */ 13 | public class Solution203 { 14 | 15 | //虚拟头指针法 16 | public ListNode removeElements(ListNode head, int val) { 17 | if (head==null||head.next==null) 18 | return head; 19 | //设置一个虚拟头指针,这样原始链表中的头结点可以和其他结点一样处理了 20 | ListNode dummyHead=new ListNode(-1); 21 | dummyHead.next=head; 22 | ListNode cur=dummyHead; 23 | while (cur.next!=null){ 24 | //当遇到目标值的时候,进行删除操作 25 | if (cur.next.val==val){ 26 | ListNode delNode=cur.next; 27 | cur.next=delNode.next; 28 | //释放delNode的空间 29 | delNode.next=null; 30 | }else { 31 | //正常遍历结点 32 | cur=cur.next; 33 | } 34 | } 35 | return dummyHead.next; 36 | } 37 | @Test 38 | public void test(){ 39 | int[] arr={1,1,1,3,4,5,6}; 40 | int val=1; 41 | ListNode head = linkedList.Test.createLinkedList(arr, arr.length); 42 | linkedList.Test.printLinkedList(head); 43 | ListNode res = removeElements(head, val); 44 | linkedList.Test.printLinkedList(res); 45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/linkedList/Solution206.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Stack; 6 | 7 | /** 8 | * 反转链表 9 | * 10 | * @author 11 | * @create 2018-10-28 20:20 12 | **/ 13 | public class Solution206 { 14 | 15 | public ListNode reverseList(ListNode head) { 16 | if (head==null||head.next==null){ 17 | return head; 18 | } 19 | ListNode pre=null; 20 | ListNode cur=head; 21 | while (cur!=null){ 22 | //这样可以确保next不抛出空指针异常 23 | ListNode next=cur.next; 24 | cur.next=pre; 25 | pre=cur; 26 | cur=next; 27 | 28 | } 29 | return pre; 30 | } 31 | 32 | public ListNode reverseList1(ListNode head){ 33 | ListNode newHead = new ListNode(-1); 34 | while (head != null) { 35 | ListNode next = head.next; 36 | head.next = newHead.next; 37 | newHead.next = head; 38 | head = next; 39 | } 40 | return newHead.next; 41 | } 42 | 43 | @Test 44 | public void test(){ 45 | Stack stack=new Stack<>(); 46 | stack.empty(); 47 | int[] arr={1,2,3,4,5}; 48 | int n=arr.length; 49 | ListNode head = linkedList.Test.createLinkedList(arr, n); 50 | linkedList.Test.printLinkedList(head); 51 | ListNode res = reverseList1(head); 52 | 53 | linkedList.Test.printLinkedList(res); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/linkedList/Solution21.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 7 | * 8 | * 示例: 9 | * 10 | * 输入:1->2->4, 1->3->4 11 | * 输出:1->1->2->3->4->4 12 | */ 13 | public class Solution21 { 14 | public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 15 | //合并的新链表 16 | ListNode dummy=new ListNode(-1); 17 | ListNode cur=dummy; 18 | while (l1!=null&&l2!=null){ 19 | if (l1.val2 12 | 输出: false 13 | 示例 2: 14 | 15 | 输入: 1->2->2->1 16 | 输出: true 17 | */ 18 | public class Solution234 { 19 | public boolean isPalindrome(ListNode head) { 20 | if (head==null||head.next==null){ 21 | return true; 22 | } 23 | //首先,将链表对半分 24 | ListNode fast=head,slow=head; 25 | //找到后半部分的前一个位置 26 | while (fast.next!=null&&fast.next.next!=null){ 27 | fast=fast.next.next; 28 | slow=slow.next; 29 | } 30 | //将后半部分翻转 31 | slow.next=reverse(slow.next); 32 | //指向后半部分的第一个结点 33 | slow=slow.next; 34 | ListNode cur=head; 35 | //遍历链表,确保前半部分与后半部分是相同的 36 | while (slow!=null){ 37 | if (slow.val!=cur.val){ 38 | return false; 39 | } 40 | slow=slow.next; 41 | cur=cur.next; 42 | } 43 | return true; 44 | 45 | } 46 | private ListNode reverse(ListNode head){ 47 | if (head==null||head.next==null){ 48 | return head; 49 | } 50 | ListNode pre=null; 51 | ListNode cur=head; 52 | while (cur!=null){ 53 | ListNode next=cur.next; 54 | cur.next=pre; 55 | pre=cur; 56 | cur=next; 57 | } 58 | return pre; 59 | } 60 | @Test 61 | public void test() { 62 | int[] arr={1,1,1,1}; 63 | ListNode head = linkedList.Test.createLinkedList(arr, arr.length); 64 | boolean res = isPalindrome(head); 65 | System.out.println(res); 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/linkedList/Solution237.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | /** 4 | * 请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点,你将只被给定要求被删除的节点。 5 | 6 | 现有一个链表 -- head = [4,5,1,9],它可以表示为: 7 | 8 | 4 -> 5 -> 1 -> 9 9 | 示例 1: 10 | 11 | 输入: head = [4,5,1,9], node = 5 12 | 输出: [4,1,9] 13 | 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9. 14 | * @author 15 | * @create 2018-11-05 20:58 16 | **/ 17 | public class Solution237 { 18 | 19 | public void deleteNode(ListNode node) { 20 | if (node==null) 21 | return; 22 | ListNode cur=node; 23 | if (cur.next==null){ 24 | node=null; 25 | } 26 | ListNode next=cur.next; 27 | cur.val=next.val; 28 | cur.next=next.next; 29 | next.next=null; 30 | } 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/linkedList/Solution24.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | *给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。 7 | * 8 | * 示例: 9 | * 10 | * 给定 1->2->3->4, 你应该返回 2->1->4->3. 11 | * 说明: 12 | * 13 | * 你的算法只能使用常数的额外空间。 14 | * 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 15 | * 16 | */ 17 | public class Solution24 { 18 | 19 | public ListNode swapPairs(ListNode head) { 20 | ListNode dummy = new ListNode(-1); 21 | dummy.next=head; 22 | ListNode p=dummy; 23 | //注意循环的条件 24 | while (p.next!=null&&p.next.next!=null){ 25 | ListNode n1=p.next; 26 | ListNode n2=p.next.next; 27 | ListNode next=n2.next; 28 | p.next=n2; 29 | n2.next=n1; 30 | n1.next=next; 31 | //p现在需要指向下一次需要交换位置的前一个 32 | p=n1; 33 | } 34 | return dummy.next; 35 | 36 | } 37 | @Test 38 | public void test(){ 39 | int[] arr={1,2,3,4}; 40 | ListNode head = linkedList.Test.createLinkedList(arr, arr.length); 41 | linkedList.Test.printLinkedList(head); 42 | ListNode res = swapPairs(head); 43 | linkedList.Test.printLinkedList(res); 44 | 45 | 46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/linkedList/Solution86.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。 7 | 8 | 你应当保留两个分区中每个节点的初始相对位置。 9 | 10 | 示例: 11 | 12 | 输入: head = 1->4->3->2->5->2, x = 3 13 | 输出: 1->2->2->4->3->5 14 | * 15 | * @author 16 | * @create 2018-10-29 21:50 17 | **/ 18 | public class Solution86 { 19 | public ListNode partition(ListNode head, int x) { 20 | if (head==null){ 21 | return head; 22 | } 23 | //左部分:记录小于x的结点 24 | ListNode left=new ListNode(-1); 25 | //右部分:记录大于或等于x的结点 26 | ListNode right=new ListNode(-1); 27 | //记录左右部分的头结点 28 | ListNode leftHead=left,rightHead=right; 29 | // 30 | while (head!=null){ 31 | //遇到小于x的结点,用left记录 32 | if (head.val2->3->4->5->NULL, m = 2, n = 4 14 | 输出: 1->4->3->2->5->NULL 15 | * 16 | * 反转链表(2) 17 | * 18 | * @author 19 | * @create 2018-10-28 20:38 20 | **/ 21 | public class Solution92 { 22 | 23 | public ListNode reverseBetween(ListNode head, int m, int n) { 24 | ListNode newHead =new ListNode(0); 25 | newHead.next=head; 26 | ListNode pre=newHead; 27 | //首先寻找到开始反转的位置 28 | for (int i = 1; i < m; i++) { 29 | pre=pre.next; 30 | } 31 | ListNode cur=pre.next; 32 | 33 | for (int i = 0; i < n - m; i++) { 34 | ListNode post=cur.next; 35 | 36 | cur.next=post.next; 37 | post.next=pre.next; 38 | pre.next=post; 39 | } 40 | 41 | 42 | return newHead.next; 43 | } 44 | @Test 45 | public void test(){ 46 | 47 | ListNode n1 = new ListNode(1); 48 | ListNode n2 = new ListNode(2); 49 | ListNode n3 = new ListNode(3); 50 | ListNode n4 = new ListNode(4); 51 | ListNode n5 = new ListNode(5); 52 | ListNode head=n1; 53 | n1.next=n2; 54 | n2.next=n3; 55 | n3.next=n4; 56 | n4.next=n5; 57 | ListNode h = reverseBetween(head, 2, 4); 58 | System.out.println(h); 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/linkedList/Test.java: -------------------------------------------------------------------------------- 1 | package linkedList; 2 | 3 | /** 4 | * 链表的测试类 5 | * 6 | * @author 7 | * @create 2018-10-28 22:04 8 | **/ 9 | public class Test { 10 | 11 | public static ListNode createLinkedList(int[] arr,int n){ 12 | if (n==0){ 13 | return null; 14 | } 15 | ListNode head = new ListNode(arr[0]); 16 | ListNode cur=head; 17 | for (int i = 1; i < n; i++) { 18 | cur.next=new ListNode(arr[i]); 19 | cur=cur.next; 20 | } 21 | return head; 22 | } 23 | 24 | public static void printLinkedList(ListNode head){ 25 | ListNode cur=head; 26 | while (cur!=null){ 27 | System.out.print(cur.val+" -> "); 28 | cur=cur.next; 29 | } 30 | System.out.println("Null"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/math/Solution12.java: -------------------------------------------------------------------------------- 1 | package math; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 7 | 8 | 字符 数值 9 | I 1 10 | V 5 11 | X 10 12 | L 50 13 | C 100 14 | D 500 15 | M 1000 16 | 例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。 17 | 18 | 通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边, 19 | 20 | 所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况: 21 | 22 | I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 23 | X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 24 | C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 25 | 给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。 26 | 27 | 28 | */ 29 | public class Solution12 { 30 | public String intToRoman(int num) { 31 | //设置两个数组 使得数字和符号一一对应 32 | String[] dict={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"}; 33 | int[] nums={1000,900,500,400,100,90,50,40,10,9,5,4,1}; 34 | StringBuilder sb = new StringBuilder(); 35 | for (int i = 0; i=nums[i]){ 38 | num-=nums[i]; 39 | sb.append(dict[i]); 40 | } 41 | } 42 | //从左向右添加符号 43 | return sb.toString(); 44 | } 45 | @Test 46 | public void test(){ 47 | int num=13; 48 | String s = intToRoman(num); 49 | System.out.println(s); 50 | 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/math/Solution231.java: -------------------------------------------------------------------------------- 1 | package math; 2 | 3 | import org.junit.Test; 4 | 5 | public class Solution231 { 6 | 7 | public boolean isPowerOfTwo(int n) { 8 | if (n<0){ 9 | return false; 10 | } 11 | for (int i = 0; i <= Math.sqrt(n); i++) { 12 | int num = 1 << i; 13 | if (num==n){ 14 | return true; 15 | }else if (num>n){ 16 | break; 17 | } 18 | } 19 | return false; 20 | } 21 | 22 | //位运算 23 | public boolean isPowerOfTwo1(int n){ 24 | if (n<=0){ 25 | return false; 26 | } 27 | //例如:1000 & 0111 = 0 28 | return (n&(n-1))==0; 29 | } 30 | 31 | //2的n次幂满足二进制表示中只有一位为1,其余位置均为0 32 | public boolean isPowerOfTwo2(int n){ 33 | if (n<=0){ 34 | return false; 35 | } 36 | String binStr = Integer.toBinaryString(n); 37 | int count=0; 38 | for (int i = 0; i < binStr.length(); i++) { 39 | if (binStr.charAt(i)=='1'){ 40 | count++; 41 | } 42 | if (count>1){ 43 | break; 44 | } 45 | } 46 | return count==1; 47 | } 48 | @Test 49 | public void test(){ 50 | /*int sqrt = (int) Math.sqrt(8); 51 | System.out.println(2==2.0); 52 | */ 53 | int n = 1024; 54 | boolean b = isPowerOfTwo2(n); 55 | System.out.println(b); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/math/Solution263.java: -------------------------------------------------------------------------------- 1 | package math; 2 | 3 | /** 4 | * @Author Ivan 16:25 5 | * @Description TODO 6 | */ 7 | public class Solution263 { 8 | 9 | //递归式 10 | public boolean isUgly(int num) { 11 | if(num==0){ 12 | return false; 13 | } 14 | if(num==1){ 15 | return true; 16 | } 17 | if(num%2==0){ 18 | return isUgly(num/2); 19 | } 20 | if(num%3==0){ 21 | return isUgly(num/3); 22 | } 23 | if(num%5==0){ 24 | return isUgly(num/5); 25 | } 26 | return false; 27 | } 28 | //迭代式 29 | public boolean isUgly1(int num){ 30 | if (num==1){ 31 | return true; 32 | } 33 | while (num%2==0) num/=2; 34 | while (num%3==0) num/=3; 35 | while (num%5==0) num/=5; 36 | return num==1; 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/math/Solution371.java: -------------------------------------------------------------------------------- 1 | package math; 2 | 3 | /** 4 | * @Author Ivan 14:22 5 | * @Description TODO 6 | */ 7 | public class Solution371 { 8 | //两个整数a, b; a ^ b是无进位的相加; a&b得到每一位的进位; 9 | // 让无进位相加的结果与进位不断的异或, 直到进位为0; 10 | public int getSum(int a, int b) { 11 | int sum,carry; 12 | do{ 13 | sum=a^b; 14 | carry=(a&b)<<1; 15 | a=sum; 16 | b=carry; 17 | }while(carry!=0); 18 | return sum; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/math/Solution50.java: -------------------------------------------------------------------------------- 1 | package math; 2 | 3 | import org.junit.Test; 4 | 5 | public class Solution50 { 6 | 7 | //时间复杂度:O(logN) 8 | public double myPow(double x, int n) { 9 | if (n==0){ 10 | return 1.0; 11 | } 12 | //先折半 13 | double half = myPow(x,n/2); 14 | //若n为偶数则将折半值直接相乘即可 15 | if (n%2==0) return half*half; 16 | //n%2==1:若n为奇数的情况 17 | //要分成n为正数和负数的情况来讨论 18 | if (n<0) return half*half/x; 19 | return half*half*x; 20 | } 21 | @Test 22 | public void test(){ 23 | double x =2; 24 | int n = -3; 25 | double v = myPow(x, n); 26 | System.out.println(v); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/math/Solution66.java: -------------------------------------------------------------------------------- 1 | package math; 2 | 3 | /** 4 | * 给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。 5 | 6 | 最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。 7 | 8 | 你可以假设除了整数 0 之外,这个整数不会以零开头。 9 | 10 | 示例 1: 11 | 12 | 输入: [1,2,3] 13 | 输出: [1,2,4] 14 | 解释: 输入数组表示数字 123。 15 | 示例 2: 16 | 17 | 输入: [4,3,2,1] 18 | 输出: [4,3,2,2] 19 | 解释: 输入数组表示数字 4321。 20 | * @Author Ivan 16:06 21 | * @Description TODO 22 | */ 23 | public class Solution66 { 24 | 25 | public int[] plusOne(int[] digits) { 26 | if (digits==null||digits.length==0){ 27 | return null; 28 | } 29 | int n = digits.length; 30 | for (int i = n-1; i >=0; i--) { 31 | ++digits[i]; 32 | digits[i]%=10; 33 | //表示此时没有进位 34 | if (digits[i]!=0){ 35 | return digits; 36 | } 37 | } 38 | //此时表明digits的每一位都是0,则表示进位了 39 | int[] res = new int[n+1]; 40 | res[0]=1; 41 | return res; 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/math/Solution69.java: -------------------------------------------------------------------------------- 1 | package math; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 实现 int sqrt(int x) 函数。 7 | * 8 | * 计算并返回 x 的平方根,其中 x 是非负整数。 9 | * 10 | * 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。 11 | * 12 | * 示例 1: 13 | * 14 | * 输入: 4 15 | * 输出: 2 16 | * 示例 2: 17 | * 18 | * 输入: 8 19 | * 输出: 2 20 | * 说明: 8 的平方根是 2.82842..., 21 | * 由于返回类型是整数,小数部分将被舍去。 22 | */ 23 | public class Solution69 { 24 | //使用二分查找的方法 25 | public int mySqrt(int x) { 26 | int l=0,h=x; 27 | while (l<=h){ 28 | int mid=l+(h-l)/2; 29 | //为了避免整型的溢出, 30 | if (midtarget ,那么所需要的步数肯定要比n多,而且肯定有向左走的步子,也就是求和的时候肯定是有负数的,至于哪个或者哪些个为负,下面开始讨论 12 | //1,n(n+1)/2 - target 为偶数时,所以要想到达 target 需要向左走 n(n+1)/2 - target 偶数步 , 13 | // 就是把前n项中第( n(n+1)/2 - target)/2 步变为负号就行了 14 | //当n(n+1)/2 - target 为奇数时,就要分类讨论了,若n为奇数n+1就是偶数 无论向左还是向右 都不会产生一个奇数的差来因此需要再走一步故要n+2步 15 | //若n为偶数,n+1则为奇数,可以产生一个奇数的差,故要n+1步 16 | public int reachNumber(int target) { 17 | int t=Math.abs(target); 18 | if(t==0){ 19 | return 0; 20 | } 21 | int i=0; 22 | while(i*(i+1)<2*t){ 23 | i++; 24 | } 25 | int sum=i*(i+1)/2; 26 | if(sum==t){ 27 | return i; 28 | } 29 | //若差值为偶数,则令1,2,...,i之间是一个为负数即可 30 | if((sum-t)%2==0){ 31 | return i; 32 | }else{ 33 | //若差值为奇数,需要向左移动奇数位 34 | //若i为偶数,那么i+1为奇数,可以产生一个奇数差; 35 | if(i%2==0){ 36 | return i+1; 37 | }else{ 38 | //若i为奇数,那么i+1为偶数,i+2为奇数,产生奇数差,必须需要i+2步 39 | return i+2; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/other/Solution292.java: -------------------------------------------------------------------------------- 1 | package other; 2 | 3 | /** 4 | 你和你的朋友,两个人一起玩 Nim游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。你作为先手。 5 | 6 | 你们是聪明人,每一步都是最优解。 编写一个函数,来判断你是否可以在给定石头数量的情况下赢得游戏。 7 | 8 | 示例: 9 | 10 | 输入: 4 11 | 12 | 输出: false 13 | 14 | 解释: 如果堆中有 4 块石头,那么你永远不会赢得比赛; 15 | 16 | 因为无论你拿走 1 块、2 块 还是 3 块石头,最后一块石头总是会被你的朋友拿走。 17 | 18 | */ 19 | public class Solution292 { 20 | /** 21 | * 22 | 互相拿球谁先拿完问题: 23 | 1)0~3个球:直接拿对应的数字就赢。 24 | 2)4个球:无论先拿的拿1、2、3,对手只用补3、2、1就能获胜,所以有了前提,如果只剩下4个球,先拿的输。 25 | 3)5、6、7个球:先拿的可以通过拿1、2、3个,使得对手从4开始拿,然后再进行2)操作。 26 | 4)8个球:无论拿1、2、3个,对手都可以拿3、2、1个,使自己从4开始拿,所以剩下8个球,先拿的输 27 | 5)... 28 | 所以规律就很明显了,以4个球为一个单位,4的倍数就输。 29 | 30 | * @param n 31 | * @return 32 | */ 33 | public boolean canWinNim(int n) { 34 | if (n%4==0){ 35 | return false; 36 | } 37 | return true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/queue/Solution279.java: -------------------------------------------------------------------------------- 1 | package queue; 2 | 3 | import javafx.util.Pair; 4 | import org.junit.Test; 5 | 6 | import java.util.Arrays; 7 | import java.util.LinkedList; 8 | import java.util.Queue; 9 | 10 | /** 11 | * 给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。 12 | * 你需要让组成和的完全平方数的个数最少。 13 | 14 | 示例 1: 15 | 16 | 输入: n = 12 17 | 输出: 3 18 | 解释: 12 = 4 + 4 + 4. 19 | 示例 2: 20 | 21 | 输入: n = 13 22 | 输出: 2 23 | 解释: 13 = 4 + 9. 24 | * @author 25 | * @create 2018-11-12 20:30 26 | **/ 27 | public class Solution279 { 28 | 29 | //使用图论的解法 30 | public int numSquares(int n) { 31 | //queue<>,num:表示目标数字;step:表示达到目标数字的步数 32 | Queue> queue=new LinkedList<>(); 33 | //设置一个数组来标记目标数字是否被访问过 34 | boolean[] flagArray=new boolean[n+1]; 35 | Arrays.fill(flagArray,false); 36 | queue.offer(new Pair<>(n,0)); 37 | while (!queue.isEmpty()){ 38 | Pair poll = queue.poll(); 39 | int num=poll.getKey(); 40 | int step = poll.getValue(); 41 | for (int i = 0; ; i++) { 42 | int a=num-i*i; //每次移动都是完全平方数 43 | if (a<0) { 44 | break; 45 | } 46 | if (a==0) { //表示达到终点 47 | return step + 1; 48 | } 49 | if (!flagArray[a]){ //若目标数字没有被访问过才将其入队操作 50 | queue.offer(new Pair<>(a,step+1)); 51 | flagArray[num]=true; 52 | } 53 | 54 | } 55 | } 56 | return n; 57 | } 58 | @Test 59 | public void test(){ 60 | int n=13; 61 | 62 | int i=numSquares(n); 63 | System.out.println(i); 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/queue/Solution621.java: -------------------------------------------------------------------------------- 1 | package queue; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 给定一个用字符数组表示的 CPU 需要执行的任务列表。其中包含使用大写的 A - Z 字母表示的26 种不同种类的任务。任务可以以任意顺序执行, 7 | * 8 | * 并且每个任务都可以在 1 个单位时间内执行完。CPU 在任何一个单位时间内都可以执行一个任务,或者在待命状态。 9 | * 10 | * 然而,两个相同种类的任务之间必须有长度为 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。 11 | * 12 | * 你需要计算完成所有任务所需要的最短时间。 13 | * 14 | * 示例 1: 15 | * 16 | * 输入: tasks = ["A","A","A","B","B","B"], n = 2 17 | * 输出: 8 18 | * 执行顺序: A -> B -> (待命) -> A -> B -> (待命) -> A -> B. 19 | * 注: 20 | * 21 | * 任务的总个数为 [1, 10000]。 22 | * n 的取值范围为 [0, 100]。 23 | * 24 | */ 25 | public class Solution621 { 26 | //将出现最多的任务首先排列好,然后的任务在这个基础上采取插空的办法 27 | public int leastInterval(char[] tasks, int n) { 28 | int[] tasksFreq=new int[26]; 29 | for (char t:tasks){ 30 | tasksFreq[t-'A']++; 31 | } 32 | //出现的最大次数 33 | int max=0; 34 | //最大次数出现的下标 35 | int maxIndex=0; 36 | for (int i = 0; i < tasksFreq.length; i++) { 37 | if (tasksFreq[i]>max){ 38 | maxIndex=i; 39 | max=tasksFreq[i]; 40 | } 41 | } 42 | //频率最高元素的个数 43 | int maxCount=0; 44 | for (int i:tasksFreq){ 45 | if (i==max){ 46 | maxCount++; 47 | } 48 | } 49 | //(max-1):空格数;(n+1):空格宽度; 50 | return Math.max(tasks.length,(max-1)*(n+1)+maxCount); 51 | } 52 | @Test 53 | public void test(){ 54 | char[] tasks={'A','B','A','B','A','B'}; 55 | int n=2; 56 | int i = leastInterval(tasks, n); 57 | System.out.println(i); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/queue/Solution933.java: -------------------------------------------------------------------------------- 1 | package queue; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | /** 7 | * 写一个 RecentCounter 类来计算最近的请求。 8 | * 9 | * 它只有一个方法:ping(int t),其中 t 代表以毫秒为单位的某个时间。 10 | * 11 | * 返回从 3000 毫秒前到现在的 ping 数。 12 | * 13 | * 任何处于 [t - 3000, t] 时间范围之内的 ping 都将会被计算在内,包括当前(指 t 时刻)的 ping。 14 | * 15 | * 保证每次对 ping 的调用都使用比之前更大的 t 值。 16 | * 17 | * 18 | * 19 | * 示例: 20 | * 21 | * 输入:inputs = ["RecentCounter","ping","ping","ping","ping"], inputs = [[],[1],[100],[3001],[3002]] 22 | * 输出:[null,1,2,3,3] 23 | * 24 | * 25 | * 提示: 26 | * 27 | * 每个测试用例最多调用 10000 次 ping。 28 | * 每个测试用例会使用严格递增的 t 值来调用 ping。 29 | * 每次调用 ping 都有 1 <= t <= 10^9。 30 | * 31 | */ 32 | public class Solution933 { 33 | class RecentCounter { 34 | private Queue queue; 35 | 36 | public RecentCounter() { 37 | queue=new LinkedList<>(); 38 | } 39 | 40 | public int ping(int t) { 41 | queue.offer(t); 42 | if (t-3000>queue.peek()){ 43 | queue.poll(); 44 | } 45 | return queue.size(); 46 | } 47 | } 48 | 49 | /** 50 | * Your RecentCounter object will be instantiated and called as such: 51 | * RecentCounter obj = new RecentCounter(); 52 | * int param_1 = obj.ping(t); 53 | */ 54 | } 55 | -------------------------------------------------------------------------------- /src/queue/TreeNode.java: -------------------------------------------------------------------------------- 1 | package queue; 2 | 3 | public class TreeNode { 4 | public int val; 5 | public TreeNode left; 6 | public TreeNode right; 7 | public TreeNode(int x) { val = x; } 8 | } 9 | -------------------------------------------------------------------------------- /src/segTree/Solution303.java: -------------------------------------------------------------------------------- 1 | package segTree; 2 | 3 | public class Solution303 { 4 | class NumArray { 5 | 6 | private int sum[]; 7 | public NumArray(int[] nums) { 8 | sum=new int[nums.length+1]; 9 | sum[0]=0; 10 | for (int i = 1; i neighbors; 15 | UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList(); } 16 | } 17 | 18 | public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { 19 | if (node==null){ 20 | return null; 21 | } 22 | UndirectedGraphNode ret = new UndirectedGraphNode(node.label); 23 | //使用栈来遍历原始的结点 24 | Stack stack=new Stack<>(); 25 | //K:原始结点;V:复制生成的新结点 26 | Map nodeMap=new HashMap<>(); 27 | stack.push(node); 28 | nodeMap.put(node,ret); 29 | while (!stack.empty()){ 30 | UndirectedGraphNode cur = stack.pop(); 31 | for (UndirectedGraphNode next:cur.neighbors){ 32 | if (nodeMap.get(next)==null){ 33 | UndirectedGraphNode graphNode = new UndirectedGraphNode(next.label); 34 | nodeMap.put(next,graphNode); 35 | stack.push(next); 36 | } 37 | nodeMap.get(cur).neighbors.add(nodeMap.get(next)); 38 | } 39 | 40 | } 41 | return ret; 42 | } 43 | @Test 44 | public void test(){ 45 | UndirectedGraphNode node1 = new UndirectedGraphNode(0); 46 | UndirectedGraphNode node2 = new UndirectedGraphNode(0); 47 | UndirectedGraphNode node3 = new UndirectedGraphNode(0); 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/stack/Solution20.java: -------------------------------------------------------------------------------- 1 | package stack; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Stack; 6 | 7 | /** 8 | * 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。 9 | * 10 | * 有效字符串需满足: 11 | * 12 | * 左括号必须用相同类型的右括号闭合。 13 | * 左括号必须以正确的顺序闭合。 14 | * 注意空字符串可被认为是有效字符串。 15 | * 16 | * 示例 1: 17 | * 18 | * 输入: "()" 19 | * 输出: true 20 | * 示例 2: 21 | * 22 | * 输入: "()[]{}" 23 | * 输出: true 24 | * 示例 3: 25 | * 26 | * 输入: "(]" 27 | * 输出: false 28 | * 示例 4: 29 | * 30 | * 输入: "([)]" 31 | * 输出: false 32 | * 33 | */ 34 | public class Solution20 { 35 | public boolean isValid(String s) { 36 | if (s==null||s.length()==0){ 37 | return true; 38 | } 39 | char[] chars = s.toCharArray(); 40 | Stack stack=new Stack<>(); 41 | for (char c : chars) { 42 | if (c=='('||c=='['||c=='{'){ 43 | stack.push(c); 44 | }else { 45 | if (stack.empty()){ 46 | return false; 47 | } 48 | Character match = stack.pop(); 49 | switch (match){ 50 | case '(':match=')';break; 51 | case '[':match=']';break; 52 | case '{':match='}';break; 53 | } 54 | if (c!=match){ 55 | return false; 56 | } 57 | } 58 | } 59 | if (!stack.empty()){ 60 | return false; 61 | } 62 | return true; 63 | 64 | } 65 | 66 | @Test 67 | public void test(){ 68 | String s="([)]"; 69 | boolean res = isValid(s); 70 | System.out.println(res); 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/stack/Solution84.java: -------------------------------------------------------------------------------- 1 | package stack; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.Stack; 6 | 7 | /** 8 | * 示例: 9 | * 10 | * 输入: [2,1,5,6,2,3] 11 | * 输出: 10 12 | */ 13 | public class Solution84 { 14 | //基本思想就是,将数值压栈,直到这些数值代表的高度的柱子不能向右再扩展长度了, 15 | // 就计算其面积大小,pop出来,留下还可以拓展的,一直到最后 16 | public int largestRectangleArea(int[] heights) { 17 | int n = heights.length; 18 | if (n==0){ 19 | return 0; 20 | } 21 | if (n==1){ 22 | return heights[0]; 23 | } 24 | //栈来记录从栈顶到栈底递增序列的下标 25 | Stack stack = new Stack<>(); 26 | int res=0; 27 | //处理的柱子宽度为0-n 28 | for (int i = 0; i <= n; i++) { 29 | //为了避免数组越界,将高度进行了统一处理 30 | int num=i==n?0:heights[i]; 31 | //如果当前遍历的栈为空或者高度大于或等于栈顶元素的值的时候,入栈 32 | if (stack.empty()||num>=heights[stack.peek()]){ 33 | stack.push(i); 34 | }//当前遍历的高度小于栈顶的值的时候,出栈 35 | else { 36 | int top = stack.pop(); 37 | //计算当前的宽度 38 | //当栈为空的时候表明,当前高度为最小高度 39 | int w = stack.empty()?i:i-1-stack.peek(); 40 | //记录最大面积 41 | res=Math.max(res,w*heights[top]); 42 | 43 | //为了从当前位置继续开始 44 | i--; 45 | } 46 | } 47 | return res; 48 | } 49 | @Test 50 | public void test(){ 51 | int[] h={2,1,5,6,2,3}; 52 | int i = largestRectangleArea(h); 53 | System.out.println(i); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/stack/Solution901.java: -------------------------------------------------------------------------------- 1 | package stack; 2 | 3 | import javafx.util.Pair; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class Solution901 { 9 | class StockSpanner { 10 | //Pair,K:price,V:next 11 | private List> nums; 12 | 13 | public StockSpanner() { 14 | nums=new ArrayList<>(); 15 | } 16 | 17 | public int next(int price) { 18 | //初始化, 19 | if (nums.size()==0||price(price,1)); 21 | return 1; 22 | } 23 | int count=1; 24 | while (nums.size()!=0&&nums.get(nums.size()-1).getKey()<=price){ 25 | count+=nums.get(nums.size()-1).getValue(); 26 | nums.remove(nums.size()-1); 27 | } 28 | nums.add(new Pair<>(price,count)); 29 | return count; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/stack/TreeNode.java: -------------------------------------------------------------------------------- 1 | package stack; 2 | 3 | public class TreeNode { 4 | public int val; 5 | public TreeNode left; 6 | public TreeNode right; 7 | public TreeNode(int x) { val = x; } 8 | } 9 | -------------------------------------------------------------------------------- /src/string/Solution14.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 编写一个函数来查找字符串数组中的最长公共前缀。 7 | * 8 | * 如果不存在公共前缀,返回空字符串 ""。 9 | * 10 | * 示例 1: 11 | * 12 | * 输入: ["flower","flow","flight"] 13 | * 输出: "fl" 14 | * 示例 2: 15 | * 16 | * 输入: ["dog","racecar","car"] 17 | * 输出: "" 18 | * 解释: 输入不存在公共前缀。 19 | * 说明: 20 | * 21 | * 所有输入只包含小写字母 a-z 。 22 | * 23 | */ 24 | public class Solution14 { 25 | public String longestCommonPrefix(String[] strs) { 26 | if (strs==null||strs.length==0){ 27 | return ""; 28 | } 29 | StringBuilder sb= new StringBuilder(); 30 | for (int i = 0; i < strs[0].length(); i++) { 31 | //公共前缀的元素一定来自于第一个字符串 32 | char c = strs[0].charAt(i); 33 | //从其他所有字符串中按位搜索 34 | for (int j = 1; j < strs.length; j++) { 35 | //如果当前的字符串已经遍历结束或者存在不同的元素就直接返回结果 36 | if (i>=strs[j].length()||strs[j].charAt(i)!=c){ 37 | return sb.toString(); 38 | } 39 | } 40 | //若其他字符串的这一位都相等的话则添加到结果集合中 41 | sb.append(c); 42 | } 43 | return sb.toString(); 44 | } 45 | @Test 46 | public void test(){ 47 | String[] strs={"flower","flow","flight"}; 48 | String s = longestCommonPrefix(strs); 49 | System.out.println(s); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/string/Solution214.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。 7 | * 8 | * 示例 1: 9 | * 10 | * 输入: "aacecaaa" 11 | * 输出: "aaacecaaa" 12 | * 示例 2: 13 | * 14 | * 输入: "abcd" 15 | * 输出: "dcbabcd" 16 | * 17 | */ 18 | public class Solution214 { 19 | public String shortestPalindrome(String s) { 20 | StringBuilder sb = new StringBuilder(s); 21 | StringBuilder reverseS = sb.reverse(); 22 | int n = s.length(); 23 | for (int i = 0; i =n-1 43 | r=Math.min(r,chars.length-1); 44 | while (l=s1.length()){ 47 | freq2[s2.charAt(i-s1.length())-'a']--; 48 | } 49 | //若各个字符出现频率相同则证明s2 是否包含 s1 的排列 50 | if (Arrays.equals(freq1,freq2)){ 51 | return true; 52 | } 53 | } 54 | return false; 55 | } 56 | @Test 57 | public void test(){ 58 | String s1="adc"; 59 | String s2="dcda"; 60 | boolean b = checkInclusion(s1, s2); 61 | System.out.println(b); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/string/Solution58.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | 7 | 给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度。 8 | 9 | 如果不存在最后一个单词,请返回 0 。 10 | 11 | 说明:一个单词是指由字母组成,但不包含任何空格的字符串。 12 | 13 | 示例: 14 | 15 | 输入: "Hello World" 16 | 输出: 5 17 | * 18 | * 19 | * @create 2019-01-29 21:30 20 | **/ 21 | public class Solution58 { 22 | 23 | public int lengthOfLastWord(String s) { 24 | if (s==null||s.length()==0){ 25 | return 0; 26 | } 27 | String[] strs = s.split(" "); 28 | if (strs.length==0){ 29 | return 0; 30 | } 31 | return strs[strs.length-1].length(); 32 | } 33 | @Test 34 | public void test(){ 35 | String s="Hello World"; 36 | int i = lengthOfLastWord(s); 37 | System.out.println(i); 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/string/Solution9.java: -------------------------------------------------------------------------------- 1 | package string; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 7 | * 8 | * 示例 1: 9 | * 10 | * 输入: 121 11 | * 输出: true 12 | * 示例 2: 13 | * 14 | * 输入: -121 15 | * 输出: false 16 | * 解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。 17 | * 示例 3: 18 | * 19 | * 输入: 10 20 | * 输出: false 21 | * 解释: 从右向左读, 为 01 。因此它不是一个回文数。 22 | * 进阶: 23 | * 24 | * 你能不将整数转为字符串来解决这个问题吗? 25 | * 26 | */ 27 | public class Solution9 { 28 | //转化为字符串来进行求解 29 | public boolean isPalindrome(int x) { 30 | if (x<0){ 31 | return false; 32 | } 33 | String s = String.valueOf(x); 34 | int l=0,r=s.length()-1; 35 | while (l queue=new LinkedList<>(); 24 | queue.offer(root); 25 | TreeNode t; 26 | while ((t=queue.poll())!=null){ 27 | queue.offer(t.left); 28 | queue.offer(t.right); 29 | } 30 | while (!queue.isEmpty()){ 31 | t=queue.poll(); 32 | if (t!=null){ 33 | return false; 34 | } 35 | } 36 | return true; 37 | } 38 | @Test 39 | public void test(){ 40 | int[] pre={1,2,4,3,5}; 41 | int[] in={4,2,1,5,3}; 42 | TreeNode root = TreeNodeUtils.ConstructBinaryTree(pre, in); 43 | boolean b = isCompete(root); 44 | System.out.println(b); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/tree/Solution101.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | /** 4 | * 给定一个二叉树,检查它是否是镜像对称的。 5 | * 6 | * 例如,二叉树 [1,2,2,3,4,4,3] 是对称的。 7 | * 8 | * 1 9 | * / \ 10 | * 2 2 11 | * / \ / \ 12 | * 3 4 4 3 13 | * 但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的: 14 | * 15 | * 1 16 | * / \ 17 | * 2 2 18 | * \ \ 19 | * 3 3 20 | * 21 | */ 22 | public class Solution101 { 23 | 24 | public boolean isSymmetric(TreeNode root) { 25 | if (root==null){ 26 | return true; 27 | } 28 | return isSymmetric(root.left,root.right); 29 | 30 | } 31 | 32 | private boolean isSymmetric(TreeNode left, TreeNode right) { 33 | if (left==null&&right==null){ 34 | return true; 35 | }else if (left==null||right==null){ 36 | return false; 37 | } 38 | if (left.val!=right.val){ 39 | return false; 40 | } 41 | return isSymmetric(left.left,right.right)&&isSymmetric(right.left,left.right); 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/tree/Solution104.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | /** 4 | * @author 5 | * @create 2018-11-15 20:48 6 | **/ 7 | public class Solution104 { 8 | 9 | 10 | public int maxDepth(TreeNode root) { 11 | if (root==null){ 12 | return 0; 13 | } 14 | 15 | return Math.max(maxDepth(root.left),maxDepth(root.right))+1; 16 | 17 | 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/tree/Solution105.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | /** 4 | * 根据一棵树的前序遍历与中序遍历构造二叉树。 5 | * 6 | * 注意: 7 | * 你可以假设树中没有重复的元素。 8 | * 9 | * 例如,给出 10 | * 11 | * 前序遍历 preorder = [3,9,20,15,7] 12 | * 中序遍历 inorder = [9,3,15,20,7] 13 | * 返回如下的二叉树: 14 | * 15 | * 3 16 | * / \ 17 | * 9 20 18 | * / \ 19 | * 15 7 20 | * 21 | */ 22 | public class Solution105 { 23 | public TreeNode buildTree(int[] preorder, int[] inorder) { 24 | return buildTree(preorder,inorder,0,preorder.length-1,0,inorder.length-1); 25 | } 26 | private TreeNode buildTree(int[] preorder,int[] inorder,int preStart,int preEnd,int inStart,int inEnd){ 27 | if (preStart>preEnd||inStart>inEnd){ 28 | return null; 29 | } 30 | int val = preorder[preStart]; 31 | TreeNode root = new TreeNode(val); 32 | //根节点的下标 33 | int index=0; 34 | for (int i = inStart; i <= inEnd; i++) { 35 | if (val==inorder[i]){ 36 | index=i; 37 | break; 38 | } 39 | } 40 | //左子树,preorder[preStart+1,preStart+(index-inStart)],inorder[inStart,index-1] 41 | // (index-inStart):左子树的结点数量 42 | root.left=buildTree(preorder,inorder,preStart+1,preStart+(index-inStart),inStart,index-1); 43 | //右子树, 44 | root.right=buildTree(preorder,inorder,preStart+(index-inStart)+1,preEnd,index+1,inEnd); 45 | return root; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/tree/Solution106.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | /** 4 | * 根据一棵树的中序遍历与后序遍历构造二叉树。 5 | * 6 | * 注意: 7 | * 你可以假设树中没有重复的元素。 8 | * 9 | * 例如,给出 10 | * 11 | * 中序遍历 inorder = [9,3,15,20,7] 12 | * 后序遍历 postorder = [9,15,7,20,3] 13 | * 返回如下的二叉树: 14 | * 15 | * 3 16 | * / \ 17 | * 9 20 18 | * / \ 19 | * 15 7 20 | * 21 | */ 22 | public class Solution106 { 23 | public TreeNode buildTree(int[] inorder, int[] postorder) { 24 | return buildTree(inorder,postorder,0,inorder.length-1,0,postorder.length-1); 25 | } 26 | private TreeNode buildTree(int[] inorder, int[] postorder,int inStart,int inEnd,int postStart,int postEnd){ 27 | if (inStart>inEnd||postStart>postEnd){ 28 | return null; 29 | } 30 | int val = postorder[postEnd]; 31 | TreeNode root = new TreeNode(val); 32 | int index=0; 33 | for (int i = inStart; i <=inEnd ; i++) { 34 | if (val==inorder[i]){ 35 | index=i; 36 | break; 37 | } 38 | } 39 | //(index-inStart):左子树的结点数量 40 | root.left=buildTree(inorder,postorder,inStart,index-1,postStart,postStart+(index-inStart)-1); 41 | root.right=buildTree(inorder,postorder,index+1,inEnd,postStart+(index-inStart),postEnd-1); 42 | return root; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/tree/Solution108.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Arrays; 7 | 8 | /** 9 | * 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。 10 | * 11 | * 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1。 12 | * 13 | * 示例: 14 | * 15 | * 给定有序数组: [-10,-3,0,5,9], 16 | * 17 | * 一个可能的答案是:[0,-3,9,-10,null,5],它可以表示下面这个高度平衡二叉搜索树: 18 | * 19 | * 0 20 | * / \ 21 | * -3 9 22 | * / / 23 | * -10 5 24 | * 25 | * 26 | */ 27 | public class Solution108 { 28 | public TreeNode sortedArrayToBST(int[] nums) { 29 | if (nums==null||nums.length==0){ 30 | return null; 31 | } 32 | return createTreeNode(nums,0,nums.length-1); 33 | } 34 | private TreeNode createTreeNode(int[]nums,int l,int h){ 35 | //特别注意,边界条件 36 | if (l>h){ 37 | return null; 38 | } 39 | int mid=l+(h-l)/2; 40 | TreeNode root=new TreeNode(nums[mid]); 41 | root.left=createTreeNode(nums,l,mid-1); 42 | root.right=createTreeNode(nums,mid+1,h); 43 | return root; 44 | } 45 | 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/tree/Solution110.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | public class Solution110 { 4 | 5 | public boolean isBalanced(TreeNode root) { 6 | if (root==null){ 7 | return true; 8 | } 9 | int right = height(root.right); 10 | int left = height(root.left); 11 | if (right-left>1||right-left<-1){ 12 | return false; 13 | }else { 14 | return isBalanced(root.left)&&isBalanced(root.right); 15 | } 16 | 17 | } 18 | private int height(TreeNode root){ 19 | if (root==null){ 20 | return 0; 21 | } 22 | return Math.max(height(root.left),height(root.right))+1; 23 | } 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/tree/Solution111.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * @author 7 | * @create 2018-11-15 21:00 8 | **/ 9 | public class Solution111 { 10 | public int minDepth(TreeNode root) { 11 | if (root==null){ 12 | return 0; 13 | } 14 | //当左右子树均不为空的时候,取左右子树中的最小值 15 | if (root.left!=null&&root.right!=null){ 16 | return Math.min(minDepth(root.right),minDepth(root.left))+1; 17 | } 18 | //当左右子树不是都有结点的时候,取左右子树的最大深度 19 | return Math.max(minDepth(root.right),minDepth(root.left))+1; 20 | 21 | } 22 | @Test 23 | public void test(){ 24 | TreeNode n1 = new TreeNode(1); 25 | TreeNode n2 = new TreeNode(1); 26 | TreeNode n3 = new TreeNode(1); 27 | TreeNode n4 = new TreeNode(1); 28 | TreeNode n5 = new TreeNode(1); 29 | n1.left=n2; 30 | n1.right=n3; 31 | n3.right=n4; 32 | n4.left=n5; 33 | int i = minDepth(n4); 34 | System.out.println(i); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/tree/Solution112.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | * 给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。 7 | 8 | 说明: 叶子节点是指没有子节点的节点。 9 | 10 | 示例: 11 | 给定如下二叉树,以及目标和 sum = 22, 12 | 13 | 5 14 | / \ 15 | 4 8 16 | / / \ 17 | 11 13 4 18 | / \ \ 19 | 7 2 1 20 | 返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。 21 | * @author 22 | * @create 2018-11-15 21:45 23 | **/ 24 | public class Solution112 { 25 | public boolean hasPathSum(TreeNode root, int sum) { 26 | //注意递归的终止条件 27 | if (root==null){ 28 | return false; 29 | } 30 | if (root.left==null&&root.right==null){ 31 | if (root.val==sum){ 32 | return true; 33 | } 34 | else { 35 | return false; 36 | } 37 | } 38 | return hasPathSum(root.right,sum-root.val)||hasPathSum(root.left,sum-root.val); 39 | } 40 | 41 | @Test 42 | public void test(){ 43 | TreeNode n1 = new TreeNode(1); 44 | TreeNode n2 = new TreeNode(1); 45 | TreeNode n3 = new TreeNode(1); 46 | TreeNode n4 = new TreeNode(1); 47 | TreeNode n5 = new TreeNode(1); 48 | n1.left=n2; 49 | n1.right=n3; 50 | n3.right=n4; 51 | n4.left=n5; 52 | 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/tree/Solution124.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | 给定一个非空二叉树,返回其最大路径和。 10 | 11 | 本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。 12 | 13 | 示例 1: 14 | 15 | 输入: [1,2,3] 16 | 17 | 1 18 | / \ 19 | 2 3 20 | 21 | 输出: 6 22 | 23 | 示例 2: 24 | 25 | 输入: [-10,9,20,null,null,15,7] 26 | 27 | -10 28 | / \ 29 | 9 20 30 | / \ 31 | 15 7 32 | 33 | 输出: 42 34 | 35 | */ 36 | public class Solution124 { 37 | private int maxSum = Integer.MIN_VALUE; 38 | public int maxPathSum(TreeNode root) { 39 | dfs(root); 40 | return maxSum; 41 | } 42 | 43 | //深度遍历 44 | private int dfs(TreeNode node){ 45 | if (node==null){ 46 | return 0; 47 | } 48 | int cur = node.val; //当前路径的值 49 | int left = dfs(node.left); 50 | int right = dfs(node.right); 51 | if (left>0){ 52 | cur+=left; 53 | } 54 | if (right>0){ 55 | cur+=right; 56 | } 57 | //记录路径的最大值 58 | maxSum = Math.max(cur,maxSum); 59 | //最多只在孩子里面选取一个结点 60 | //记录从当前结点所经过能得到的最大值 61 | int curMax = Math.max(node.val,Math.max(node.val+left,node.val+right)); 62 | return curMax; 63 | } 64 | @Test 65 | public void test(){ 66 | int[] pre={-10,9,20,15,7}; 67 | int[] in={9,-10,15,20,7}; 68 | TreeNode root = TreeNodeUtils.ConstructBinaryTree(pre, in); 69 | int i = maxPathSum(root); 70 | System.out.println(i); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/tree/Solution226.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | /** 4 | * @author 5 | * @create 2018-11-15 21:32 6 | **/ 7 | public class Solution226 { 8 | 9 | public TreeNode invertTree(TreeNode root) { 10 | if (root==null){ 11 | return null; 12 | } 13 | TreeNode t=root.right; 14 | root.right=root.left; 15 | root.left=t; 16 | invertTree(root.left); 17 | invertTree(root.right); 18 | return root; 19 | 20 | } 21 | private void swap(TreeNode t1,TreeNode t2){ 22 | TreeNode t=t1; 23 | t1=t2; 24 | t2=t; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/tree/Solution235.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 7 | 8 | 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x, 9 | 满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。” 10 | 11 | 例如,给定如下二叉搜索树: root = [6,2,8,0,4,7,9,null,null,3,5] 12 | 13 | _______6______ 14 | / \ 15 | ___2__ ___8__ 16 | / \ / \ 17 | 0 _4 7 9 18 | / \ 19 | 3 5 20 | 示例 1: 21 | 22 | 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 23 | 输出: 6 24 | 解释: 节点 2 和节点 8 的最近公共祖先是 6。 25 | 示例 2: 26 | 27 | 输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 28 | 输出: 2 29 | 解释: 节点 2 和节点 4 的最近公共祖先是 2, 因为根据定义最近公共祖先节点可以为节点本身。 30 | 说明: 31 | 32 | 所有节点的值都是唯一的。 33 | p、q 为不同节点且均存在于给定的二叉搜索树中。 34 | 35 | * 36 | */ 37 | public class Solution235 { 38 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 39 | if (root==null){ 40 | return null; 41 | } 42 | //如果p,q同时小于根节点的时候,那么在左子树中继续寻找 43 | if (p.valroot.val&&q.val>root.val){ 48 | return lowestCommonAncestor(root.right,p,q); 49 | } 50 | //如果p,q分布在根节点的两侧的时候,此时公共祖先为当前的根节点 51 | return root; 52 | } 53 | 54 | @Test 55 | public void test(){ 56 | int[] pre={6,2,0,4,3,5,8,7,9}; 57 | int[] in={0,2,3,4,5,6,7,8,9}; 58 | TreeNode root = TreeNodeUtils.ConstructBinaryTree(pre, in); 59 | 60 | 61 | 62 | 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/tree/Solution257.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | /** 9 | * 给定一个二叉树,返回所有从根节点到叶子节点的路径。 10 | 11 | 说明: 叶子节点是指没有子节点的节点。 12 | 13 | 示例: 14 | 15 | 输入: 16 | 17 | 1 18 | / \ 19 | 2 3 20 | \ 21 | 5 22 | 23 | 输出: ["1->2->5", "1->3"] 24 | 25 | 解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3 26 | * 27 | * 28 | */ 29 | public class Solution257 { 30 | public List binaryTreePaths(TreeNode root) { 31 | List res=new LinkedList<>(); 32 | if (root==null){ 33 | return res; 34 | } 35 | //当寻找到叶子结点的时候,就将叶子结点加入集合 36 | if (root.left==null&&root.right==null){ 37 | res.add(String.valueOf(root.val)); 38 | } 39 | //分别添加左右子树,注意递归调用的语义! 40 | 41 | //获得左子树结点从根到叶子所有的路径 42 | List leftStr = binaryTreePaths(root.left); 43 | for (String s : leftStr) { 44 | res.add(String.valueOf(root.val)+"->"+s); 45 | } 46 | //获得右子树结点从根到叶子所有的路径 47 | List rightStr = binaryTreePaths(root.right); 48 | for (String s : rightStr) { 49 | res.add(String.valueOf(root.val)+"->"+s); 50 | } 51 | return res; 52 | } 53 | @Test 54 | public void test(){ 55 | TreeNode n1 = new TreeNode(1); 56 | TreeNode n2 = new TreeNode(2); 57 | TreeNode n3 = new TreeNode(3); 58 | TreeNode n4 = new TreeNode(5); 59 | TreeNode n5 = new TreeNode(1); 60 | n1.left=n2; 61 | n1.right=n3; 62 | n2.right=n4; 63 | List strings = binaryTreePaths(n1); 64 | System.out.println(strings); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/tree/Solution404.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import org.junit.Test; 4 | 5 | /** 6 | *计算给定二叉树的所有左叶子之和。 7 | 8 | 示例: 9 | 10 | 3 11 | / \ 12 | 9 20 13 | / \ 14 | 15 7 15 | 16 | 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24 17 | * 18 | * 19 | */ 20 | public class Solution404 { 21 | public int sumOfLeftLeaves(TreeNode root) { 22 | if (root==null){ 23 | return 0; 24 | } 25 | //如何判断一个结点是否为左叶子结点,当其父亲结点的左孩子不空 26 | if (root.left!=null){ 27 | //并且为叶子结点,则此时为左叶子结点 28 | if (root.left.left==null&&root.left.right==null){ 29 | return 30 | //继续遍历右边累积 31 | sumOfLeftLeaves(root.right)+root.left.val; 32 | } 33 | } 34 | return sumOfLeftLeaves(root.left)+sumOfLeftLeaves(root.right); 35 | 36 | } 37 | 38 | @Test 39 | public void test(){ 40 | int[] pre={3,9,20,15,7}; 41 | int[] in={9,3,15,20,7}; 42 | TreeNode root = TreeNodeUtils.ConstructBinaryTree(pre, in); 43 | int res = sumOfLeftLeaves(root); 44 | System.out.println(res); 45 | 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/tree/Solution543.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | /** 4 | 给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。 5 | 6 | 这条路径可能穿过根结点。 7 | 8 | 示例 : 9 | 给定二叉树 10 | 11 | 1 12 | / \ 13 | 2 3 14 | / \ 15 | 4 5 16 | 17 | 返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。 18 | 19 | 注意:两结点之间的路径长度是以它们之间边的数目表示。 20 | 21 | 22 | */ 23 | public class Solution543 { 24 | private int diameter; 25 | public int diameterOfBinaryTree(TreeNode root) { 26 | depth(root); 27 | return diameter; 28 | } 29 | private int depth(TreeNode node){ 30 | if (node==null){ 31 | return 0; 32 | } 33 | int l = depth(node.left); 34 | int r = depth(node.right); 35 | //直径:左右子树的深度之和 36 | diameter=Math.max(diameter,l+r); 37 | return Math.max(l,r)+1; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/tree/Solution572.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | /** 4 | * @Author Ivan 16:26 5 | * @Description TODO 6 | */ 7 | public class Solution572 { 8 | public boolean isSubtree(TreeNode s, TreeNode t) { 9 | if (s==null){ 10 | return false; 11 | } 12 | return isSubtreeWithRoot(s,t)||isSubtree(s.left,t)||isSubtree(s.right,t); 13 | } 14 | private boolean isSubtreeWithRoot(TreeNode s, TreeNode t){ 15 | if (s==null&&t==null){ 16 | return true; 17 | } 18 | if (s==null||t==null){ 19 | return false; 20 | } 21 | if (s.val!=t.val){ 22 | return false; 23 | } 24 | return isSubtreeWithRoot(s.left,t.left)&&isSubtreeWithRoot(s.right,t.right); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/tree/Solution617.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | public class Solution617 { 4 | public TreeNode mergeTrees(TreeNode t1, TreeNode t2) { 5 | if (t1==null&&t2==null){ 6 | return null; 7 | } 8 | if (t1==null){ 9 | return t2; 10 | } 11 | if (t2==null){ 12 | return t1; 13 | } 14 | TreeNode newRoot = new TreeNode(t1.val + t2.val); 15 | newRoot.left=mergeTrees(t1.left,t2.right); 16 | newRoot.right=mergeTrees(t1.right,t2.right); 17 | return newRoot; 18 | } 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/tree/Solution872.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class Solution872 { 9 | public boolean leafSimilar(TreeNode root1, TreeNode root2) { 10 | List l1=new ArrayList<>(); 11 | List l2=new ArrayList<>(); 12 | leaves(root1,l1); 13 | leaves(root2,l2); 14 | if (l1.size()!=l2.size()){ 15 | return false; 16 | } 17 | int n = l1.size(); 18 | for (int i = 0; i < n; i++) { 19 | if (l1.get(i)!=l2.get(i)){ 20 | return false; 21 | } 22 | } 23 | return true; 24 | 25 | } 26 | //获得树的所有叶子结点的集合 27 | private void leaves(TreeNode root,List res){ 28 | if (root==null){ 29 | return ; 30 | } 31 | if (root.left==null&&root.right==null){ 32 | res.add(root.val); 33 | } 34 | leaves(root.right,res); 35 | leaves(root.left,res); 36 | } 37 | @Test 38 | public void test(){ 39 | int[] pre={1,2,4,3,5,6}; 40 | int[] in={4,2,1,5,3,6}; 41 | TreeNode root1 = TreeNodeUtils.ConstructBinaryTree(pre, in); 42 | List l1=new ArrayList<>(); 43 | leaves(root1,l1); 44 | System.out.println(l1); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/tree/Solution894.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public class Solution894 { 7 | public List allPossibleFBT(int N) { 8 | List res=new ArrayList<>(); 9 | //N为偶数则不存在这样的满二叉树 10 | if (N%2==0){ 11 | return res; 12 | } 13 | //仅有一个根结点 14 | if (N==1){ 15 | TreeNode root=new TreeNode(0); 16 | res.add(root); 17 | return res; 18 | } 19 | 20 | for (int i = 1; i < N; i+=2) { 21 | //获取左子树的集合 22 | List leftNodes = allPossibleFBT(i); 23 | //获取右子树的集合,left+right=N-1 24 | List rightNodes = allPossibleFBT(N - 1 - i); 25 | for (TreeNode left:leftNodes){ 26 | for (TreeNode right:rightNodes){ 27 | //构造满二叉树 28 | TreeNode root = new TreeNode(0); 29 | root.left=left; 30 | root.right=right; 31 | res.add(root); 32 | } 33 | } 34 | } 35 | return res; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/tree/Solution897.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class Solution897 { 9 | public TreeNode increasingBST(TreeNode root) { 10 | if (root==null){ 11 | return root; 12 | } 13 | List res=new ArrayList<>(); 14 | inOrder(root,res); 15 | root=new TreeNode(res.get(0)); 16 | TreeNode head=root; 17 | for (int i = 1; i < res.size(); i++) { 18 | root.right=new TreeNode(res.get(i)); 19 | root.left=null; 20 | root=root.right; 21 | } 22 | return head; 23 | 24 | } 25 | private void inOrder(TreeNode root,List res){ 26 | if (root==null){ 27 | return; 28 | } 29 | inOrder(root.left,res); 30 | res.add(root.val); 31 | inOrder(root.right,res); 32 | } 33 | @Test 34 | public void test(){ 35 | int[] pre={5,3,2,4,6}; 36 | int[] in={2,3,4,5,6}; 37 | TreeNode root = TreeNodeUtils.ConstructBinaryTree(pre, in); 38 | TreeNode res = increasingBST(root); 39 | ArrayList> r = TreeNodeUtils.Print(res); 40 | System.out.println(r); 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/tree/Solution95.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import org.junit.Test; 4 | import tree.TreeNode; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class Solution95 { 10 | public List generateTrees(int n) { 11 | List res=new ArrayList<>(); 12 | if (n<=0){ 13 | return res; 14 | } 15 | res=generare(1,n); 16 | return res; 17 | 18 | } 19 | private List generare(int start,int end){ 20 | List treeNodes=new ArrayList<>(); 21 | if (start>end){ 22 | treeNodes.add(null); 23 | return treeNodes; 24 | } 25 | for (int i = start; i <=end ; i++) { 26 | List left = generare(start, i-1); 27 | List right = generare(i + 1, end); 28 | if (left.isEmpty()){ 29 | left.add(null); 30 | } 31 | if (right.isEmpty()){ 32 | right.add(null); 33 | } 34 | 35 | for (TreeNode l:left){ 36 | for (TreeNode r:right){ 37 | TreeNode root = new TreeNode(i); 38 | root.right=r; 39 | root.left=l; 40 | treeNodes.add(root); 41 | } 42 | } 43 | } 44 | return treeNodes; 45 | } 46 | @Test 47 | public void test(){ 48 | List res = generateTrees(3); 49 | System.out.println(res); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/tree/Solution96.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import org.junit.Test; 4 | 5 | public class Solution96 { 6 | /** 7 | * 递推公式: 8 | * F(0)=1 9 | * F(1)=1 10 | * F(N)=SUM(F(i-1)*F(n-i)) 11 | * @param n 12 | * @return 13 | */ 14 | public int numTrees(int n) { 15 | int[] memo=new int[n+1]; 16 | memo[0]=1; 17 | memo[1]=1; 18 | for (int i = 2; i <=n ; i++) { 19 | for (int j = 1; j <= i; j++) { 20 | memo[i]+=memo[j-1]*memo[i-j]; 21 | } 22 | } 23 | return memo[n]; 24 | } 25 | @Test 26 | public void test(){ 27 | int n=3; 28 | int res = numTrees(n); 29 | System.out.println(res); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/tree/Solution99.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import org.junit.Test; 4 | 5 | import java.util.ArrayList; 6 | 7 | public class Solution99 { 8 | private TreeNode pre; 9 | private TreeNode first,second; 10 | 11 | public void recoverTree(TreeNode root) { 12 | pre=null; 13 | first=null; 14 | second=null; 15 | inOrder(root); 16 | int t=first.val; 17 | first.val=second.val; 18 | second.val=t; 19 | 20 | } 21 | private void inOrder(TreeNode root){ 22 | if (root==null){ 23 | return; 24 | } 25 | inOrder(root.left); 26 | //此时发生了逆序 27 | if (pre!=null&&pre.val>root.val){ 28 | if (first==null){ 29 | first=pre; 30 | } 31 | second=root; 32 | } 33 | pre=root; 34 | inOrder(root.right); 35 | } 36 | @Test 37 | public void test(){ 38 | int[] pre={1,3,2}; 39 | int[] in={3,2,1}; 40 | TreeNode root = TreeNodeUtils.ConstructBinaryTree(pre, in); 41 | ArrayList> r1 = TreeNodeUtils.Print(root); 42 | System.out.println(r1); 43 | recoverTree(root); 44 | ArrayList> r2 = TreeNodeUtils.Print(root); 45 | System.out.println(r2); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/tree/TreeNode.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | public class TreeNode { 4 | public int val; 5 | public TreeNode left; 6 | public TreeNode right; 7 | public TreeNode(int x) { val = x; } 8 | } 9 | -------------------------------------------------------------------------------- /src/utils/LinkedListUtils.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | 4 | /** 5 | * 链表的测试类 6 | * 7 | * @author 8 | * @create 2018-10-28 22:04 9 | **/ 10 | public class LinkedListUtils { 11 | 12 | 13 | public static ListNode createLinkedList(int[] arr,int n){ 14 | if (n==0){ 15 | return null; 16 | } 17 | ListNode head = new ListNode(arr[0]); 18 | ListNode cur=head; 19 | for (int i = 1; i < n; i++) { 20 | cur.next=new ListNode(arr[i]); 21 | cur=cur.next; 22 | } 23 | return head; 24 | } 25 | 26 | public static void printLinkedList(ListNode head){ 27 | ListNode cur=head; 28 | while (cur!=null){ 29 | System.out.print(cur.val+" -> "); 30 | cur=cur.next; 31 | } 32 | System.out.println("Null"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/utils/ListNode.java: -------------------------------------------------------------------------------- 1 | package utils; 2 | 3 | /** 4 | * 链表的结点 5 | * 6 | * @author 7 | * @create 2018-10-28 20:18 8 | **/ 9 | public class ListNode { 10 | public int val; 11 | public ListNode next; 12 | 13 | public ListNode(int val) { 14 | this.val = val; 15 | } 16 | } 17 | --------------------------------------------------------------------------------