├── .gitignore ├── CodingInterview.iml ├── LICENSE ├── README.md ├── pom.xml └── src └── main └── java ├── algorithm ├── alg4 │ ├── README.md │ ├── Solution001.java │ ├── Solution002.java │ ├── Solution003.java │ ├── Solution004.java │ └── Solution005.java ├── knapsack │ ├── 0-1背包问题.md │ ├── Problem01.java │ ├── Problem02.java │ ├── Problem03.java │ └── Problem04.java ├── leetcode │ ├── Solution001.java │ ├── Solution002.java │ ├── Solution003.java │ ├── Solution005.java │ ├── Solution006.java │ ├── Solution007.java │ ├── Solution008.java │ ├── Solution009.java │ ├── Solution011.java │ ├── Solution013.java │ ├── Solution014.java │ ├── Solution015.java │ ├── Solution016.java │ ├── Solution017.java │ ├── Solution018.java │ ├── Solution019.java │ ├── Solution020.java │ ├── Solution021.java │ ├── Solution022.java │ ├── Solution024.java │ ├── Solution026.java │ ├── Solution027.java │ ├── Solution028.java │ ├── Solution034.java │ ├── Solution035.java │ ├── Solution037.java │ ├── Solution038.java │ ├── Solution039.java │ ├── Solution040.java │ ├── Solution046.java │ ├── Solution047.java │ ├── Solution048.java │ ├── Solution051.java │ ├── Solution052.java │ ├── Solution053.java │ ├── Solution055.java │ ├── Solution056.java │ ├── Solution057.java │ ├── Solution060.java │ ├── Solution061.java │ ├── Solution062.java │ ├── Solution063.java │ ├── Solution064.java │ ├── Solution069.java │ ├── Solution070.java │ ├── Solution072.java │ ├── Solution075.java │ ├── Solution077.java │ ├── Solution078.java │ ├── Solution079.java │ ├── Solution080.java │ ├── Solution086.java │ ├── Solution088.java │ ├── Solution089.java │ ├── Solution090.java │ ├── Solution091.java │ ├── Solution093.java │ ├── Solution094.java │ ├── Solution095.java │ ├── Solution096.java │ ├── Solution098.java │ ├── Solution100.java │ ├── Solution101.java │ ├── Solution102.java │ ├── Solution103.java │ ├── Solution104.java │ ├── Solution105.java │ ├── Solution106.java │ ├── Solution107.java │ ├── Solution108.java │ ├── Solution110.java │ ├── Solution111.java │ ├── Solution112.java │ ├── Solution113.java │ ├── Solution114.java │ ├── Solution120.java │ ├── Solution121.java │ ├── Solution122.java │ ├── Solution123.java │ ├── Solution125.java │ ├── Solution127.java │ ├── Solution129.java │ ├── Solution130.java │ ├── Solution131.java │ ├── Solution134.java │ ├── Solution136.java │ ├── Solution137.java │ ├── Solution139.java │ ├── Solution141.java │ ├── Solution142.java │ ├── Solution144.java │ ├── Solution144a.java │ ├── Solution145.java │ ├── Solution147.java │ ├── Solution148.java │ ├── Solution152.java │ ├── Solution153.java │ ├── Solution167.java │ ├── Solution179.java │ ├── Solution198.java │ ├── Solution199.java │ ├── Solution200.java │ ├── Solution206.java │ ├── Solution207.java │ ├── Solution209.java │ ├── Solution210.java │ ├── Solution211.java │ ├── Solution212.java │ ├── Solution213.java │ ├── Solution215.java │ ├── Solution216.java │ ├── Solution220.java │ ├── Solution221.java │ ├── Solution226.java │ ├── Solution234.java │ ├── Solution235.java │ ├── Solution236.java │ ├── Solution241.java │ ├── Solution242.java │ ├── Solution257.java │ ├── Solution260.java │ ├── Solution264.java │ ├── Solution274.java │ ├── Solution278.java │ ├── Solution279.java │ ├── Solution283.java │ ├── Solution287.java │ ├── Solution300.java │ ├── Solution303.java │ ├── Solution304.java │ ├── Solution306.java │ ├── Solution309.java │ ├── Solution322.java │ ├── Solution324.java │ ├── Solution337.java │ ├── Solution338.java │ ├── Solution343.java │ ├── Solution344.java │ ├── Solution345.java │ ├── Solution347.java │ ├── Solution349.java │ ├── Solution350.java │ ├── Solution357.java │ ├── Solution368.java │ ├── Solution375.java │ ├── Solution376.java │ ├── Solution377.java │ ├── Solution392.java │ ├── Solution394.java │ ├── Solution402.java │ ├── Solution404.java │ ├── Solution406.java │ ├── Solution413.java │ ├── Solution416.java │ ├── Solution417.java │ ├── Solution435.java │ ├── Solution451.java │ ├── Solution452.java │ ├── Solution455.java │ ├── Solution467.java │ ├── Solution474.java │ ├── Solution491.java │ ├── Solution494.java │ ├── Solution513.java │ ├── Solution516.java │ ├── Solution524.java │ ├── Solution526.java │ ├── Solution530.java │ ├── Solution532.java │ ├── Solution540.java │ ├── Solution547.java │ ├── Solution559.java │ ├── Solution567.java │ ├── Solution583.java │ ├── Solution605.java │ ├── Solution621.java │ ├── Solution633.java │ ├── Solution646.java │ ├── Solution649.java │ ├── Solution650.java │ ├── Solution659.java │ ├── Solution665.java │ ├── Solution680.java │ ├── Solution690.java │ ├── Solution695.java │ ├── Solution713.java │ ├── Solution714.java │ ├── Solution738.java │ ├── Solution744.java │ ├── Solution763.java │ ├── Solution767.java │ ├── Solution783.java │ ├── Solution784.java │ ├── Solution826.java │ ├── Solution838.java │ ├── Solution841.java │ ├── Solution842.java │ ├── Solution844.java │ ├── Solution845.java │ ├── Solution859.java │ ├── Solution860.java │ ├── Solution861.java │ ├── Solution870.java │ ├── Solution874.java │ ├── Solution881.java │ ├── Solution904.java │ ├── Solution908.java │ ├── Solution910.java │ ├── Solution921.java │ ├── Solution922.java │ ├── Solution923.java │ ├── Solution925.java │ ├── Solution930.java │ ├── Solution938.java │ ├── Solution944.java │ ├── Solution948.java │ ├── Solution955.java │ ├── Solution969.java │ ├── Solution973.java │ ├── Solution984.java │ └── Trie.java ├── note │ ├── KMP.java │ ├── LRU.java │ ├── MergeArray.java │ ├── MySearch.java │ ├── MySort.java │ ├── RedBlackTree.md │ ├── ReverseLinkedList.java │ ├── StrToNumber.java │ ├── TopK.java │ ├── TreeVisit.java │ └── 最长公共子序列.md ├── sfo │ ├── README.md │ └── cpt06 │ │ ├── Solution056.java │ │ ├── Solution05602.java │ │ └── Solution063.java ├── str │ ├── Problem042.java │ ├── Problem06.java │ ├── Problem07.java │ ├── Problem08.java │ ├── Problem09.java │ ├── Problem0901.java │ ├── Problem0902.java │ └── Problem11.java └── tmop │ ├── README.md │ ├── Solution.java │ ├── Solution001.java │ ├── Solution002.java │ ├── Solution003.java │ ├── Solution004.java │ ├── Solution005.java │ ├── Solution006.java │ ├── Solution007.java │ ├── Solution008.java │ ├── Solution009.java │ ├── Solution010.java │ ├── Solution011.java │ ├── Solution012.java │ ├── Solution013.java │ ├── Solution014.java │ ├── Solution015.java │ ├── Solution016.java │ ├── Solution017.java │ ├── Solution018.java │ ├── Solution019.java │ ├── Solution020.java │ ├── Solution021.java │ ├── Solution022.java │ └── Solution023.java ├── bishi ├── Main080501.java ├── Main080503.java ├── Main081101.java ├── Main081103.java ├── Main0831.java ├── Main0901.java ├── Main090401.java ├── Main090402.java ├── Main090601.java ├── Main090602.java ├── Main090701.java ├── Main090702.java ├── Main090703.java ├── Main0909001.java ├── Main0909002.java ├── Main090901.java ├── Main090902.java ├── Main090903.java ├── Main090905.java ├── Main091001.java ├── Main091002.java ├── Main091501.java ├── Main091502.java ├── Main091601.java ├── Main091602.java ├── beike │ ├── Main002.java │ └── Main003.java ├── iqiyi │ ├── Main091501.java │ ├── Main091502.java │ └── Main091503.java └── toutiao │ ├── Main01.java │ └── Main05.java ├── concurrent ├── CountDownLatchExample.java ├── CyclicBarrierExample.java ├── DeathLockExample.java ├── SemaphoreExample.java ├── cpt01 │ └── TryConcurrency.java ├── cpt02 │ ├── DaemonThread.java │ └── ThreadConstruction.java ├── cpt03 │ ├── CurrentThread.java │ ├── FlagThreadExit.java │ ├── ThreadInterrupt.java │ ├── ThreadInterrupted.java │ ├── ThreadInterrupted2.java │ ├── ThreadInterrupted3.java │ ├── ThreadInterrupted4.java │ ├── ThreadJoin.java │ ├── ThreadPriority.java │ ├── ThreadPriority2.java │ ├── ThreadPriority3.java │ ├── ThreadSleep.java │ └── ThreadYield.java ├── cpt04 │ ├── DeadLock.java │ ├── Mutex.java │ ├── ThisMonitor.java │ ├── ThisMonitor2.java │ └── TicketWindowRunnable.java ├── cpt05 │ ├── EventClient.java │ ├── EventClient2.java │ └── EventQueue.java ├── cpt06 │ └── ThreadGroupCreateror.java ├── cpt07 │ ├── CaptureThreadException.java │ ├── EmptyExceptionHandler.java │ ├── ExecutorTest.java │ ├── PreventDuplicated.java │ └── ThreadHook.java ├── cpt09 │ ├── ActiveLoadTest.java │ ├── Child.java │ ├── ClassInit.java │ ├── Parent.java │ ├── Price.java │ ├── PriceTest.java │ ├── Singleton.java │ ├── Singleton2.java │ └── StaticInitTest.java ├── cpt10 │ ├── ApplicationClassLoader.java │ ├── BootstrapClassLoader.java │ └── ExtClassLoader.java └── cpt12 │ └── VolatileFoo.java └── design ├── ProducerConsumer.java ├── builder ├── AbstractStringBuilder.java ├── Client.java └── MyStringBuilder.java ├── chainofresponsibility ├── Client.java ├── ConcreteHandler1.java ├── ConcreteHandler2.java ├── Handler.java ├── Request.java └── RequestType.java ├── command ├── Client.java ├── Command.java ├── Invoker.java ├── Light.java ├── LightOffCommand.java └── LightOnCommand.java ├── prototype ├── Client.java ├── ConcretePrototype.java └── Prototype.java ├── simplefactory ├── Client.java ├── ConcreteProduct.java ├── ConcreteProduct1.java ├── ConcreteProduct2.java ├── Product.java └── SimpleFactory.java └── singleton ├── Singleton01.java ├── Singleton02.java ├── Singleton03.java ├── Singleton04.java └── Singleton05.java /CodingInterview.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.zhiming 8 | interview 9 | 1.0 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/main/java/algorithm/alg4/README.md: -------------------------------------------------------------------------------- 1 | # 算法(第四版) 2 | 3 | ## 第一章(基础) 4 | 5 | | 编号 | 内容 | 6 | |:----:| --------------------------------------- | 7 | | 001 | [求最大公约数和最小公倍数](Solution001.java) | 8 | | 002 | [二分查找的递归实现](Solution002.java) | 9 | | 003 | [判断是否是素数](Solution003.java) | 10 | | 004 | [判断回文字符串](Solution004.java) | 11 | | 005 | [双栈算术表达式求值](Solution005.java) | 12 | 13 | ## 第二章(排序) 14 | 15 | ## 第三章(查找) 16 | 17 | ## 第四章(图) 18 | 19 | ## 第五章(字符串) 20 | 21 | ## 第六章(总结) 22 | -------------------------------------------------------------------------------- /src/main/java/algorithm/alg4/Solution002.java: -------------------------------------------------------------------------------- 1 | package algorithm.alg4; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 二分查找的递归实现 6 | * @date: 2018/10/28 7 | */ 8 | public class Solution002 { 9 | 10 | public static void main(String[] args) { 11 | int[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 12 | int key = 6; 13 | 14 | System.out.print("key==" + key + "的下标为: "); 15 | System.out.println(binarySearch(array, key)); 16 | } 17 | 18 | public static int binarySearch(int[] array, int key) { 19 | return binarySearch(array, key, 0, array.length); 20 | } 21 | 22 | public static int binarySearch(int[] array, int key, int left, int right) { 23 | if (left > right) { 24 | return -1; 25 | } 26 | 27 | int mid = left + (right - left) / 2; 28 | if (key < array[mid]) { 29 | return binarySearch(array, key, left, mid - 1); 30 | } else if (key > array[mid]) { 31 | return binarySearch(array, key, mid + 1, right); 32 | } else { 33 | return mid; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/algorithm/alg4/Solution003.java: -------------------------------------------------------------------------------- 1 | package algorithm.alg4; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/10/28 7 | */ 8 | public class Solution003 { 9 | 10 | public static void main(String[] args) { 11 | System.out.println("3是素数吗? " + isPrime(3)); 12 | System.out.println("4是素数吗? " + isPrime(4)); 13 | System.out.println("11是素数吗? " + isPrime(11)); 14 | } 15 | 16 | /** 17 | * 判断一个数是不是素数 18 | * 19 | * @param n 20 | * @return 21 | */ 22 | public static boolean isPrime(int n) { 23 | if (2 > n) { 24 | return false; 25 | } 26 | 27 | for (int i = 2; i * i <= n; ++i) { 28 | if (0 == n % i) { 29 | return false; 30 | } 31 | } 32 | return true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/algorithm/alg4/Solution004.java: -------------------------------------------------------------------------------- 1 | package algorithm.alg4; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/10/28 7 | */ 8 | public class Solution004 { 9 | 10 | public static void main(String[] args) { 11 | System.out.println("abcd 是回文字符串吗? " + isPalindrome("abcd")); 12 | System.out.println("abcdcba 是回文字符串吗? " + isPalindrome("abcdcba")); 13 | System.out.println("aaaa 是回文字符串吗? " + isPalindrome("aaaa")); 14 | } 15 | 16 | /** 17 | * 判断字符串是否为回文字符串 18 | * 19 | * @param str 20 | * @return 21 | */ 22 | public static boolean isPalindrome(String str) { 23 | if (null == str || 0 == str.length()) { 24 | return false; 25 | } 26 | 27 | for (int i = 0; i < str.length() / 2; ++i) { 28 | if (str.charAt(i) != str.charAt(str.length() - 1 - i)) { 29 | return false; 30 | } 31 | } 32 | return true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/algorithm/knapsack/Problem02.java: -------------------------------------------------------------------------------- 1 | package algorithm.knapsack; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 完全背包问题 6 | * @date: 2018/09/04 7 | */ 8 | public class Problem02 { 9 | public static void main(String[] args) { 10 | int[] weights = {1, 2, 3, 4, 5}; 11 | int[] values = {5, 1, 3, 2, 1}; 12 | 13 | System.out.println(knapsack01(5, 5, weights, values)); 14 | } 15 | 16 | public static int knapsack01(int numberOfGoods, int W, int[] weights, int[] values) { 17 | int[] dp = new int[numberOfGoods + 1]; 18 | 19 | for (int i = 1; i <= numberOfGoods; ++i) { 20 | int w = weights[i - 1]; 21 | int v = values[i - 1]; 22 | for (int j = w; j <= W; ++j) { 23 | dp[j] = Math.max(dp[j], dp[j - w] + v); 24 | } 25 | } 26 | return dp[numberOfGoods]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution001.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 两数之和 9 | * 时间复杂度: O(n) 只遍历了包含有 n 个元素的列表一次。在哈希表中进行的每次查找只花费 O(1)的时间。 10 | * 空间复杂度: O(n) 所需的额外空间取决于哈希表中存储的元素数量,该表最多需要存储 n 个元素 11 | * @date: 2018/11/18 12 | */ 13 | public class Solution001 { 14 | 15 | /** 16 | * 依次顺序扫描数组,每次从哈希表中查询是否存在对应的相加之和为 target 的数字, 17 | * 存在则直接将它们的下标放入数组返回,不存在则将当前数字和下标放入哈希表. 18 | * key -> 该数字 19 | * value -> 该数字的下标 20 | */ 21 | public int[] twoSum(int[] nums, int target) { 22 | if (null == nums || 0 >= nums.length) { 23 | return null; 24 | } 25 | 26 | Map map = new HashMap<>(nums.length); 27 | int pos; 28 | for (int i = 0; i < nums.length; ++i) { 29 | int number = target - nums[i]; 30 | if (-1 != (pos = map.getOrDefault(number, -1))) { 31 | return new int[]{i, pos}; 32 | } else { 33 | map.put(nums[i], i); 34 | } 35 | } 36 | 37 | return null; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution007.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author mayuan 5 | * @desc 6 | * @date 2018/02/08 7 | */ 8 | public class Solution007 { 9 | 10 | public int reverse(int x) { 11 | int result = 0; 12 | 13 | while (0 != x){ 14 | int tail = x % 10; 15 | int newResult = 10 * result + tail; 16 | 17 | if ((newResult - tail) / 10 != result){ 18 | return 0; 19 | } 20 | 21 | result = newResult; 22 | x /= 10; 23 | } 24 | return result; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution009.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author mayuan 5 | * @desc 6 | * @date 2018/02/08 7 | */ 8 | public class Solution009 { 9 | 10 | public boolean isPalindrome(int x) { 11 | // Special cases: 12 | // As discussed above, when x < 0, x is not a palindrome. 13 | // Also if the last digit of the number is 0, in order to be a palindrome, 14 | // the first digit of the number also needs to be 0. 15 | // Only 0 satisfy this property. 16 | if (0 > x || (0 == x % 10 && 0 != x)) { 17 | return false; 18 | } 19 | 20 | int revertedNumber = 0; 21 | while (x > revertedNumber) { 22 | revertedNumber = revertedNumber * 10 + x % 10; 23 | x /= 10; 24 | } 25 | 26 | // When the length is an odd number, we can get rid of the middle digit by revertedNumber/10 27 | // For example when the input is 12321, at the end of the while loop we get x = 12, revertedNumber = 123, 28 | // since the middle digit doesn't matter in palidrome(it will always equal to itself), we can simply get rid of it. 29 | return x == revertedNumber || x == revertedNumber / 10; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution011.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 盛最多水的容器 6 | * @date: 2019/01/02 7 | */ 8 | public class Solution011 { 9 | 10 | /** 11 | * 双指针解法,指向较小数字的指针向指向较大数字的指针方向移动 12 | * 13 | * @param height 14 | * @return 15 | */ 16 | public int maxArea(int[] height) { 17 | if (null == height || 2 > height.length) { 18 | return -1; 19 | } 20 | 21 | int i = 0, j = height.length - 1; 22 | int maxArea = 0; 23 | while (i < j) { 24 | maxArea = Math.max(Math.min(height[i], height[j]) * (j - i), maxArea); 25 | 26 | if (height[i] < height[j]) { 27 | ++i; 28 | } else { 29 | --j; 30 | } 31 | } 32 | return maxArea; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution014.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author mayuan 5 | * @desc 6 | * @date 2018/02/08 7 | */ 8 | public class Solution014 { 9 | 10 | public String longestCommonPrefix(String[] strs) { 11 | if (null == strs || 0 == strs.length) { 12 | return ""; 13 | } 14 | 15 | String pre = strs[0]; 16 | for (int i = 1; i < strs.length; ++i) { 17 | while (strs[i].indexOf(pre) != 0) { 18 | pre = pre.substring(0, pre.length() - 1); 19 | } 20 | } 21 | 22 | return pre; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution020.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @author mayuan 7 | * @desc 8 | * @date 2018/02/08 9 | */ 10 | public class Solution020 { 11 | 12 | public boolean isValid(String s) { 13 | if (null == s || (1 == (s.length() & 1))){ 14 | return false; 15 | } 16 | 17 | Stack stack = new Stack<>(); 18 | for (int i=0; i generateParenthesis(int n) { 18 | List ans = new ArrayList<>(); 19 | dfs(ans, "", n, 0, 0); 20 | return ans; 21 | } 22 | 23 | public void dfs(List ans, String oneAnswer, int n, int left, int right) { 24 | if (right == n) { 25 | ans.add(oneAnswer); 26 | return; 27 | } 28 | 29 | // 左括号数量少于 n ,优先添加左括号 30 | if (left < n) { 31 | dfs(ans, oneAnswer + "(", n, left + 1, right); 32 | } 33 | // 右括号数量少于左括号数量 ,添加右括号与左括号配对 34 | if (right < left) { 35 | dfs(ans, oneAnswer + ")", n, left, right + 1); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution024.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/16 7 | */ 8 | public class Solution024 { 9 | public ListNode swapPairs(ListNode head) { 10 | if (null == head || null == head.next) { 11 | return head; 12 | } 13 | 14 | ListNode temp = new ListNode(-1); 15 | temp.next = head; 16 | ListNode p = temp; 17 | 18 | while (null != p.next && null != p.next.next) { 19 | ListNode t = p.next; 20 | p.next = t.next; 21 | t.next = p.next.next; 22 | p.next.next = t; 23 | p = t; 24 | } 25 | return temp.next; 26 | } 27 | 28 | private class ListNode { 29 | int val; 30 | ListNode next; 31 | 32 | ListNode(int x) { 33 | val = x; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution026.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author mayuan 5 | * @desc 删除排序数组中的重复项 6 | * @date 2018/02/09 7 | */ 8 | public class Solution026 { 9 | 10 | public int removeDuplicates(int[] nums) { 11 | // 无重复元素指针,指向存放数据的位置 12 | int i = nums.length > 0 ? 1 : 0; 13 | 14 | for (int number : nums) { 15 | // i-1指向无重复元素数组的末尾 16 | if (nums[i - 1] < number) { 17 | nums[i++] = number; 18 | } 19 | } 20 | 21 | return i; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution027.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author mayuan 5 | * @desc 移除元素 6 | * @date 2018/02/09 7 | */ 8 | public class Solution027 { 9 | 10 | public int removeElement(int[] nums, int val) { 11 | // i指向存放元素的位置 12 | int i = 0; 13 | for(int e : nums){ 14 | if (e != val){ 15 | nums[i++] = e; 16 | } 17 | } 18 | return i; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution035.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author mayuan 5 | * @desc 6 | * @date 2018/02/09 7 | */ 8 | public class Solution035 { 9 | 10 | public int searchInsert(int[] nums, int target) { 11 | if (null == nums || 0 == nums.length) { 12 | return 0; 13 | } 14 | 15 | int low = 0, high = nums.length - 1; 16 | while (low <= high) { 17 | int mid = (low + high) / 2; 18 | if (nums[mid] == target) { 19 | return mid; 20 | } else if (nums[mid] > target) { 21 | high = mid - 1; 22 | } else { 23 | low = mid + 1; 24 | } 25 | } 26 | return low; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution038.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author mayuan 5 | * @desc 6 | * @date 2018/02/09 7 | */ 8 | public class Solution038 { 9 | 10 | public String countAndSay(int n) { 11 | String str = "1"; 12 | while (--n > 0) { 13 | int times = 1; 14 | StringBuilder sb = new StringBuilder(); 15 | char[] chars = str.toCharArray(); 16 | int len = chars.length; 17 | for (int j = 1; j < len; j++) { 18 | if (chars[j - 1] == chars[j]) { 19 | times++; 20 | } else { 21 | sb.append(times).append(chars[j - 1]); 22 | times = 1; 23 | } 24 | } 25 | str = sb.append(times).append(chars[len - 1]).toString(); 26 | } 27 | return str; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution053.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 最大子序和 6 | * @date: 2018/08/17 7 | */ 8 | public class Solution053 { 9 | public static void main(String[] args) { 10 | int[] nums = {-2, 1, -3, 4, -1, 2, 1, -5, 4}; 11 | 12 | Solution053 test = new Solution053(); 13 | System.out.println(test.maxSubArray(nums)); 14 | } 15 | 16 | public int maxSubArray(int[] nums) { 17 | if (null == nums || 0 >= nums.length) { 18 | return 0; 19 | } 20 | 21 | // dp[i]代表以第i个位置结尾,最大子序和 22 | int[] dp = new int[nums.length]; 23 | dp[0] = nums[0]; 24 | int ans = dp[0]; 25 | 26 | for (int i = 1; i < nums.length; ++i) { 27 | dp[i] = Math.max(nums[i] + dp[i - 1], nums[i]); 28 | ans = Math.max(ans, dp[i]); 29 | } 30 | return ans; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution055.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 跳跃游戏 6 | * @date: 2019/01/19 7 | */ 8 | public class Solution055 { 9 | 10 | public boolean canJump(int[] nums) { 11 | if (null == nums || 0 >= nums.length) { 12 | return false; 13 | } 14 | 15 | int farthest = 0; 16 | for (int i = 0; i < nums.length; ++i) { 17 | if (farthest < i) { 18 | return false; 19 | } 20 | farthest = farthest < i + nums[i] ? i + nums[i] : farthest; 21 | } 22 | return true; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution056.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Collections; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * @author: mayuan 9 | * @desc: 合并区间 10 | * @date: 2019/01/13 11 | */ 12 | public class Solution056 { 13 | 14 | public List merge(List intervals) { 15 | if (null == intervals) { 16 | return intervals; 17 | } 18 | 19 | Collections.sort(intervals, (a, b) -> a.start - b.start); 20 | 21 | LinkedList result = new LinkedList<>(); 22 | for (Interval e : intervals) { 23 | if (result.isEmpty() || result.getLast().end < e.start) { 24 | result.add(e); 25 | } else { 26 | result.getLast().end = Math.max(result.getLast().end, e.end); 27 | } 28 | } 29 | return result; 30 | } 31 | 32 | private class Interval { 33 | int start; 34 | int end; 35 | 36 | Interval() { 37 | start = 0; 38 | end = 0; 39 | } 40 | 41 | Interval(int s, int e) { 42 | start = s; 43 | end = e; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution061.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 旋转链表 6 | * @date: 2019/01/03 7 | */ 8 | public class Solution061 { 9 | 10 | public ListNode rotateRight(ListNode head, int k) { 11 | if (null == head || 0 > k) { 12 | return null; 13 | } 14 | 15 | // 获得链表的长度 16 | int cnt = 0; 17 | ListNode tmp = head; 18 | while (null != tmp) { 19 | ++cnt; 20 | tmp = tmp.next; 21 | } 22 | 23 | k %= cnt; 24 | if (0 == k) { 25 | return head; 26 | } 27 | 28 | ListNode fast = head; 29 | ListNode slow = head; 30 | for (int i = 0; i < k; ++i) { 31 | fast = fast.next; 32 | } 33 | 34 | while (null != fast.next) { 35 | fast = fast.next; 36 | slow = slow.next; 37 | } 38 | 39 | fast.next = head; 40 | head = slow.next; 41 | slow.next = null; 42 | return head; 43 | } 44 | 45 | private class ListNode { 46 | int val; 47 | ListNode next; 48 | 49 | ListNode(int x) { 50 | val = x; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution062.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 不同路径 8 | * @date: 2018/08/22 9 | */ 10 | public class Solution062 { 11 | public static void main(String[] args) { 12 | Solution062 test = new Solution062(); 13 | 14 | System.out.println(test.uniquePaths(7, 3)); 15 | System.out.println(test.uniquePaths(3, 2)); 16 | } 17 | 18 | public int uniquePaths(int m, int n) { 19 | // m 指的是列数 20 | int[] dp = new int[m]; 21 | // 初始状态: 第一行的位置(即到达该位置仅有1种走法) 22 | Arrays.fill(dp, 1); 23 | // 每行的第一列的位置(到达该位置也仅有1种走法) 24 | for (int i = 1; i < n; ++i) { 25 | for (int j = 0; j < m; ++j) { 26 | // 到达该位置的方法数为: 从上方走过来的走法数目 + 从左侧方向走过来的走法数目 27 | dp[j] = dp[j] + dp[j - 1]; 28 | } 29 | } 30 | return dp[m - 1]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution063.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 不同路径 II 6 | * @date: 2019/02/17 7 | */ 8 | public class Solution063 { 9 | public int uniquePathsWithObstacles(int[][] obstacleGrid) { 10 | if (null == obstacleGrid || 0 >= obstacleGrid.length) { 11 | return 0; 12 | } 13 | 14 | // 列数 15 | int m = obstacleGrid[0].length; 16 | // dp[i][j]代表走到第(i,j)个位置共多少种路径 17 | int[] dp = new int[m]; 18 | dp[0] = 1; 19 | 20 | for (int[] row : obstacleGrid) { 21 | for (int j = 0; j < m; ++j) { 22 | if (1 == row[j]) { 23 | dp[j] = 0; 24 | } else if (0 < j) { 25 | dp[j] = dp[j] + dp[j - 1]; 26 | } 27 | } 28 | } 29 | 30 | return dp[m - 1]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution064.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 最小路径和 6 | * @date: 2018/08/22 7 | */ 8 | public class Solution064 { 9 | public static void main(String[] args) { 10 | int[][] grid = { 11 | {1, 2}, 12 | {5, 6}, 13 | {1, 1}}; 14 | 15 | Solution064 test = new Solution064(); 16 | System.out.println(test.minPathSum(grid)); 17 | } 18 | 19 | public int minPathSum(int[][] grid) { 20 | if (null == grid || 0 >= grid.length || 0 >= grid[0].length) { 21 | return 0; 22 | } 23 | 24 | // dp[j]代表:到第(i,j)个位置路径数字总和最小值 25 | int[] dp = new int[grid[0].length]; 26 | dp[0] = grid[0][0]; 27 | // 初始化第一行 28 | for (int j = 1; j < dp.length; ++j) { 29 | dp[j] = grid[0][j] + dp[j - 1]; 30 | } 31 | 32 | for (int i = 1; i < grid.length; ++i) { 33 | // 当前行第一列的值为:上一行第一列的值 + 当前位置值 34 | dp[0] = dp[0] + grid[i][0]; 35 | for (int j = 1; j < grid[i].length; ++j) { 36 | dp[j] = Math.min(dp[j], dp[j - 1]) + grid[i][j]; 37 | } 38 | } 39 | return dp[grid[0].length - 1]; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution069.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/08/19 7 | */ 8 | public class Solution069 { 9 | public static void main(String[] args){ 10 | Solution069 test = new Solution069(); 11 | 12 | System.out.println(test.mySqrt(1)); 13 | System.out.println(test.mySqrt(2)); 14 | System.out.println(test.mySqrt(3)); 15 | System.out.println(test.mySqrt(4)); 16 | System.out.println(test.mySqrt(9)); 17 | } 18 | 19 | public int mySqrt(int x) { 20 | if (1 >= x) { 21 | return x; 22 | } 23 | 24 | int left = 1, right = x; 25 | while (left <= right) { 26 | int mid = left + (right - left) / 2; 27 | int sqrt = x / mid; 28 | if (sqrt == mid) { 29 | return sqrt; 30 | } else if (sqrt < mid) { 31 | right = mid - 1; 32 | } else { 33 | left = mid + 1; 34 | } 35 | } 36 | return right; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution080.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 删除排序数组中的重复项 II 6 | * @date: 2019/01/02 7 | */ 8 | public class Solution080 { 9 | 10 | public int removeDuplicates(int[] nums) { 11 | int i = 0; 12 | 13 | for (int e : nums) { 14 | // 数组前两个元素直接放 15 | // 只需要保证最多有2个重复的元素即可 16 | if (2 > i || e != nums[i - 2]) { 17 | nums[i++] = e; 18 | } 19 | } 20 | return i; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution086.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 分隔链表 6 | * @date: 2019/01/03 7 | */ 8 | public class Solution086 { 9 | 10 | public ListNode partition(ListNode head, int x) { 11 | ListNode node1 = new ListNode(0); 12 | ListNode node2 = new ListNode(0); 13 | ListNode p1 = node1, p2 = node2; 14 | 15 | while (null != head) { 16 | if (x > head.val) { 17 | p1.next = head; 18 | p1 = p1.next; 19 | } else { 20 | p2.next = head; 21 | p2 = p2.next; 22 | } 23 | head = head.next; 24 | } 25 | 26 | p2.next = null; 27 | p1.next = node2.next; 28 | return node1.next; 29 | } 30 | 31 | private class ListNode { 32 | int val; 33 | ListNode next; 34 | 35 | ListNode(int x) { 36 | val = x; 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution088.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 合并两个有序数组 6 | * @date: 2018/08/17 7 | */ 8 | public class Solution088 { 9 | public static void main(String[] args) { 10 | Solution088 test = new Solution088(); 11 | 12 | int[] a = new int[]{1, 2, 3, 0, 0, 0}; 13 | int[] b = new int[]{2, 5, 6}; 14 | test.merge(a, 3, b, 3); 15 | 16 | for (int t : a) { 17 | System.out.print(t); 18 | System.out.print(" "); 19 | } 20 | System.out.println(); 21 | } 22 | 23 | public void merge(int[] nums1, int m, int[] nums2, int n) { 24 | int index1 = m - 1; 25 | int index2 = n - 1; 26 | int mergeIndex = m + n - 1; 27 | 28 | while (0 <= index1 || 0 <= index2) { 29 | if (0 > index1) { 30 | nums1[mergeIndex--] = nums2[index2--]; 31 | } else if (0 > index2) { 32 | nums1[mergeIndex--] = nums1[index1--]; 33 | } else if (nums1[index1] <= nums2[index2]) { 34 | nums1[mergeIndex--] = nums2[index2--]; 35 | } else { 36 | nums1[mergeIndex--] = nums1[index1--]; 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution089.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 格雷编码 9 | * @date: 2018/08/12 10 | */ 11 | public class Solution089 { 12 | public static void main(String[] args) { 13 | Solution089 test = new Solution089(); 14 | List ans = test.grayCode(2); 15 | 16 | ans.forEach(System.out::println); 17 | } 18 | 19 | /** 20 | * 此题定义 格雷编码序列必须以 0 开头 21 | * 给定编码总位数为 n 的格雷编码序列,其长度为 2^n。当 n = 0 时,长度为 2^0 = 1。 22 | * 因此,当 n = 0 时,其格雷编码序列为 [0]。 23 | * 24 | * @param n 25 | * @return 26 | */ 27 | public List grayCode(int n) { 28 | List answer = new LinkedList<>(); 29 | for (int i = 0; i < Math.pow(2, n); i++) { 30 | answer.add(i ^ (i >> 1)); 31 | } 32 | return answer; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution096.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 不同的二叉搜索树 6 | * https://leetcode.com/problems/unique-binary-search-trees/discuss/31666/DP-Solution-in-6-lines-with-explanation.-F(i-n)-G(i-1)-*-G(n-i) 7 | * @date: 2019/02/18 8 | */ 9 | public class Solution096 { 10 | public int numTrees(int n) { 11 | int[] dp = new int[n + 1]; 12 | dp[0] = 1; 13 | dp[1] = 1; 14 | 15 | for (int i = 2; i <= n; ++i) { 16 | for (int j = 1; j <= i; ++j) { 17 | dp[i] += dp[j - 1] * dp[i - j]; 18 | } 19 | } 20 | 21 | return dp[n]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution101.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 对称二叉树 6 | * @date: 2019/02/26 7 | */ 8 | public class Solution101 { 9 | 10 | public boolean isSymmetric(TreeNode root) { 11 | if (null == root) { 12 | return true; 13 | } 14 | 15 | return isSymmetric(root.left, root.right); 16 | } 17 | 18 | public boolean isSymmetric(TreeNode left, TreeNode right) { 19 | if (null == left || null == right) { 20 | return left == right; 21 | } 22 | 23 | if (left.val != right.val){ 24 | return false; 25 | } 26 | 27 | return isSymmetric(left.left, right.right) && isSymmetric(left.right, right.left); 28 | } 29 | 30 | public class TreeNode { 31 | int val; 32 | TreeNode left; 33 | TreeNode right; 34 | 35 | TreeNode(int x) { 36 | val = x; 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution102.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | 7 | /** 8 | * @author: mayuan 9 | * @desc: 二叉树的层次遍历 10 | * @date: 2019/02/26 11 | */ 12 | public class Solution102 { 13 | public List> levelOrder(TreeNode root) { 14 | List> ans = new ArrayList<>(); 15 | 16 | if (null == root) { 17 | return ans; 18 | } 19 | 20 | levelOrder(ans, root, 0); 21 | return ans; 22 | } 23 | 24 | public void levelOrder(List> answer, TreeNode node, int depth) { 25 | if (null == node) { 26 | return; 27 | } 28 | 29 | // 遍历到当前层的第一个节点 30 | if (answer.size() <= depth) { 31 | answer.add(new LinkedList<>()); 32 | } 33 | answer.get(depth).add(node.val); 34 | levelOrder(answer, node.left, depth + 1); 35 | levelOrder(answer, node.right, depth + 1); 36 | } 37 | 38 | public class TreeNode { 39 | int val; 40 | TreeNode left; 41 | TreeNode right; 42 | 43 | TreeNode(int x) { 44 | val = x; 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution106.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 从中序与后序遍历序列构造二叉树 6 | * @date: 2019/03/06 7 | */ 8 | public class Solution106 { 9 | public TreeNode buildTree(int[] inorder, int[] postorder) { 10 | return dfs(inorder, postorder, 0, inorder.length - 1, postorder.length - 1); 11 | } 12 | 13 | private TreeNode dfs(int[] inorder, int[] postorder, int inStart, int inEnd, int postEnd) { 14 | if (inStart > inEnd || postEnd < 0) { 15 | return null; 16 | } 17 | 18 | TreeNode node = new TreeNode(postorder[postEnd]); 19 | int inIndex = 0; 20 | for (int i = inEnd; i >= inStart; --i) { 21 | if (inorder[i] == node.val) { 22 | inIndex = i; 23 | break; 24 | } 25 | } 26 | 27 | node.left = dfs(inorder, postorder, inStart, inIndex - 1, postEnd - (inEnd - inIndex + 1)); 28 | node.right = dfs(inorder, postorder, inIndex + 1, inEnd, postEnd - 1); 29 | return node; 30 | } 31 | 32 | private class TreeNode { 33 | int val; 34 | TreeNode left; 35 | TreeNode right; 36 | 37 | TreeNode(int x) { 38 | val = x; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution107.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.LinkedList; 6 | import java.util.List; 7 | 8 | /** 9 | * @author: mayuan 10 | * @desc: 二叉树的层次遍历 II 11 | * @date: 2019/03/07 12 | */ 13 | public class Solution107 { 14 | 15 | public List> levelOrderBottom(TreeNode root) { 16 | List> ans = new ArrayList<>(); 17 | if (null == root) { 18 | return ans; 19 | } 20 | 21 | dfs(ans, root, 0); 22 | Collections.reverse(ans); 23 | return ans; 24 | } 25 | 26 | private void dfs(List> answer, TreeNode node, int depth) { 27 | if (null == node) { 28 | return; 29 | } 30 | 31 | if (answer.size() <= depth) { 32 | answer.add(new LinkedList<>()); 33 | } 34 | answer.get(depth).add(node.val); 35 | 36 | dfs(answer, node.left, depth + 1); 37 | dfs(answer, node.right, depth + 1); 38 | } 39 | 40 | class TreeNode { 41 | int val; 42 | TreeNode left; 43 | TreeNode right; 44 | 45 | TreeNode(int x) { 46 | val = x; 47 | } 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution108.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 将有序数组转换为二叉搜索树 6 | * @date: 2019/03/07 7 | */ 8 | public class Solution108 { 9 | public TreeNode sortedArrayToBST(int[] nums) { 10 | if (null == nums || 0 >= nums.length) { 11 | return null; 12 | } 13 | 14 | return dfs(nums, 0, nums.length - 1); 15 | } 16 | 17 | private TreeNode dfs(int[] nums, int start, int end) { 18 | if (start > end) { 19 | return null; 20 | } 21 | if (start == end) { 22 | return new TreeNode(nums[start]); 23 | } 24 | 25 | int mid = (start + end) >> 1; 26 | TreeNode node = new TreeNode(nums[mid]); 27 | node.left = dfs(nums, start, mid - 1); 28 | node.right = dfs(nums, mid + 1, end); 29 | return node; 30 | } 31 | 32 | class TreeNode { 33 | int val; 34 | TreeNode left; 35 | TreeNode right; 36 | 37 | TreeNode(int x) { 38 | val = x; 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution110.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 平衡二叉树 6 | * @date: 2019/03/07 7 | */ 8 | public class Solution110 { 9 | 10 | public boolean isBalanced(TreeNode root) { 11 | return dfs(root) != -1; 12 | } 13 | 14 | public int dfs(TreeNode root) { 15 | if (null == root) { 16 | return 0; 17 | } 18 | 19 | int leftHeight = dfs(root.left); 20 | if (leftHeight == -1) { 21 | return -1; 22 | } 23 | int rightHeight = dfs(root.right); 24 | if (rightHeight == -1) { 25 | return -1; 26 | } 27 | 28 | if (Math.abs(leftHeight - rightHeight) > 1) { 29 | return -1; 30 | } 31 | return Math.max(leftHeight, rightHeight) + 1; 32 | } 33 | 34 | class TreeNode { 35 | int val; 36 | TreeNode left; 37 | TreeNode right; 38 | 39 | TreeNode(int x) { 40 | val = x; 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution111.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 二叉树的最小深度 6 | * @date: 2019/03/07 7 | */ 8 | public class Solution111 { 9 | 10 | public int minDepth(TreeNode root) { 11 | if (null == root) { 12 | return 0; 13 | } 14 | 15 | int l = minDepth(root.left); 16 | int r = minDepth(root.right); 17 | 18 | if (0 == l || 0 == r) { 19 | return l + r + 1; 20 | } else { 21 | return Math.min(l, r) + 1; 22 | } 23 | } 24 | 25 | class TreeNode { 26 | int val; 27 | TreeNode left; 28 | TreeNode right; 29 | 30 | TreeNode(int x) { 31 | val = x; 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution112.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 路径总和 6 | * @date: 2019/03/09 7 | */ 8 | public class Solution112 { 9 | public boolean hasPathSum(TreeNode root, int sum) { 10 | if (null == root) { 11 | return false; 12 | } 13 | 14 | if (null == root.left && null == root.right && sum == root.val) { 15 | return true; 16 | } 17 | 18 | return hasPathSum(root.left, sum - root.val) 19 | || hasPathSum(root.right, sum - root.val); 20 | } 21 | 22 | class TreeNode { 23 | int val; 24 | TreeNode left; 25 | TreeNode right; 26 | 27 | TreeNode(int x) { 28 | val = x; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution114.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 二叉树展开为链表 6 | * @date: 2019/03/09 7 | */ 8 | public class Solution114 { 9 | 10 | private TreeNode prev = null; 11 | 12 | public void flatten(TreeNode root) { 13 | if (null == root) { 14 | return; 15 | } 16 | 17 | flatten(root.right); 18 | flatten(root.left); 19 | root.right = prev; 20 | root.left = null; 21 | prev = root; 22 | } 23 | 24 | public class TreeNode { 25 | int val; 26 | TreeNode left; 27 | TreeNode right; 28 | 29 | TreeNode(int x) { 30 | val = x; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution121.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 买卖股票的最佳时机 6 | * @date: 2019/01/28 7 | */ 8 | public class Solution121 { 9 | 10 | public int maxProfit(int[] prices) { 11 | if (null == prices || 1 >= prices.length) { 12 | return 0; 13 | } 14 | 15 | int profile = 0; 16 | int bottom = prices[0]; 17 | for (int i = 1; i < prices.length; ++i) { 18 | if (prices[i] >= bottom) { 19 | profile = Math.max(profile, prices[i] - bottom); 20 | } else { 21 | // 出现新的底部 22 | bottom = prices[i]; 23 | } 24 | } 25 | return profile; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution122.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 买卖股票的最佳时机 II 6 | * @date: 2018/08/19 7 | */ 8 | public class Solution122 { 9 | 10 | /** 11 | * 由于可以多次买卖股票: 12 | * 对于 [a, b, c, d],如果有 a <= b <= c <= d ,那么最大收益为 d - a。 13 | * 而 d - a = (d - c) + (c - b) + (b - a) ,因此当访问到一个 prices[i] 且 prices[i] - prices[i-1] > 0, 14 | * 那么就把 prices[i] - prices[i-1] 添加到收益中,从而在局部最优的情况下也保证全局最优。 15 | * 16 | * @param prices 17 | * @return 18 | */ 19 | public int maxProfit(int[] prices) { 20 | if (null == prices || 0 >= prices.length) { 21 | return 0; 22 | } 23 | 24 | int profit = 0; 25 | for (int i = 1; i < prices.length; ++i) { 26 | if (prices[i - 1] < prices[i]) { 27 | profit += (prices[i] - prices[i - 1]); 28 | } 29 | } 30 | return profit; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution123.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 买卖股票的最佳时机 III 6 | * @date: 2019/01/28 7 | */ 8 | public class Solution123 { 9 | 10 | /** 11 | * buy first -> sell first -> buy second -> sell second 12 | * 13 | * @param prices 14 | * @return 15 | */ 16 | public int maxProfit(int[] prices) { 17 | if (null == prices || 1 >= prices.length) { 18 | return 0; 19 | } 20 | 21 | int buy1 = Integer.MIN_VALUE, sell1 = 0; 22 | int buy2 = Integer.MIN_VALUE, sell2 = 0; 23 | for (int e : prices) { 24 | buy1 = Math.max(buy1, -e); 25 | sell1 = Math.max(sell1, buy1 + e); 26 | buy2 = Math.max(buy2, sell1 - e); 27 | sell2 = Math.max(sell2, buy2 + e); 28 | } 29 | return sell2; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution129.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 求根到叶子节点数字之和 6 | * @date: 2019/03/09 7 | */ 8 | public class Solution129 { 9 | 10 | public int sumNumbers(TreeNode root) { 11 | if (null == root) { 12 | return 0; 13 | } 14 | 15 | return dfs(root, 0); 16 | } 17 | 18 | public int dfs(TreeNode node, int sum) { 19 | if (null == node) { 20 | return 0; 21 | } 22 | 23 | int curNumber = sum * 10 + node.val; 24 | // 当前节点为叶子节点 25 | if (null == node.left && null == node.right) { 26 | return curNumber; 27 | } else { 28 | // 非叶子节点 29 | return dfs(node.left, curNumber) + dfs(node.right, curNumber); 30 | } 31 | } 32 | 33 | public class TreeNode { 34 | int val; 35 | TreeNode left; 36 | TreeNode right; 37 | 38 | TreeNode(int x) { 39 | val = x; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution134.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 加油站 6 | * @date: 2019/01/19 7 | */ 8 | public class Solution134 { 9 | 10 | public int canCompleteCircuit(int[] gas, int[] cost) { 11 | int debt = 0, remain = 0; 12 | int start = 0; 13 | 14 | for (int i = 0; i < gas.length; ++i) { 15 | remain += gas[i] - cost[i]; 16 | // 环路,最终还要回到出发点,欠款总是要还上的 17 | if (0 > remain) { 18 | debt += remain; 19 | start = i + 1; 20 | remain = 0; 21 | } 22 | } 23 | return remain + debt < 0 ? -1 : start; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution136.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 只出现一次的数字 6 | * @date: 2019/01/29 7 | */ 8 | public class Solution136 { 9 | 10 | public int singleNumber(int[] nums) { 11 | if (null == nums || 0 >= nums.length) { 12 | return 0; 13 | } 14 | 15 | int ans = 0; 16 | for (int e : nums) { 17 | ans ^= e; 18 | } 19 | return ans; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution137.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 只出现一次的数字 II 6 | * @date: 2019/01/30 7 | */ 8 | public class Solution137 { 9 | 10 | public static void main(String[] args) { 11 | int[] nums = {2, 2, 3, 2}; 12 | System.out.println(new Solution137().singleNumber(nums)); 13 | } 14 | 15 | public int singleNumber(int[] nums) { 16 | if (null == nums || 1 > nums.length) { 17 | return 0; 18 | } 19 | 20 | int ans = 0; 21 | for (int i = 0; i < 32; ++i) { 22 | int sum = 0; 23 | for (int e : nums) { 24 | if (1 == ((e >>> i) & 1)) { 25 | ++sum; 26 | } 27 | } 28 | 29 | if (0 != sum % 3) { 30 | ans |= 1 << i; 31 | } 32 | } 33 | return ans; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution139.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 单词拆分 8 | * @date: 2018/08/23 9 | */ 10 | public class Solution139 { 11 | public boolean wordBreak(String s, List wordDict) { 12 | int n = s.length(); 13 | // dp[i] 表示以第i个字符结尾的字符串是否可以拆分为一个或多个在字典中出现的单词 14 | boolean[] dp = new boolean[n + 1]; 15 | dp[0] = true; 16 | for (int i = 1; i <= n; ++i) { 17 | for (String word : wordDict) { 18 | int len = word.length(); 19 | if (i >= len && word.equals(s.substring(i - len, i))) { 20 | dp[i] = dp[i] || dp[i - len]; 21 | } 22 | } 23 | } 24 | return dp[n]; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution141.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 环形链表 6 | * @date: 2019/01/04 7 | */ 8 | public class Solution141 { 9 | 10 | public boolean hasCycle(ListNode head) { 11 | if (null == head) { 12 | return false; 13 | } 14 | 15 | ListNode slow = head, fast = head; 16 | while (null != fast && null != fast.next) { 17 | fast = fast.next.next; 18 | slow = slow.next; 19 | 20 | if (slow == fast) { 21 | return true; 22 | } 23 | } 24 | return false; 25 | } 26 | 27 | private class ListNode { 28 | int val; 29 | ListNode next; 30 | 31 | ListNode(int x) { 32 | val = x; 33 | next = null; 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution142.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 环形链表 II 6 | * @date: 2019/01/04 7 | */ 8 | public class Solution142 { 9 | 10 | public ListNode detectCycle(ListNode head) { 11 | if (null == head) { 12 | return null; 13 | } 14 | 15 | boolean isCycle = false; 16 | ListNode slow = head, fast = head; 17 | while (null != fast && null != fast.next) { 18 | fast = fast.next.next; 19 | slow = slow.next; 20 | 21 | if (slow == fast) { 22 | isCycle = true; 23 | break; 24 | } 25 | } 26 | 27 | if (!isCycle) { 28 | return null; 29 | } 30 | fast = head; 31 | while (fast != slow) { 32 | fast = fast.next; 33 | slow = slow.next; 34 | } 35 | return slow; 36 | } 37 | 38 | class ListNode { 39 | int val; 40 | ListNode next; 41 | 42 | ListNode(int x) { 43 | val = x; 44 | next = null; 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution144.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 二叉树的前序遍历 9 | * @date: 2019/03/09 10 | */ 11 | public class Solution144 { 12 | public List preorderTraversal(TreeNode root) { 13 | List ans = new LinkedList<>(); 14 | if (null == root) { 15 | return ans; 16 | } 17 | 18 | LinkedList stack = new LinkedList<>(); 19 | stack.push(root); 20 | 21 | while (!stack.isEmpty()) { 22 | TreeNode cur = stack.pop(); 23 | ans.add(cur.val); 24 | 25 | if (null != cur.right) { 26 | stack.push(cur.right); 27 | } 28 | if (null != cur.left) { 29 | stack.push(cur.left); 30 | } 31 | } 32 | 33 | return ans; 34 | } 35 | 36 | public class TreeNode { 37 | int val; 38 | TreeNode left; 39 | TreeNode right; 40 | 41 | TreeNode(int x) { 42 | val = x; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution144a.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/08/17 7 | */ 8 | public class Solution144a { 9 | public static void main(String[] args) { 10 | 11 | } 12 | 13 | public boolean hasCycle(ListNode head) { 14 | if (null == head) { 15 | return false; 16 | } 17 | 18 | ListNode slow = head; 19 | ListNode fast = head.next; 20 | 21 | while (null != fast && null != fast.next && null != slow) { 22 | if (slow == fast) { 23 | return true; 24 | } 25 | 26 | slow = slow.next; 27 | fast = fast.next.next; 28 | } 29 | return false; 30 | } 31 | 32 | class ListNode { 33 | int val; 34 | ListNode next; 35 | 36 | ListNode(int x) { 37 | val = x; 38 | next = null; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution152.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 乘积最大子序列 6 | * @date: 2019/02/17 7 | */ 8 | public class Solution152 { 9 | public int maxProduct(int[] nums) { 10 | if (null == nums || 0 >= nums.length) { 11 | return 0; 12 | } 13 | 14 | int ans = nums[0]; 15 | for (int i = 1, mx = nums[0], mn = nums[0]; i < nums.length; ++i) { 16 | // 以当前位置结尾,乘积最大的连续子序列有以下几种情况: 17 | // 1. 当前元素为正数,从前一状态挑选最大值转移过来 18 | // 2. 当前元素为负数,从前一状态挑选最小值转移过来(负负得正) 19 | // 3. 前一状态为0, 从前一状态或当前元素选择最大值 20 | int a = mx * nums[i]; 21 | int b = mn * nums[i]; 22 | mx = Math.max(Math.max(a, b), nums[i]); 23 | mn = Math.min(Math.min(a, b), nums[i]); 24 | if (mx > ans) { 25 | ans = mx; 26 | } 27 | } 28 | 29 | return ans; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution153.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/08/20 7 | */ 8 | public class Solution153 { 9 | public static void main(String[] args) { 10 | int[] nums = {3, 4, 5, 1, 2}; 11 | 12 | Solution153 test = new Solution153(); 13 | System.out.println(test.findMin(nums)); 14 | } 15 | 16 | public int findMin(int[] nums) { 17 | int left = 0; 18 | int right = nums.length - 1; 19 | while (left < right) { 20 | int mid = left + (right - left) / 2; 21 | if (nums[mid] <= nums[right]) { 22 | right = mid; 23 | } else { 24 | left = mid + 1; 25 | } 26 | } 27 | return nums[left]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution167.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 两数之和 II - 输入有序数组 6 | * @date: 2018/08/17 7 | */ 8 | public class Solution167 { 9 | public static void main(String[] args) { 10 | int[] nums = {2, 7, 11, 15}; 11 | int target = 9; 12 | 13 | Solution167 test = new Solution167(); 14 | for (int t : test.twoSum(nums, target)) { 15 | System.out.println(t); 16 | } 17 | } 18 | 19 | public int[] twoSum(int[] numbers, int target) { 20 | int[] answer = new int[2]; 21 | if (null == numbers || 2 > numbers.length) { 22 | return answer; 23 | } 24 | 25 | int left = 0; 26 | int right = numbers.length - 1; 27 | while (left < right) { 28 | int temp = numbers[left] + numbers[right]; 29 | if (target == temp) { 30 | answer[0] = left + 1; 31 | answer[1] = right + 1; 32 | break; 33 | } else if (target > temp) { 34 | ++left; 35 | } else { 36 | --right; 37 | } 38 | } 39 | return answer; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution179.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 最大数 8 | * @date: 2019/01/14 9 | */ 10 | public class Solution179 { 11 | 12 | public static void main(String[] args) { 13 | int[] nums = {3, 30, 34, 5, 9}; 14 | System.out.println(new Solution179().largestNumber(nums)); 15 | } 16 | 17 | public String largestNumber(int[] nums) { 18 | if (null == nums || 0 >= nums.length) { 19 | return "0"; 20 | } 21 | 22 | String[] strNums = new String[nums.length]; 23 | for (int i = 0; i < nums.length; ++i) { 24 | strNums[i] = String.valueOf(nums[i]); 25 | } 26 | Arrays.sort(strNums, (a, b) -> (b + a).compareTo(a + b)); 27 | 28 | // 特殊情况处理: [0, 0, 0] -> 0 29 | if ('0' == strNums[0].charAt(0)) { 30 | return "0"; 31 | } 32 | 33 | StringBuilder stringBuilder = new StringBuilder(); 34 | for (String e : strNums) { 35 | stringBuilder.append(e); 36 | } 37 | 38 | return stringBuilder.toString(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution199.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 二叉树的右视图 9 | * @date: 2019/03/13 10 | */ 11 | public class Solution199 { 12 | public List rightSideView(TreeNode root) { 13 | List ans = new LinkedList<>(); 14 | if (null == root) { 15 | return ans; 16 | } 17 | 18 | dfs(ans, root, 0); 19 | return ans; 20 | } 21 | 22 | public void dfs(List answer, TreeNode node, int depth) { 23 | if (null == node) { 24 | return; 25 | } 26 | 27 | if (answer.size() == depth) { 28 | answer.add(node.val); 29 | } 30 | // 必须先右子树,因为右子树添加节点后左子树就无法添加节点 31 | dfs(answer, node.right, depth + 1); 32 | dfs(answer, node.left, depth + 1); 33 | } 34 | 35 | public class TreeNode { 36 | int val; 37 | TreeNode left; 38 | TreeNode right; 39 | 40 | TreeNode(int x) { 41 | val = x; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution206.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/11/22 7 | */ 8 | public class Solution206 { 9 | 10 | public ListNode reverseList(ListNode head) { 11 | if (null == head) { 12 | return head; 13 | } 14 | 15 | ListNode pre = null; 16 | ListNode cur = head; 17 | head = head.next; 18 | 19 | while (null != cur) { 20 | cur.next = pre; 21 | 22 | pre = cur; 23 | cur = head; 24 | if (null != head){ 25 | head = head.next; 26 | } 27 | } 28 | 29 | return pre; 30 | } 31 | 32 | 33 | class ListNode { 34 | int val; 35 | ListNode next; 36 | 37 | ListNode(int x) { 38 | val = x; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution209.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 长度最小的子数组 6 | * @date: 2019/01/04 7 | */ 8 | public class Solution209 { 9 | 10 | public int minSubArrayLen(int s, int[] nums) { 11 | if (0 > s || null == nums || 1 > nums.length) { 12 | return 0; 13 | } 14 | 15 | int i = 0, j = -1; 16 | int sum = 0; 17 | int len = nums.length + 1; 18 | while (i < nums.length) { 19 | if (j < nums.length - 1 && sum < s) { 20 | ++j; 21 | sum += nums[j]; 22 | } else { 23 | sum -= nums[i]; 24 | ++i; 25 | } 26 | 27 | if (sum >= s) { 28 | len = len < j - i + 1 ? len : j - i + 1; 29 | } 30 | } 31 | if (len == nums.length + 1) { 32 | return 0; 33 | } else { 34 | return len; 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution220.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 存在重复元素 III 9 | * @date: 2019/03/02 10 | */ 11 | public class Solution220 { 12 | 13 | public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) { 14 | if (k < 1 || t < 0) { 15 | return false; 16 | } 17 | 18 | Map map = new HashMap<>(k); 19 | for (int i = 0; i < nums.length; ++i) { 20 | long remappedNum = (long) nums[i] - Integer.MIN_VALUE; 21 | long bucket = remappedNum / ((long) t + 1); 22 | 23 | if (map.containsKey(bucket) 24 | || (map.containsKey(bucket - 1) && remappedNum - map.get(bucket - 1) <= t) 25 | || (map.containsKey(bucket + 1) && map.get(bucket + 1) - remappedNum <= t)) { 26 | return true; 27 | } 28 | 29 | if (map.size() >= k) { 30 | long lastBucket = ((long) nums[i - k] - Integer.MIN_VALUE) / ((long) t + 1); 31 | map.remove(lastBucket); 32 | } 33 | map.put(bucket, remappedNum); 34 | } 35 | return false; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution221.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 最大正方形 6 | * @date: 2019/02/21 7 | */ 8 | public class Solution221 { 9 | public int maximalSquare(char[][] matrix) { 10 | if (null == matrix || 0 >= matrix.length) { 11 | return 0; 12 | } 13 | 14 | int m = matrix.length, n = matrix[0].length; 15 | // dp[i][j]表示:以第(i,j)个元素为正方形右下角元素时,最大的边长. 16 | int[][] dp = new int[m + 1][n + 1]; 17 | int ans = 0; 18 | for (int i = 1; i <= m; ++i) { 19 | for (int j = 1; j <= n; ++j) { 20 | // 如果当前位置为1 21 | if ('1' == matrix[i - 1][j - 1]) { 22 | dp[i][j] = Math.min(Math.min(dp[i][j - 1], dp[i - 1][j - 1]), dp[i - 1][j]) + 1; 23 | if (dp[i][j] > ans) { 24 | ans = dp[i][j]; 25 | } 26 | } 27 | } 28 | } 29 | return ans * ans; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution226.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 翻转二叉树 6 | * @date: 2019/03/05 7 | */ 8 | public class Solution226 { 9 | 10 | public TreeNode invertTree(TreeNode root) { 11 | if (null == root) { 12 | return root; 13 | } 14 | 15 | TreeNode tmp = root.left; 16 | root.left = root.right; 17 | root.right = tmp; 18 | 19 | invertTree(root.left); 20 | invertTree(root.right); 21 | return root; 22 | } 23 | 24 | 25 | public class TreeNode { 26 | int val; 27 | TreeNode left; 28 | TreeNode right; 29 | 30 | TreeNode(int x) { 31 | val = x; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution236.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 二叉树的最近公共祖先 6 | * @date: 2018/12/02 7 | */ 8 | public class Solution236 { 9 | 10 | /** 11 | * 在root为根的二叉树中找A,B的LCA: 12 | * 如果找到了就返回这个LCA 13 | * 如果只碰到A,就返回A 14 | * 如果只碰到B,就返回B 15 | * 如果都没有,就返回null 16 | * 17 | * @param root 18 | * @param p 19 | * @param q 20 | * @return 21 | */ 22 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 23 | if (null == root || p == root || q == root) { 24 | return root; 25 | } 26 | 27 | TreeNode left = lowestCommonAncestor(root.left, p, q); 28 | TreeNode right = lowestCommonAncestor(root.right, p, q); 29 | if (null != left && null != right) { 30 | return root; 31 | } 32 | 33 | return null != left ? left : right; 34 | } 35 | 36 | private static class TreeNode { 37 | int val; 38 | TreeNode left; 39 | TreeNode right; 40 | 41 | TreeNode(int x) { 42 | val = x; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution242.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 有效的字母异位词 6 | * @date: 2019/01/14 7 | */ 8 | public class Solution242 { 9 | 10 | public boolean isAnagram(String s, String t) { 11 | if (null == s || null == t || s.length() != t.length()) { 12 | return false; 13 | } 14 | 15 | // 存储26个小写英文字母出现的次数 16 | int[] map = new int[26]; 17 | for (int i = 0; i < s.length(); ++i) { 18 | ++map[s.charAt(i) - 'a']; 19 | --map[t.charAt(i) - 'a']; 20 | } 21 | 22 | for (int e : map) { 23 | if (0 != e) { 24 | return false; 25 | } 26 | } 27 | return true; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution260.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 只出现一次的数字 III 6 | * @date: 2019/01/30 7 | */ 8 | public class Solution260 { 9 | 10 | public static void main(String[] args) { 11 | int[] nums = {2, 1, 2, 3, 4, 1}; 12 | 13 | for (int e : new Solution260().singleNumber(nums)) { 14 | System.out.print(e + " "); 15 | } 16 | } 17 | 18 | public int[] singleNumber(int[] nums) { 19 | int[] ans = new int[2]; 20 | if (null == nums || 0 >= nums.length) { 21 | return ans; 22 | } 23 | 24 | int diff = 0; 25 | for (int e : nums) { 26 | diff ^= e; 27 | } 28 | 29 | // 取最右侧1位的1 30 | diff &= -diff; 31 | 32 | for (int e : nums) { 33 | if (0 == (e & diff)) { 34 | ans[0] ^= e; 35 | } else { 36 | ans[1] ^= e; 37 | } 38 | } 39 | return ans; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution264.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 丑数 II 6 | * @date: 2019/02/22 7 | */ 8 | public class Solution264 { 9 | public int nthUglyNumber(int n) { 10 | // dp[i]代表第i个丑数 11 | int[] dp = new int[n + 1]; 12 | // 第一个丑数为1 13 | dp[1] = 1; 14 | 15 | int index2 = 1, index3 = 1, index5 = 1; 16 | int factor2 = 2, factor3 = 3, factor5 = 5; 17 | for (int i = 2; i <= n; ++i) { 18 | int mn = Math.min(Math.min(factor2, factor3), factor5); 19 | dp[i] = mn; 20 | 21 | if (mn == factor2) { 22 | factor2 = 2 * dp[++index2]; 23 | } 24 | if (mn == factor3) { 25 | factor3 = 3 * dp[++index3]; 26 | } 27 | if (mn == factor5) { 28 | factor5 = 5 * dp[++index5]; 29 | } 30 | } 31 | return dp[n]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution274.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: H指数 6 | * @date: 2019/01/14 7 | */ 8 | public class Solution274 { 9 | 10 | public int hIndex(int[] citations) { 11 | if (null == citations || 0 >= citations.length) { 12 | return 0; 13 | } 14 | 15 | int N = citations.length; 16 | int[] buckets = new int[citations.length + 1]; 17 | for (int i = 0; i < N; ++i) { 18 | if (citations[i] >= N) { 19 | ++buckets[N]; 20 | } else { 21 | ++buckets[citations[i]]; 22 | } 23 | } 24 | 25 | int cnt = 0; 26 | for (int i = N; i >= 0; --i) { 27 | cnt += buckets[i]; 28 | if (i <= cnt) { 29 | return i; 30 | } 31 | } 32 | return 0; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution278.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/08/20 7 | */ 8 | public class Solution278 extends VersionControl { 9 | public static void main(String[] args) { 10 | 11 | } 12 | 13 | public int firstBadVersion(int n) { 14 | int left = 1, right = n; 15 | while (left < right) { 16 | int mid = left + (right - left) / 2; 17 | if (isBadVersion(mid)) { 18 | right = mid; 19 | } else { 20 | left = mid + 1; 21 | } 22 | } 23 | return left; 24 | } 25 | } 26 | 27 | /** 28 | * 仅作为示例 29 | */ 30 | class VersionControl { 31 | boolean isBadVersion(int version) { 32 | return true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution283.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 移动零 6 | * @date: 2019/01/04 7 | */ 8 | public class Solution283 { 9 | 10 | public static void main(String[] args) { 11 | int[] numbers = {0, 1, 0, 3, 12}; 12 | new Solution283().moveZeroes(numbers); 13 | 14 | for (int i = 0; i < numbers.length; ++i) { 15 | System.out.print(numbers[i]); 16 | System.out.print(" "); 17 | } 18 | } 19 | 20 | public void moveZeroes(int[] nums) { 21 | if (null == nums || 1 >= nums.length) { 22 | return; 23 | } 24 | 25 | int i = 0, j = 0; 26 | for (; j < nums.length; ++j) { 27 | if (0 != nums[j]) { 28 | nums[i++] = nums[j]; 29 | } 30 | } 31 | 32 | for (; i < nums.length; ++i) { 33 | nums[i] = 0; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution287.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 寻找重复数 6 | * @date: 2019/01/06 7 | */ 8 | public class Solution287 { 9 | 10 | /** 11 | * 与链表中有环,判断环的入口问题相似 12 | * @param nums 13 | * @return 14 | */ 15 | public int findDuplicate(int[] nums) { 16 | if (null == nums || 1 >= nums.length) { 17 | return -1; 18 | } 19 | 20 | int slow = nums[0]; 21 | int fast = nums[nums[0]]; 22 | while (fast != slow) { 23 | fast = nums[nums[fast]]; 24 | slow = nums[slow]; 25 | } 26 | 27 | fast = 0; 28 | while (fast != slow) { 29 | fast = nums[fast]; 30 | slow = nums[slow]; 31 | } 32 | return slow; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution300.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 最长上升子序列 6 | * @date: 2018/08/22 7 | */ 8 | public class Solution300 { 9 | public static void main(String[] args) { 10 | int[] nums = {10, 9, 2, 5, 3, 7, 101, 18}; 11 | 12 | Solution300 test = new Solution300(); 13 | System.out.println(test.lengthOfLIS(nums)); 14 | } 15 | 16 | public int lengthOfLIS(int[] nums) { 17 | if (null == nums || 0 >= nums.length) { 18 | return 0; 19 | } 20 | 21 | int ans = Integer.MIN_VALUE; 22 | // dp[i]表示:以第i个位置结尾的最长上升子序列 23 | int[] dp = new int[nums.length]; 24 | for (int i = 0; i < nums.length; ++i) { 25 | int mx = 1; 26 | for (int j = 0; j < i; ++j) { 27 | if (nums[i] > nums[j]) { 28 | mx = Math.max(mx, dp[j] + 1); 29 | } 30 | } 31 | dp[i] = mx; 32 | if (dp[i] > ans) { 33 | ans = dp[i]; 34 | } 35 | } 36 | 37 | return ans; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution303.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 区域和检索 - 数组不可变 6 | * @date: 2018/08/22 7 | */ 8 | public class Solution303 { 9 | 10 | private int[] nums; 11 | 12 | public Solution303(int[] nums) { 13 | this.nums = nums; 14 | for (int i = 1; i < nums.length; ++i) { 15 | this.nums[i] = this.nums[i - 1] + this.nums[i]; 16 | } 17 | } 18 | 19 | public int sumRange(int i, int j) { 20 | if (1 <= i) { 21 | return this.nums[j] - this.nums[i - 1]; 22 | } else { 23 | return this.nums[j]; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution304.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 二维区域和检索 - 矩阵不可变 6 | * @date: 2019/02/23 7 | */ 8 | public class Solution304 { 9 | /** 10 | * dp[i][j] 表示从第(1,1)到第(i,j)范围的和,即从左上角到该位置范围的和 11 | */ 12 | private int[][] dp; 13 | 14 | public Solution304(int[][] matrix) { 15 | if (null == matrix || 0 >= matrix.length || 0 >= matrix[0].length) { 16 | return; 17 | } 18 | 19 | int m = matrix.length; 20 | int n = matrix[0].length; 21 | dp = new int[m+1][n+1]; 22 | for (int i = 1; i <= m; ++i) { 23 | for (int j = 1; j <= n; ++j) { 24 | dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + matrix[i - 1][j - 1]; 25 | } 26 | } 27 | } 28 | 29 | public int sumRegion(int row1, int col1, int row2, int col2) { 30 | return dp[row2 + 1][col2 + 1] - dp[row2 + 1][col1] - dp[row1][col2 + 1] + dp[row1][col1]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution322.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 零钱兑换 8 | * @date: 2018/08/23 9 | */ 10 | public class Solution322 { 11 | public int coinChange(int[] coins, int amount) { 12 | if (null == coins || 0 >= coins.length || 0 > amount) { 13 | return 0; 14 | } 15 | 16 | Arrays.sort(coins); 17 | int[] dp = new int[amount + 1]; 18 | // 最多用 amount 个 1元硬币,故此处初始化为 amount+1 用于判断是否能够凑齐 19 | Arrays.fill(dp, amount + 1); 20 | dp[0] = 0; 21 | 22 | for (int i = 1; i <= amount; ++i) { 23 | for (int j = 0; j < coins.length && coins[j] <= i; ++j) { 24 | dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1); 25 | } 26 | } 27 | return (dp[amount] > amount) ? -1 : dp[amount]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution337.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 打家劫舍 III 6 | * @date: 2019/03/12 7 | */ 8 | public class Solution337 { 9 | public int rob(TreeNode root) { 10 | int[] ans = dfs(root); 11 | return Math.max(ans[0], ans[1]); 12 | } 13 | 14 | public int[] dfs(TreeNode node) { 15 | if (null == node) { 16 | return new int[2]; 17 | } 18 | 19 | int[] left = dfs(node.left); 20 | int[] right = dfs(node.right); 21 | int[] ans = new int[2]; 22 | // ans[0] 表示不抢劫该节点,则可获得的最大收益为,左子树和右子树的最大收益之和 23 | ans[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]); 24 | // ans[1] 表示抢劫该节点,则可获得的最大收益为,不可抢直接相邻的左子树和右子树节点的收益之和 25 | ans[1] = node.val + left[0] + right[0]; 26 | return ans; 27 | } 28 | 29 | public class TreeNode { 30 | int val; 31 | TreeNode left; 32 | TreeNode right; 33 | 34 | TreeNode(int x) { 35 | val = x; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution338.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 比特位计数 6 | * @date: 2019/02/24 7 | */ 8 | public class Solution338 { 9 | public int[] countBits(int num) { 10 | int[] dp = new int[num + 1]; 11 | 12 | for (int i = 1; i <= num; ++i) { 13 | dp[i] = dp[i >>> 1] + (i & 1); 14 | } 15 | return dp; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution343.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 整数拆分 6 | * @date: 2018/08/22 7 | */ 8 | public class Solution343 { 9 | public static void main(String[] args) { 10 | Solution343 test = new Solution343(); 11 | 12 | System.out.println(test.integerBreak(10)); 13 | System.out.println(test.integerBreak2(10)); 14 | } 15 | 16 | public int integerBreak(int n) { 17 | // 第 n 个位置表示:数字 n 分解后可获得的最大乘积 18 | int[] dp = new int[n + 1]; 19 | for (int i = 1; i <= n; ++i) { 20 | for (int j = 1; j < i; ++j) { 21 | dp[i] = Math.max(dp[i], Math.max(j * dp[i - j], j * (i - j))); 22 | } 23 | } 24 | return dp[n]; 25 | } 26 | 27 | public int integerBreak2(int n) { 28 | int ans = 1; 29 | 30 | if (4 >= n) { 31 | return (4 == n) ? 4 : n - 1; 32 | } 33 | 34 | // 分解该数字后,数字3的数量越多,乘积越大 35 | while (4 < n) { 36 | ans *= 3; 37 | n -= 3; 38 | } 39 | 40 | return ans * n; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution344.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 反转字符串 6 | * @date: 2019/01/06 7 | */ 8 | public class Solution344 { 9 | 10 | public String reverseString(String s) { 11 | if (null == s || 1 >= s.length()) { 12 | return s; 13 | } 14 | 15 | char[] words = s.toCharArray(); 16 | int i = 0, j = words.length - 1; 17 | while (i < j) { 18 | swap(words, i, j); 19 | ++i; 20 | --j; 21 | } 22 | return new String(words); 23 | } 24 | 25 | public static void swap(char[] array, int i, int j) { 26 | char tmp = array[i]; 27 | array[i] = array[j]; 28 | array[j] = tmp; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution349.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | /** 7 | * @author Administrator 8 | * @desc 两个数组的交集 9 | * @create 2019/01/08 10 | */ 11 | public class Solution349 { 12 | 13 | public int[] intersection(int[] nums1, int[] nums2) { 14 | Set set = new HashSet<>(nums1.length); 15 | Set intersect = new HashSet<>(nums2.length); 16 | 17 | for (int i = 0; i < nums1.length; ++i) { 18 | set.add(nums1[i]); 19 | } 20 | for (int i = 0; i < nums2.length; ++i) { 21 | if (set.contains(nums2[i])) { 22 | intersect.add(nums2[i]); 23 | } 24 | } 25 | 26 | int[] ans = new int[intersect.size()]; 27 | int i = 0; 28 | for (Integer n : intersect) { 29 | ans[i++] = n; 30 | } 31 | return ans; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution357.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 计算各个位数不同的数字个数 6 | * @date: 2019/02/16 7 | */ 8 | public class Solution357 { 9 | 10 | public int countNumbersWithUniqueDigits(int n) { 11 | int[] f = new int[11]; 12 | f[0] = 1; 13 | f[1] = 10; 14 | f[2] = 81; 15 | 16 | for (int i = 3, num = 8; i < f.length; ++i) { 17 | f[i] = f[i - 1] * num; 18 | if (1 < num) { 19 | --num; 20 | } 21 | } 22 | for (int i = 2; i < f.length; ++i) { 23 | f[i] += f[i - 1]; 24 | } 25 | 26 | return 11 > n ? f[n] : f[10]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution375.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 猜数字大小 II 6 | * @date: 2019/02/25 7 | */ 8 | public class Solution375 { 9 | public int getMoneyAmount(int n) { 10 | int[][] dp = new int[n + 1][n + 1]; 11 | dfs(dp, 1, n); 12 | return dp[1][n]; 13 | } 14 | 15 | public int dfs(int[][] dp, int start, int end) { 16 | // [start,end]范围仅1个数字,不需任何代价 17 | if (start >= end) { 18 | return 0; 19 | } 20 | // 当前范围最小需要付出的代价已经计算过,直接返回该值 21 | if (0 != dp[start][end]) { 22 | return dp[start][end]; 23 | } 24 | 25 | int ans = Integer.MAX_VALUE; 26 | // 当答案不是n的时候,需要付出的代价,寻找最小的代价 27 | for (int n = start; n <= end; ++n) { 28 | // 需要确保在最极端的情况下也能猜到答案,故需要有足够的钱,因此选择 max 29 | int tmp = n + Math.max(dfs(dp, start, n - 1), dfs(dp, n + 1, end)); 30 | if (tmp < ans) { 31 | ans = tmp; 32 | } 33 | } 34 | dp[start][end] = ans; 35 | return ans; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution377.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 组合总和 Ⅳ 8 | * @date: 2018/08/23 9 | */ 10 | public class Solution377 { 11 | public int combinationSum4(int[] nums, int target) { 12 | if (nums == null || nums.length == 0) { 13 | return 0; 14 | } 15 | 16 | // dp[i]表示:和为i的组合的个数 17 | int[] dp = new int[target + 1]; 18 | dp[0] = 1; 19 | Arrays.sort(nums); 20 | 21 | for (int i = 1; i <= target; ++i) { 22 | for (int j = 0; j < nums.length && nums[j] <= i; ++j) { 23 | dp[i] += dp[i - nums[j]]; 24 | } 25 | } 26 | return dp[target]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution392.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 判断子序列 6 | * @date: 2018/08/19 7 | */ 8 | public class Solution392 { 9 | public static void main(String[] args) { 10 | Solution392 test = new Solution392(); 11 | System.out.println(test.isSubsequence("axc", "ahbgdc")); 12 | } 13 | 14 | public boolean isSubsequence(String s, String t) { 15 | int start = -1; 16 | for (char c : s.toCharArray()) { 17 | start = t.indexOf(c, start + 1); 18 | if (-1 == start) { 19 | return false; 20 | } 21 | } 22 | return true; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution404.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 左叶子之和 6 | * @date: 2019/03/10 7 | */ 8 | public class Solution404 { 9 | public int sumOfLeftLeaves(TreeNode root) { 10 | if (null == root){ 11 | return 0; 12 | } 13 | 14 | return dfs(root.left, true) + dfs(root.right, false); 15 | } 16 | 17 | private int dfs(TreeNode node, boolean isLeft) { 18 | if (null == node) { 19 | return 0; 20 | } 21 | 22 | if (null == node.left && null == node.right && isLeft) { 23 | return node.val; 24 | } else { 25 | return dfs(node.left, true) + dfs(node.right, false); 26 | } 27 | } 28 | 29 | public class TreeNode { 30 | int val; 31 | TreeNode left; 32 | TreeNode right; 33 | 34 | TreeNode(int x) { 35 | val = x; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution416.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 分割等和子集 6 | * @date: 2018/08/23 7 | */ 8 | public class Solution416 { 9 | public boolean canPartition(int[] nums) { 10 | int sum = sumOfArray(nums); 11 | // 数组和为奇数,直接返回 false 12 | if (1 == (sum & 1)) { 13 | return false; 14 | } 15 | 16 | int W = sum >>> 1; 17 | // dp[i] 代表能否组合成和为 i 的结果。 18 | boolean[] dp = new boolean[W + 1]; 19 | dp[0] = true; 20 | 21 | // 对于每一个数字,选择都是两个,放或者不放。所以, 22 | // 如果不放第 i 个数字,那问题就变成了前 i - 1 个数字能否组合成和为 j 的结果; 23 | // 如果放第 i 个数字,那问题就变成了前 i - 1 个数字能否组合成和为 j - nums[i] 的结果。 24 | // 只要这两种情况有一种存在, dp[j] 就成立。 25 | for (int e : nums) { 26 | // 必须从大到小 27 | for (int j = W; j >= e; --j) { 28 | dp[j] = dp[j] || dp[j - e]; 29 | } 30 | } 31 | return dp[W]; 32 | } 33 | 34 | private int sumOfArray(int[] nums) { 35 | int sum = 0; 36 | for (int n : nums) { 37 | sum += n; 38 | } 39 | return sum; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution452.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 用最少数量的箭引爆气球 9 | * @date: 2018/08/19 10 | */ 11 | public class Solution452 { 12 | public static void main(String[] args) { 13 | int[][] arrays = {{10, 16}, {2, 8}, {1, 6}, {7, 12}}; 14 | 15 | Solution452 test = new Solution452(); 16 | System.out.println(test.findMinArrowShots(arrays)); 17 | } 18 | 19 | /** 20 | * 计算不重叠的区间个数,不过和 Non-overlapping Intervals 的区别在于,[1, 2] 和 [2, 3] 在本题中算是重叠区间 21 | * 22 | * @param points 23 | * @return 24 | */ 25 | public int findMinArrowShots(int[][] points) { 26 | if (null == points || 0 >= points.length) { 27 | return 0; 28 | } 29 | 30 | Arrays.sort(points, (a, b) -> a[1] - b[1]); 31 | int arrowCnt = 1, arrowPos = points[0][1]; 32 | for (int i = 1; i < points.length; ++i) { 33 | if (arrowPos >= points[i][0]) { 34 | continue; 35 | } 36 | ++arrowCnt; 37 | arrowPos = points[i][1]; 38 | } 39 | return arrowCnt; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution455.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 分发饼干 8 | * @date: 2018/08/18 9 | */ 10 | public class Solution455 { 11 | public static void main(String[] args) { 12 | int[] g = {1, 2}; 13 | int[] s = {1, 2, 3}; 14 | 15 | Solution455 test = new Solution455(); 16 | System.out.println(test.findContentChildren(g, s)); 17 | } 18 | 19 | public int findContentChildren(int[] g, int[] s) { 20 | Arrays.sort(g); 21 | Arrays.sort(s); 22 | 23 | int gIndex = 0, sIndex = 0; 24 | while (gIndex < g.length && sIndex < s.length) { 25 | if (g[gIndex] <= s[sIndex]) { 26 | ++gIndex; 27 | } 28 | ++sIndex; 29 | } 30 | return gIndex; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution467.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 环绕字符串中唯一的子字符串 6 | * @date: 2019/03/02 7 | */ 8 | public class Solution467 { 9 | public int findSubstringInWraproundString(String p) { 10 | // count[i] is the maximum unique substring end with ith letter. 11 | // 0 - 'a', 1 - 'b', ..., 25 - 'z'. 12 | int[] count = new int[26]; 13 | 14 | // store longest contiguous substring ends at current position. 15 | int maxLengthCur = 0; 16 | 17 | for (int i = 0; i < p.length(); i++) { 18 | if (i > 0 && (p.charAt(i) - p.charAt(i - 1) == 1 || (p.charAt(i - 1) - p.charAt(i) == 25))) { 19 | maxLengthCur++; 20 | } else { 21 | maxLengthCur = 1; 22 | } 23 | 24 | int index = p.charAt(i) - 'a'; 25 | count[index] = Math.max(count[index], maxLengthCur); 26 | } 27 | 28 | // Sum to get result 29 | int sum = 0; 30 | for (int i = 0; i < 26; i++) { 31 | sum += count[i]; 32 | } 33 | return sum; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution474.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/08/23 7 | */ 8 | public class Solution474 { 9 | public int findMaxForm(String[] strs, int m, int n) { 10 | if (strs == null || strs.length == 0) { 11 | return 0; 12 | } 13 | int[][] dp = new int[m + 1][n + 1]; 14 | // 每个字符串只能用一次 15 | for (String s : strs) { 16 | int zeros = 0, ones = 0; 17 | for (char c : s.toCharArray()) { 18 | if ('0' == c) { 19 | ++zeros; 20 | } else { 21 | ++ones; 22 | } 23 | } 24 | 25 | for (int i = m; i >= zeros; --i) { 26 | for (int j = n; j >= ones; --j) { 27 | dp[i][j] = Math.max(dp[i][j], dp[i - zeros][j - ones] + 1); 28 | } 29 | } 30 | } 31 | return dp[m][n]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution491.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.HashSet; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | /** 9 | * @author: mayuan 10 | * @desc: 递增子序列 11 | * @date: 2019/03/15 12 | */ 13 | public class Solution491 { 14 | public List> findSubsequences(int[] nums) { 15 | List> ans = new LinkedList<>(); 16 | dfs(ans, new LinkedList<>(), nums, 0); 17 | return ans; 18 | } 19 | 20 | public void dfs(List> answer, LinkedList oneAnswer, int[] nums, int start) { 21 | if (oneAnswer.size() > 1) { 22 | answer.add(new LinkedList<>(oneAnswer)); 23 | } 24 | 25 | Set set = new HashSet<>(); 26 | for (int i = start; i < nums.length; ++i) { 27 | if (set.contains(nums[i])) { 28 | continue; 29 | } 30 | 31 | if (0 == oneAnswer.size() || nums[i] >= oneAnswer.peekLast()) { 32 | set.add(nums[i]); 33 | oneAnswer.add(nums[i]); 34 | dfs(answer, oneAnswer, nums, i + 1); 35 | oneAnswer.remove(oneAnswer.size() - 1); 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution513.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 找树左下角的值 6 | * @date: 2019/03/15 7 | */ 8 | public class Solution513 { 9 | int ans = 0; 10 | int curDepth = 0; 11 | 12 | public int findBottomLeftValue(TreeNode root) { 13 | dfs(root, 1); 14 | return ans; 15 | } 16 | 17 | public void dfs(TreeNode node, int depth) { 18 | if (curDepth < depth) { 19 | ans = node.val; 20 | curDepth = depth; 21 | } 22 | 23 | if (null != node.left) { 24 | dfs(node.left, depth + 1); 25 | } 26 | if (null != node.right) { 27 | dfs(node.right, depth + 1); 28 | } 29 | } 30 | 31 | public class TreeNode { 32 | int val; 33 | TreeNode left; 34 | TreeNode right; 35 | 36 | TreeNode(int x) { 37 | val = x; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution516.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 最长回文子序列 6 | * @date: 2019/02/26 7 | */ 8 | public class Solution516 { 9 | public int longestPalindromeSubseq(String s) { 10 | if (null == s || 0 >= s.length()) { 11 | return 0; 12 | } 13 | 14 | int n = s.length(); 15 | // dp[i][j]代表: substring(i, j)的最长回文子串 16 | // here i, j represent left, right indexes in the string 17 | int[][] dp = new int[n][n]; 18 | 19 | // dp[i][j] = dp[i+1][j-1] + 2 ,如果s.charAt(i) == s.charAt(j) 20 | // 否则, dp[i][j] = Math.max(dp[i+1][j], dp[i][j-1]) 21 | 22 | for (int i = n - 1; i >= 0; --i) { 23 | dp[i][i] = 1; 24 | for (int j = i + 1; j < n; ++j) { 25 | if (s.charAt(i) == s.charAt(j)) { 26 | dp[i][j] = dp[i + 1][j - 1] + 2; 27 | } else { 28 | dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]); 29 | } 30 | } 31 | } 32 | return dp[0][n-1]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution526.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 优美的排列 6 | * @date: 2019/02/16 7 | */ 8 | public class Solution526 { 9 | 10 | int count = 0; 11 | 12 | public int countArrangement(int N) { 13 | if (0 >= N) { 14 | return 0; 15 | } 16 | 17 | dfs(N, 1, new boolean[N + 1]); 18 | return count; 19 | } 20 | 21 | public void dfs(int N, int pos, boolean[] hasVisited) { 22 | if (pos > N) { 23 | ++count; 24 | return; 25 | } 26 | 27 | for (int i = 1; i <= N; ++i) { 28 | if (!hasVisited[i] && (0 == i % pos || 0 == pos % i)) { 29 | hasVisited[i] = true; 30 | dfs(N, pos + 1, hasVisited); 31 | hasVisited[i] = false; 32 | } 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution530.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 二叉搜索树的最小绝对差 6 | * @date: 2019/03/02 7 | */ 8 | public class Solution530 { 9 | 10 | TreeNode pre; 11 | int mn = Integer.MAX_VALUE; 12 | 13 | public int getMinimumDifference(TreeNode root) { 14 | inOrder(root); 15 | return mn; 16 | } 17 | 18 | public void inOrder(TreeNode node) { 19 | if (null == node) { 20 | return; 21 | } 22 | 23 | inOrder(node.left); 24 | if (null != pre) { 25 | mn = Math.min(mn, node.val - pre.val); 26 | } 27 | // 遍历右子树时,pre引用需要更新为node 28 | pre = node; 29 | inOrder(node.right); 30 | } 31 | 32 | public class TreeNode { 33 | int val; 34 | TreeNode left; 35 | TreeNode right; 36 | 37 | TreeNode(int x) { 38 | val = x; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution532.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 数组中的K-diff数对 9 | * @date: 2019/01/10 10 | */ 11 | public class Solution532 { 12 | 13 | public int findPairs(int[] nums, int k) { 14 | if (null == nums || 0 >= nums.length || 0 > k) { 15 | return 0; 16 | } 17 | 18 | Map map = new HashMap<>(nums.length); 19 | for (int n : nums) { 20 | map.put(n, 1 + map.getOrDefault(n, 0)); 21 | } 22 | 23 | int ans = 0; 24 | for (Map.Entry entry : map.entrySet()) { 25 | if (0 == k) { 26 | if (2 <= entry.getValue()) { 27 | ++ans; 28 | } 29 | } else { 30 | if (map.containsKey(entry.getKey() + k)) { 31 | ++ans; 32 | } 33 | } 34 | } 35 | return ans; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution540.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/08/20 7 | */ 8 | public class Solution540 { 9 | public static void main(String[] args) { 10 | int[] nums = {3, 3, 7, 7, 10, 11, 11}; 11 | 12 | Solution540 test = new Solution540(); 13 | System.out.println(test.singleNonDuplicate(nums)); 14 | System.out.println(test.singleNonDuplicate2(nums)); 15 | } 16 | 17 | public int singleNonDuplicate(int[] nums) { 18 | int ans = 0; 19 | for (int n : nums) { 20 | ans ^= n; 21 | } 22 | return ans; 23 | } 24 | 25 | public int singleNonDuplicate2(int[] nums) { 26 | int left = 0, right = nums.length - 1; 27 | while (left < right) { 28 | int mid = ((right - left) >> 1) + left; 29 | // 保证 left right mid 都在偶数位,使得查找区间大小一直都是奇数 30 | if (1 == (mid & 1)) { 31 | --mid; 32 | } 33 | if (nums[mid] == nums[mid + 1]) { 34 | left = mid + 2; 35 | } else { 36 | right = mid; 37 | } 38 | } 39 | return nums[left]; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution547.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 朋友圈 6 | * @date: 2018/08/15 7 | */ 8 | public class Solution547 { 9 | public static void main(String[] args) { 10 | Solution547 test = new Solution547(); 11 | 12 | int[][] M = new int[][]{ 13 | {1, 1, 0}, 14 | {1, 1, 0}, 15 | {0, 0, 1}}; 16 | System.out.println(test.findCircleNum(M)); 17 | } 18 | 19 | public int findCircleNum(int[][] M) { 20 | if (null == M || 0 >= M.length) { 21 | return 0; 22 | } 23 | 24 | int circleNumber = 0; 25 | boolean[] hasVisited = new boolean[M.length]; 26 | for (int i = 0; i < M.length; ++i) { 27 | if (!hasVisited[i]) { 28 | dfs(M, hasVisited, i); 29 | ++circleNumber; 30 | } 31 | } 32 | return circleNumber; 33 | } 34 | 35 | private void dfs(int[][] M, boolean[] hasVisited, int i) { 36 | hasVisited[i] = true; 37 | for (int j = 0; j < M[i].length; ++j) { 38 | if (1 == M[i][j] && !hasVisited[j]) { 39 | dfs(M, hasVisited, j); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution559.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: N叉树的最大深度 8 | * @date: 2019/03/10 9 | */ 10 | public class Solution559 { 11 | public int maxDepth(Node root) { 12 | if (null == root) { 13 | return 0; 14 | } 15 | 16 | int mx = 0; 17 | for (Node node : root.children) { 18 | mx = Math.max(mx, maxDepth(node)); 19 | } 20 | return mx + 1; 21 | } 22 | 23 | class Node { 24 | public int val; 25 | public List children; 26 | 27 | public Node() { 28 | } 29 | 30 | public Node(int _val, List _children) { 31 | val = _val; 32 | children = _children; 33 | } 34 | } 35 | 36 | ; 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution583.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/08/24 7 | */ 8 | public class Solution583 { 9 | public int minDistance(String word1, String word2) { 10 | if (null == word1 || null == word2) { 11 | return 0; 12 | } 13 | 14 | int lengthOfWord1 = word1.length(); 15 | int lengthOfWord2 = word2.length(); 16 | // dp[i][j]表示 word1的第 i 个字符前和 word2的第 j个字符前,最长公共子序列的长度 17 | int[][] dp = new int[lengthOfWord1 + 1][lengthOfWord2 + 1]; 18 | 19 | for (int i = 1; i <= lengthOfWord1; ++i) { 20 | for (int j = 1; j <= lengthOfWord2; ++j) { 21 | // word1 的第 i 个字符和 word2 的第 j个字符相等 22 | if (word1.charAt(i - 1) == word2.charAt(j - 1)) { 23 | dp[i][j] = dp[i - 1][j - 1] + 1; 24 | } else { 25 | // word1 的第 i 个字符和 word2 的第 j个字符不相等 26 | dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); 27 | } 28 | } 29 | } 30 | return lengthOfWord1 + lengthOfWord2 - 2 * dp[lengthOfWord1][lengthOfWord2]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution605.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/08/19 7 | */ 8 | public class Solution605 { 9 | public static void main(String[] args) { 10 | 11 | } 12 | 13 | public boolean canPlaceFlowers(int[] flowerbed, int n) { 14 | int cnt = 0; 15 | for (int i = 0; i < flowerbed.length && cnt < n; ++i) { 16 | if (1 == flowerbed[i]) { 17 | continue; 18 | } 19 | 20 | int pre = (0 == i) ? 0 : flowerbed[i - 1]; 21 | int next = (flowerbed.length - 1 == i) ? 0 : flowerbed[i + 1]; 22 | if (0 == pre && 0 == next) { 23 | flowerbed[i] = 1; 24 | ++cnt; 25 | } 26 | } 27 | return cnt >= n; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution621.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 任务调度器 6 | * @date: 2019/01/21 7 | */ 8 | public class Solution621 { 9 | 10 | public int leastInterval(char[] tasks, int n) { 11 | int[] dict = new int[26]; 12 | for (char c : tasks) { 13 | ++dict[c - 'A']; 14 | } 15 | 16 | // 出现次数最多的任务,其总次数 17 | int maxNumber = 0; 18 | // 总次数最大,任务数量 19 | int sameCnt = 1; 20 | for (int e : dict) { 21 | if (maxNumber < e) { 22 | maxNumber = e; 23 | sameCnt = 1; 24 | } else if (maxNumber == e) { 25 | ++sameCnt; 26 | } 27 | } 28 | 29 | int space = (n + 1) * (maxNumber - 1) + sameCnt; 30 | return space < tasks.length ? tasks.length : space; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution633.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/08/17 7 | */ 8 | public class Solution633 { 9 | public static void main(String[] args) { 10 | Solution633 test = new Solution633(); 11 | 12 | System.out.println(test.judgeSquareSum(100000)); 13 | } 14 | 15 | public boolean judgeSquareSum(int c) { 16 | if (0 > c) { 17 | return false; 18 | } 19 | 20 | int left = 0; 21 | int right = (int) Math.sqrt(c); 22 | while (left <= right) { 23 | int temp = left * left + right * right; 24 | if (temp < c) { 25 | ++left; 26 | } else if (temp > c) { 27 | --right; 28 | } else { 29 | return true; 30 | } 31 | } 32 | return false; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution646.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/08/22 9 | */ 10 | public class Solution646 { 11 | public int findLongestChain(int[][] pairs) { 12 | if (null == pairs || 0 >= pairs.length) { 13 | return 0; 14 | } 15 | 16 | // 按照第一个元素从小到大排序 17 | Arrays.sort(pairs, (a, b) -> (a[0] - b[0])); 18 | // 以该位置数对作为链表的尾端,串的最大长度 19 | int[] dp = new int[pairs.length]; 20 | Arrays.fill(dp, 1); 21 | 22 | for (int i = 0; i < pairs.length; ++i) { 23 | for (int j = 0; j < i; ++j) { 24 | if (pairs[j][1] < pairs[i][0]) { 25 | dp[i] = Math.max(dp[i], dp[j] + 1); 26 | } 27 | } 28 | } 29 | 30 | int max = dp[0]; 31 | for (int i = 1; i < dp.length; ++i) { 32 | if (max < dp[i]) { 33 | max = dp[i]; 34 | } 35 | } 36 | return max; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution649.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.ArrayDeque; 4 | 5 | /** 6 | * @author Administrator 7 | * @desc Dota2 参议院 8 | * @create 2019/01/22 9 | */ 10 | public class Solution649 { 11 | 12 | public String predictPartyVictory(String senate) { 13 | ArrayDeque r = new ArrayDeque<>(); 14 | ArrayDeque d = new ArrayDeque<>(); 15 | for (int i = 0; i < senate.length(); ++i) { 16 | if ('R' == senate.charAt(i)) { 17 | r.add(i); 18 | } else { 19 | d.add(i); 20 | } 21 | } 22 | 23 | int n = senate.length(); 24 | while (!r.isEmpty() && !d.isEmpty()) { 25 | int r_id = r.pollFirst(); 26 | int d_id = d.pollFirst(); 27 | if (r_id < d_id) { 28 | r.addLast(r_id + n); 29 | } else { 30 | d.addLast(d_id + n); 31 | } 32 | } 33 | 34 | return r.size() > d.size() ? "Radiant" : "Dire"; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution650.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/08/24 7 | */ 8 | public class Solution650 { 9 | public static void main(String[] args) { 10 | Solution650 test = new Solution650(); 11 | 12 | System.out.println(test.minSteps(6)); 13 | } 14 | 15 | public int minSteps(int n) { 16 | // 得到长度为n 的字符串的最小操作: 17 | // 1.直接将字符'A'复制 1 次,然后粘贴 n-1 次,共n次操作 18 | // 2.n可以被一个比它自己小的数j整除(长度为n的字符串可以由多个长度为j的字符串组成),则可以复制 j 个字符串一次,然后粘贴 i/j - 1 次,共 i/j + dp[j]次 19 | int[] dp = new int[n + 1]; 20 | dp[1] = 0; 21 | 22 | for (int i = 2; i <= n; ++i) { 23 | dp[i] = i; 24 | for (int j = 1; j < i; ++j) { 25 | // 最终得到字符串的大小只可能与当前存在的字符串有 i%j == 0的关系,否则无法得到. 26 | if (0 == i % j) { 27 | dp[i] = Math.min(dp[i], dp[j] + i / j); 28 | } 29 | } 30 | } 31 | return dp[n]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution680.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/08/17 7 | */ 8 | public class Solution680 { 9 | public static void main(String[] args) { 10 | Solution680 test = new Solution680(); 11 | 12 | System.out.println(test.validPalindrome("aba")); 13 | System.out.println(test.validPalindrome("abcda")); 14 | } 15 | 16 | public boolean validPalindrome(String s) { 17 | int left = 0; 18 | int right = s.length() - 1; 19 | while (left < right) { 20 | if (s.charAt(left) != s.charAt(right)) { 21 | return isPalindrome(s, left, right - 1) || isPalindrome(s, left + 1, right); 22 | } 23 | ++left; 24 | --right; 25 | } 26 | return true; 27 | } 28 | 29 | private boolean isPalindrome(String s, int left, int right) { 30 | while (left < right) { 31 | if (s.charAt(left) != s.charAt(right)) { 32 | return false; 33 | } 34 | ++left; 35 | --right; 36 | } 37 | return true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution714.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 买卖股票的最佳时机含手续费 6 | * 动态规划思想 7 | * @date: 2019/01/24 8 | */ 9 | public class Solution714 { 10 | 11 | public int maxProfit(int[] prices, int fee) { 12 | if (null == prices || 1 >= prices.length) { 13 | return 0; 14 | } 15 | 16 | int buy0 = -prices[0]; 17 | int buy1 = 0; 18 | int sell0 = 0; 19 | int sell1 = 0; 20 | 21 | for (int i = 1; i < prices.length; ++i) { 22 | buy1 = Math.max(buy0, sell0 - prices[i]); 23 | sell1 = Math.max(sell0, buy0 + prices[i] - fee); 24 | 25 | buy0 = buy1; 26 | sell0 = sell1; 27 | } 28 | 29 | return sell1; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution738.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 单调递增的数字 6 | * @date: 2019/01/22 7 | */ 8 | public class Solution738 { 9 | 10 | public static void main(String[] args) { 11 | final int n = 332; 12 | 13 | System.out.println(new Solution738().monotoneIncreasingDigits(n)); 14 | } 15 | 16 | public int monotoneIncreasingDigits(int N) { 17 | char[] number = String.valueOf(N).toCharArray(); 18 | 19 | // 必须从后向前推导,才能确保最前面几个数字是递增的 20 | int mark = number.length; 21 | for (int i = number.length - 1; i > 0; --i) { 22 | if (number[i] < number[i - 1]) { 23 | mark = i - 1; 24 | --number[mark]; 25 | } 26 | } 27 | 28 | for (int i = mark + 1; i < number.length; ++i) { 29 | number[i] = '9'; 30 | } 31 | 32 | return Integer.parseInt(new String(number)); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution744.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/08/19 7 | */ 8 | public class Solution744 { 9 | public static void main(String[] args) { 10 | char[] array = {'c', 'f', 'j'}; 11 | 12 | Solution744 test = new Solution744(); 13 | System.out.println(test.nextGreatestLetter(array, 'd')); 14 | } 15 | 16 | public char nextGreatestLetter(char[] letters, char target) { 17 | int left = 0, right = letters.length - 1; 18 | while (left <= right) { 19 | int mid = left + (right - left) / 2; 20 | if (letters[mid] <= target) { 21 | left = mid + 1; 22 | } else { 23 | right = mid - 1; 24 | } 25 | } 26 | // 找出 letters 中大于 target 的最小字符,如果找不到就返回第 1 个字符。 27 | return (left < letters.length) ? letters[left] : letters[0]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution763.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 划分字母区间 9 | * @date: 2018/08/19 10 | */ 11 | public class Solution763 { 12 | public static void main(String[] args) { 13 | Solution763 test = new Solution763(); 14 | 15 | List ans = test.partitionLabels("ababcbacadefegdehijhklij"); 16 | ans.forEach(System.out::println); 17 | } 18 | 19 | public List partitionLabels(String S) { 20 | int[] map = new int[26]; 21 | for (int i = 0; i < S.length(); ++i) { 22 | map[S.charAt(i) - 'a'] = i; 23 | } 24 | 25 | List answer = new LinkedList<>(); 26 | int start = 0, last = 0; 27 | for (int i = 0; i < S.length(); ++i) { 28 | last = last > map[S.charAt(i) - 'a'] ? last : map[S.charAt(i) - 'a']; 29 | if (last == i) { 30 | answer.add(last - start + 1); 31 | start = last + 1; 32 | } 33 | } 34 | return answer; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution783.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 二叉搜索树结点最小距离 6 | * @date: 2019/03/02 7 | */ 8 | public class Solution783 { 9 | 10 | TreeNode pre; 11 | int mn = Integer.MAX_VALUE; 12 | 13 | public int minDiffInBST(TreeNode root) { 14 | inOrder(root); 15 | return mn; 16 | } 17 | 18 | public void inOrder(TreeNode node) { 19 | if (null == node) { 20 | return; 21 | } 22 | 23 | inOrder(node.left); 24 | if (null != pre) { 25 | mn = Math.min(mn, node.val - pre.val); 26 | } 27 | // 遍历右子树时,pre引用需要更新为node 28 | pre = node; 29 | inOrder(node.right); 30 | } 31 | 32 | public class TreeNode { 33 | int val; 34 | TreeNode left; 35 | TreeNode right; 36 | 37 | TreeNode(int x) { 38 | val = x; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution784.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 字母大小写全排列 9 | * @date: 2019/02/16 10 | */ 11 | public class Solution784 { 12 | 13 | public List letterCasePermutation(String S) { 14 | List ans = new LinkedList<>(); 15 | 16 | if (null == S) { 17 | return ans; 18 | } 19 | 20 | dfs(ans, S.toCharArray(), 0); 21 | return ans; 22 | } 23 | 24 | public void dfs(List answer, char[] chs, int start) { 25 | if (start == chs.length) { 26 | answer.add(new String(chs)); 27 | return; 28 | } 29 | 30 | if ('0' <= chs[start] && chs[start] <= '9') { 31 | dfs(answer, chs, start + 1); 32 | } else { 33 | chs[start] = Character.toLowerCase(chs[start]); 34 | dfs(answer, chs, start + 1); 35 | 36 | chs[start] = Character.toUpperCase(chs[start]); 37 | dfs(answer, chs, start + 1); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution841.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 字符的最短距离 6 | * Initial result array. 7 | * Loop twice on the string S. 8 | * First forward pass to find shortest distant to character on left. 9 | * Second backward pass to find shortest distant to character on right. 10 | * @date: 2019/01/11 11 | */ 12 | public class Solution841 { 13 | 14 | public int[] shortestToChar(String S, char C) { 15 | if (null == S || 0 >= S.length()) { 16 | return null; 17 | } 18 | 19 | int[] ans = new int[S.length()]; 20 | int pos = -S.length(); 21 | for (int i = 0; i < S.length(); ++i) { 22 | if (S.charAt(i) == C) { 23 | pos = i; 24 | } 25 | ans[i] = i - pos; 26 | } 27 | 28 | for (int i = S.length() - 1; i >= 0; --i) { 29 | if (S.charAt(i) == C) { 30 | pos = i; 31 | } 32 | ans[i] = Math.min(ans[i], Math.abs(i - pos)); 33 | } 34 | return ans; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution844.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 比较含退格的字符串 6 | * @date: 2019/01/12 7 | */ 8 | public class Solution844 { 9 | 10 | /** 11 | * The idea is that, read next letter from end to start. 12 | * If we meet #, we increase the number we need to step back, until back = 0 13 | * @param S 14 | * @param T 15 | * @return 16 | */ 17 | public boolean backspaceCompare(String S, String T) { 18 | if ((null == S && null != T) || (null != S && null == T)) { 19 | return false; 20 | } 21 | 22 | for (int i = S.length() - 1, j = T.length() - 1; ; --i, --j) { 23 | for (int b = 0; i >= 0 && (b > 0 || '#' == S.charAt(i)); --i) { 24 | b += '#' == S.charAt(i) ? 1 : -1; 25 | } 26 | for (int b = 0; j >= 0 && (b > 0 || '#' == T.charAt(j)); --j) { 27 | b += '#' == T.charAt(j) ? 1 : -1; 28 | } 29 | 30 | if (0 > i || 0 > j || S.charAt(i) != T.charAt(j)) { 31 | return -1 == i && -1 == j; 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution859.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/12/25 7 | */ 8 | public class Solution859 { 9 | 10 | public boolean buddyStrings(String A, String B) { 11 | if (null == A || null == B || A.length() != B.length() || 0 == A.length()) { 12 | return false; 13 | } 14 | 15 | int indexA = -1, indexB = -1, diff = 0; 16 | int[] map = new int[26]; 17 | boolean duplicate = false; 18 | 19 | for (int i = 0; i < A.length(); ++i) { 20 | if (++map[A.charAt(i) - 'a'] >= 2) { 21 | duplicate = true; 22 | } 23 | if (A.charAt(i) != B.charAt(i)) { 24 | ++diff; 25 | if (-1 == indexA) { 26 | indexA = i; 27 | } else if (-1 == indexB) { 28 | indexB = i; 29 | } 30 | } 31 | } 32 | return (0 == diff && duplicate) || 33 | (2 == diff && A.charAt(indexA) == B.charAt(indexB) && A.charAt(indexB) == B.charAt(indexA)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution861.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 翻转矩阵后的得分 6 | * @date: 2019/02/01 7 | */ 8 | public class Solution861 { 9 | 10 | public int matrixScore(int[][] A) { 11 | if (null == A || 0 >= A.length) { 12 | return 0; 13 | } 14 | 15 | int M = A.length, N = A[0].length; 16 | int ans = (1 << (N - 1)) * M; 17 | 18 | for (int j = 1; j < N; ++j) { 19 | int cur = 0; 20 | for (int i = 0; i < M; ++i) { 21 | cur += A[i][j] == A[i][0] ? 1 : 0; 22 | } 23 | ans += Math.max(cur, M - cur) * (1 << (N - 1 - j)); 24 | } 25 | return ans; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution870.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Arrays; 4 | import java.util.PriorityQueue; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 优势洗牌 9 | * @date: 2019/02/08 10 | */ 11 | public class Solution870 { 12 | 13 | public int[] advantageCount(int[] A, int[] B) { 14 | if (0 == A.length && 0 == B.length) { 15 | return A; 16 | } 17 | 18 | Arrays.sort(A); 19 | PriorityQueue queue = new PriorityQueue<>((a, b) -> b[1] - a[1]); 20 | for (int i = 0; i < B.length; ++i) { 21 | queue.add(new int[]{i, B[i]}); 22 | } 23 | 24 | int[] ans = new int[A.length]; 25 | int low = 0, high = A.length - 1; 26 | while (!queue.isEmpty()) { 27 | int[] cur = queue.poll(); 28 | int idx = cur[0], val = cur[1]; 29 | if (A[high] > val) { 30 | ans[idx] = A[high--]; 31 | } else { 32 | ans[idx] = A[low++]; 33 | } 34 | } 35 | return ans; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution881.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 救生艇 8 | * @date: 2019/01/12 9 | */ 10 | public class Solution881 { 11 | 12 | /** 13 | * 先对数组进行排序 14 | * i指针指向开始(体重轻),j指针指向末尾(体重重) 15 | * 重的人肯定能坐上船,因此j指针每次循环均能够减一. 16 | * 轻的人只有和重的人两个体重和不超过限制才能坐上船. 17 | * 18 | * @param people 19 | * @param limit 20 | * @return 21 | */ 22 | public int numRescueBoats(int[] people, int limit) { 23 | if (null == people || 0 >= people.length) { 24 | return 0; 25 | } 26 | 27 | Arrays.sort(people); 28 | int ans = 0; 29 | for (int i = 0, j = people.length - 1; i <= j; --j, ++ans) { 30 | if (people[i] + people[j] <= limit) { 31 | ++i; 32 | } 33 | } 34 | return ans; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution908.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 最小差值 I 6 | * @date: 2019/02/10 7 | */ 8 | public class Solution908 { 9 | public int smallestRangeI(int[] A, int K) { 10 | if (null == A || 1 >= A.length) { 11 | return 0; 12 | } 13 | 14 | int mx = A[0], mn = A[0]; 15 | for (int i = 1; i < A.length; ++i) { 16 | mx = Math.max(mx, A[i]); 17 | mn = Math.min(mn, A[i]); 18 | } 19 | return Math.max(mx - mn - 2 * K, 0); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution910.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 最小差值 II 8 | * https://leetcode.com/problems/smallest-range-ii/discuss/173505/Java-Solution-with-the-Picture-to-explain-it 9 | * @date: 2019/02/12 10 | */ 11 | public class Solution910 { 12 | 13 | public int smallestRangeII(int[] A, int K) { 14 | Arrays.sort(A); 15 | 16 | int n = A.length; 17 | int ans = A[n - 1] - A[0]; 18 | for (int i = 0; i < n - 1; ++i) { 19 | int mx = Math.max(A[i] + K, A[n - 1] - K); 20 | int mn = Math.min(A[i + 1] - K, A[0] + K); 21 | ans = Math.min(ans, mx - mn); 22 | } 23 | return ans; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution921.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2019/02/09 7 | */ 8 | public class Solution921 { 9 | 10 | public static void main(String[] args) { 11 | String str1 = "()))(("; 12 | 13 | Solution921 solution921 = new Solution921(); 14 | System.out.println(solution921.minAddToMakeValid(str1)); 15 | } 16 | 17 | public int minAddToMakeValid(String S) { 18 | if (null == S || 1 > S.length()) { 19 | return 0; 20 | } 21 | 22 | int left = 0, right = 0; 23 | for (int i = 0; i < S.length(); ++i) { 24 | char c = S.charAt(i); 25 | if ('(' == c) { 26 | ++left; 27 | } else { 28 | if (0 < left) { 29 | --left; 30 | } else { 31 | ++right; 32 | } 33 | } 34 | } 35 | 36 | return left + right; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution922.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2019/01/15 7 | */ 8 | public class Solution922 { 9 | 10 | public int[] sortArrayByParityII(int[] A) { 11 | if (null == A || 1 >= A.length) { 12 | return A; 13 | } 14 | 15 | // 偶数指针(even pointer) 16 | int i = 0; 17 | // 奇数指针(odd pointer) 18 | int j = 1; 19 | while (i < A.length && j < A.length) { 20 | while (i < A.length && 0 == (A[i] & 1)) { 21 | i += 2; 22 | } 23 | while (j < A.length && 1 == (A[j] & 1)) { 24 | j += 2; 25 | } 26 | if (i < A.length && j < A.length) { 27 | swap(A, i, j); 28 | } 29 | } 30 | return A; 31 | } 32 | 33 | public void swap(int[] array, int i, int j) { 34 | int tmp = array[i]; 35 | array[i] = array[j]; 36 | array[j] = tmp; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution925.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 长按键入 6 | * @date: 2019/01/12 7 | */ 8 | public class Solution925 { 9 | 10 | public boolean isLongPressedName(String name, String typed) { 11 | if (null == name || null == typed) { 12 | return false; 13 | } 14 | 15 | int i = 0; 16 | for (int j = 0; j < typed.length(); ++j) { 17 | if (i < name.length() && name.charAt(i) == typed.charAt(j)) { 18 | ++i; 19 | } else if (0 == j || typed.charAt(j - 1) != typed.charAt(j)) { 20 | return false; 21 | } 22 | } 23 | return i == name.length(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution930.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 和相同的二元子数组 6 | * @date: 2019/01/13 7 | */ 8 | public class Solution930 { 9 | 10 | public static void main(String[] args) { 11 | int[] nums = {1, 0, 1, 0, 1, 0, 0, 1, 1, 0}; 12 | final int S = 2; 13 | 14 | System.out.println(new Solution930().numSubarraysWithSum(nums, S)); 15 | } 16 | 17 | /** 18 | * 统计前缀和出现的次数 19 | * 20 | * @param A 21 | * @param S 22 | * @return 23 | */ 24 | public int numSubarraysWithSum(int[] A, int S) { 25 | if (null == A || 0 >= A.length) { 26 | return 0; 27 | } 28 | 29 | int preSum = 0, cnt = 0; 30 | int[] count = new int[A.length + 1]; 31 | // preSum与S相等时,仅有1种情况 32 | count[0] = 1; 33 | for (int e : A) { 34 | preSum += e; 35 | if (preSum >= S) { 36 | cnt += count[preSum - S]; 37 | } 38 | ++count[preSum]; 39 | } 40 | return cnt; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution938.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 二叉搜索树的范围和 6 | * @date: 2019/03/02 7 | */ 8 | public class Solution938 { 9 | 10 | public int rangeSumBST(TreeNode root, int L, int R) { 11 | if (null == root) { 12 | return 0; 13 | } 14 | 15 | if (root.val < L) { 16 | return rangeSumBST(root.right, L, R); 17 | } else if (root.val > R) { 18 | return rangeSumBST(root.left, L, R); 19 | } else { 20 | return root.val + rangeSumBST(root.left, L, R) + rangeSumBST(root.right, L, R); 21 | } 22 | } 23 | 24 | public class TreeNode { 25 | int val; 26 | TreeNode left; 27 | TreeNode right; 28 | 29 | TreeNode(int x) { 30 | val = x; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution944.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 删列造序 6 | * @date: 2019/02/12 7 | */ 8 | public class Solution944 { 9 | public int minDeletionSize(String[] A) { 10 | int cnt = 0; 11 | for (int i = 0; i < A[0].length(); ++i) { 12 | for (int j = 1; j < A.length; ++j) { 13 | if (A[j - 1].charAt(i) > A[j].charAt(i)) { 14 | ++cnt; 15 | break; 16 | } 17 | } 18 | } 19 | return cnt; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution948.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 令牌放置 8 | * @date: 2019/02/12 9 | */ 10 | public class Solution948 { 11 | public int bagOfTokensScore(int[] tokens, int P) { 12 | Arrays.sort(tokens); 13 | 14 | int ans = 0, i = 0, j = tokens.length - 1, points = 0; 15 | while (i <= j) { 16 | if (P >= tokens[i]) { 17 | P -= tokens[i]; 18 | ++points; 19 | ++i; 20 | 21 | ans = Math.max(ans, points); 22 | } else if (0 < points) { 23 | --points; 24 | P += tokens[j]; 25 | --j; 26 | } else { 27 | break; 28 | } 29 | } 30 | return ans; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution955.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 删列造序 II 6 | * @date: 2019/02/12 7 | */ 8 | public class Solution955 { 9 | public int minDeletionSize(String[] A) { 10 | int ans = 0, n = A.length, m = A[0].length(), i, j; 11 | boolean[] sorted = new boolean[n - 1]; 12 | 13 | for (j = 0; j < m; ++j) { 14 | for (i = 0; i < n - 1; ++i) { 15 | if (!sorted[i] && A[i].charAt(j) > A[i + 1].charAt(j)) { 16 | ++ans; 17 | break; 18 | } 19 | } 20 | 21 | if (i < n - 1) { 22 | continue; 23 | } 24 | for (i = 0; i < n - 1; ++i) { 25 | if (A[i].charAt(j) < A[i + 1].charAt(j)) { 26 | sorted[i] = true; 27 | } 28 | } 29 | } 30 | return ans; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution973.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 最接近原点的 K 个点 9 | * @date: 2019/01/15 10 | */ 11 | public class Solution973 { 12 | 13 | public int[][] kClosest(int[][] points, int K) { 14 | if (null == points || K >= points.length) { 15 | return points; 16 | } 17 | 18 | Arrays.sort(points, Comparator.comparingInt(a -> (a[0] * a[0] + a[1] * a[1]))); 19 | return Arrays.copyOfRange(points, 0, K); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/algorithm/leetcode/Solution984.java: -------------------------------------------------------------------------------- 1 | package algorithm.leetcode; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 不含 AAA 或 BBB 的字符串 6 | * @date: 2019/02/12 7 | */ 8 | public class Solution984 { 9 | public String strWithout3a3b(int A, int B) { 10 | StringBuilder ans = new StringBuilder(A + B); 11 | char a = 'a', b = 'b'; 12 | int i = A, j = B; 13 | if (B > A) { 14 | a = 'b'; 15 | b = 'a'; 16 | i = B; 17 | j = A; 18 | } 19 | while (i-- > 0) { 20 | ans.append(a); 21 | if (i > j) { 22 | ans.append(a); 23 | --i; 24 | } 25 | if (j > 0) { 26 | ans.append(b); 27 | --j; 28 | } 29 | } 30 | return ans.toString(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/algorithm/note/LRU.java: -------------------------------------------------------------------------------- 1 | package algorithm.note; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: LRU算法的实现 9 | * @date: 2018/09/14 10 | */ 11 | public class LRU { 12 | 13 | private static final float loadFactor = 0.75F; 14 | private final int capacity; 15 | 16 | private LinkedHashMap map; 17 | 18 | public LRU(int size) { 19 | this.capacity = size; 20 | int cap = (int) Math.ceil(size / loadFactor) + 1; 21 | 22 | map = new LinkedHashMap(cap, loadFactor, true) { 23 | @Override 24 | protected boolean removeEldestEntry(Map.Entry entry) { 25 | return size() > capacity; 26 | } 27 | }; 28 | } 29 | 30 | public K get(K key) { 31 | return map.get(key); 32 | } 33 | 34 | public void put(K key) { 35 | map.put(key, key); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/algorithm/note/MergeArray.java: -------------------------------------------------------------------------------- 1 | package algorithm.note; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 合并两个有序数组 6 | * @date: 2018/09/04 7 | */ 8 | public class MergeArray { 9 | public static void main(String[] args) { 10 | int[] a = {1, 3, 5, 7, 9}; 11 | int[] b = {0, 2, 4, 6, 8}; 12 | 13 | int[] array = mergeArray(a, b); 14 | printArray(array); 15 | } 16 | 17 | public static int[] mergeArray(int[] a, int[] b) { 18 | int length = a.length + b.length; 19 | int[] array = new int[length]; 20 | 21 | int i = 0, j = 0, k = 0; 22 | while (i < a.length && j < b.length) { 23 | if (a[i] < b[j]) { 24 | array[k++] = a[i++]; 25 | } else { 26 | array[k++] = b[j++]; 27 | } 28 | } 29 | 30 | while (i < a.length) { 31 | array[k++] = a[i++]; 32 | } 33 | while (j < b.length) { 34 | array[k++] = b[j++]; 35 | } 36 | 37 | return array; 38 | } 39 | 40 | public static void printArray(int[] array) { 41 | for (int i = 0; i < array.length; ++i) { 42 | System.out.print(array[i] + " "); 43 | } 44 | System.out.println(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/algorithm/note/MySearch.java: -------------------------------------------------------------------------------- 1 | package algorithm.note; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/09/01 7 | */ 8 | public class MySearch { 9 | public static void main(String[] args) { 10 | int[] numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 11 | 12 | System.out.println(binarySearch(numbers, 8)); 13 | } 14 | 15 | /** 16 | * 二分查找:数组需要有序 17 | * @param array 18 | * @param searchKey 19 | * @return 20 | */ 21 | public static int binarySearch(int[] array, int searchKey) { 22 | if (null == array || 0 >= array.length) { 23 | return -1; 24 | } 25 | 26 | int left = 0, right = array.length - 1; 27 | while (left <= right) { 28 | int middle = left + (right - left) / 2; 29 | if (searchKey == array[middle]) { 30 | return middle; 31 | } else if (searchKey < array[middle]) { 32 | right = middle - 1; 33 | } else { 34 | left = middle + 1; 35 | } 36 | } 37 | return -1; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/algorithm/sfo/README.md: -------------------------------------------------------------------------------- 1 | ### **剑指offer(第二版)** 2 | 3 | | 题号 | 题目 | 4 | |:----:| ------------------------------------------------------- | 5 | | 056 | [数组中只出现一次的两个数字](cpt06/Solution056.java) | 6 | | 056-2 | [数组中只出现一次的数字,其它数字均出现三次](cpt06/Solution05602.java) | 7 | | 063 | [股票的最大利润](cpt06/Solution063.java) | 8 | -------------------------------------------------------------------------------- /src/main/java/algorithm/sfo/cpt06/Solution05602.java: -------------------------------------------------------------------------------- 1 | package algorithm.sfo.cpt06; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 数组中仅有一个数字出现1次, 其余数字都出现了三次, 找出这个数字. 6 | * @date: 2018/09/25 7 | */ 8 | public class Solution05602 { 9 | 10 | public static void main(String[] args) { 11 | int[] numbers = {1, 1, 1, 2, 2, 2, 5, 3, 3, 3}; 12 | 13 | System.out.println(findAppearOnceNumber(numbers)); 14 | } 15 | 16 | /** 17 | * 采用位运算的思路:将所有数字都采用二进制的表示形式,int类型采用32个bit位来表示. 18 | * 将对应的bit位相加,如果该位置的和能被3整除,则对应所求数字的该位置为0; 不能被3整除,则对应所求数字的该位置为1. 19 | * 20 | * @param array 21 | * @return 22 | */ 23 | public static int findAppearOnceNumber(int[] array) { 24 | int[] bit = new int[32]; 25 | 26 | for (int i = 0; i < array.length; ++i) { 27 | int bitMask = 1; 28 | for (int j = 31; j >= 0; --j) { 29 | if (0 != (array[i] & bitMask)) { 30 | ++bit[j]; 31 | } 32 | bitMask = bitMask << 1; 33 | } 34 | } 35 | 36 | int result = 0; 37 | for (int i = 0; i < bit.length; ++i) { 38 | result = result << 1; 39 | result += (bit[i] % 3); 40 | } 41 | 42 | return result; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/algorithm/sfo/cpt06/Solution063.java: -------------------------------------------------------------------------------- 1 | package algorithm.sfo.cpt06; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 股票的最大利润 6 | * @date: 2018/09/25 7 | */ 8 | public class Solution063 { 9 | 10 | public static void main(String[] args) { 11 | int[] numbers = {9, 11, 8, 5, 7, 12, 16, 14}; 12 | 13 | final int answer = 11; 14 | 15 | System.out.println(answer == getMaxValue(numbers)); 16 | } 17 | 18 | /** 19 | * 思路: 在卖出价固定时,买入价越低获得的利润越大. 20 | * 在扫描到数组中的第 i 个数字时,只要能够记住之前的 i-1 个数字中的最小值,就能够算出当前价位卖出时可能得到的最大利润. 21 | * 22 | * @param array 23 | * @return 24 | */ 25 | public static int getMaxValue(int[] array) { 26 | if (null == array || 2 > array.length) { 27 | return -1; 28 | } 29 | 30 | int minNumber = array[0]; 31 | int maxValue = array[1] - array[0]; 32 | 33 | for (int i = 2; i < array.length; ++i) { 34 | if (array[i - 1] < minNumber) { 35 | minNumber = array[i - 1]; 36 | } 37 | 38 | int current = array[i] - minNumber; 39 | if (current > maxValue) { 40 | maxValue = current; 41 | } 42 | } 43 | 44 | return maxValue; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/algorithm/str/Problem042.java: -------------------------------------------------------------------------------- 1 | package algorithm.str; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 最长回文子串 leetcode 005 6 | * @date: 2018/09/07 7 | */ 8 | public class Problem042 { 9 | private int index; 10 | private int len; 11 | 12 | public static void main(String[] args) { 13 | Problem042 solution = new Problem042(); 14 | 15 | System.out.println(solution.longestPalindrome("ac")); 16 | } 17 | 18 | public String longestPalindrome(String s) { 19 | if (null == s || 2 > s.length()) { 20 | return s; 21 | } 22 | 23 | for (int i = 0; i < s.length() - 1; ++i) { 24 | palindromeHelper(s, i, i); 25 | palindromeHelper(s, i, i + 1); 26 | } 27 | 28 | return s.substring(index, index + len); 29 | } 30 | 31 | public void palindromeHelper(String s, int l, int r) { 32 | while (l >= 0 && r < s.length() && s.charAt(l) == s.charAt(r)) { 33 | --l; 34 | ++r; 35 | } 36 | 37 | // 发现更长的回文子序列,则进行更新 38 | if (len < r - l - 1) { 39 | index = l + 1; 40 | len = r - l - 1; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/algorithm/str/Problem07.java: -------------------------------------------------------------------------------- 1 | package algorithm.str; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 第一个只出现一次的字符 9 | * @date: 2018/09/08 10 | */ 11 | public class Problem07 { 12 | public static void main(String[] args) { 13 | String str = "abcabb"; 14 | 15 | int ans = FirstNotRepeatingChar(str); 16 | System.out.println((char)ans); 17 | } 18 | 19 | public static int FirstNotRepeatingChar(String str) { 20 | if (null == str || str.length() < 1) { 21 | return -1; 22 | } 23 | 24 | Map map = new HashMap<>(128); 25 | for (char c : str.toCharArray()) { 26 | map.put(c, map.getOrDefault(c, 0) + 1); 27 | } 28 | 29 | for (char c : str.toCharArray()) { 30 | if (1 == map.getOrDefault(c, 0)) { 31 | return c; 32 | } 33 | } 34 | return -1; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/algorithm/str/Problem08.java: -------------------------------------------------------------------------------- 1 | package algorithm.str; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 翻转字符串里的单词 6 | * @date: 2018/09/08 7 | */ 8 | public class Problem08 { 9 | 10 | public static void main(String[] args) { 11 | Problem08 test = new Problem08(); 12 | 13 | String ans = test.reverseWords(" 1"); 14 | System.out.println(ans); 15 | } 16 | 17 | public String reverseWords(String s) { 18 | if (null == s) { 19 | return s; 20 | } 21 | if (s.trim().length() == 0) { 22 | return s.trim(); 23 | } 24 | 25 | String[] temp = s.trim().split("\\s+"); 26 | 27 | StringBuilder stringBuilder = new StringBuilder(); 28 | for (int i = temp.length - 1; i > 0; --i) { 29 | stringBuilder.append(temp[i] + " "); 30 | } 31 | stringBuilder.append(temp[0]); 32 | return stringBuilder.toString(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/algorithm/str/Problem09.java: -------------------------------------------------------------------------------- 1 | package algorithm.str; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 旋转字符串 6 | * @date: 2018/09/08 7 | */ 8 | public class Problem09 { 9 | public boolean rotateString(String A, String B) { 10 | return A.length() == B.length() && (A + A).contains(B); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/algorithm/str/Problem0901.java: -------------------------------------------------------------------------------- 1 | package algorithm.str; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 左旋转字符串 6 | * @date: 2018/09/08 7 | */ 8 | public class Problem0901 { 9 | 10 | public static void main(String[] args) { 11 | String ans = leftRotateString("abcXYZdef", 3); 12 | 13 | System.out.println(ans); 14 | } 15 | 16 | 17 | public static String leftRotateString(String str, int n) { 18 | if (null == str || str.length() < 1) { 19 | return ""; 20 | } 21 | 22 | n %= str.length(); 23 | String s1 = str.substring(n); 24 | String s2 = str.substring(0, n); 25 | return s1 + s2; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/algorithm/str/Problem0902.java: -------------------------------------------------------------------------------- 1 | package algorithm.str; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 反转字符串 6 | * @date: 2018/09/08 7 | */ 8 | public class Problem0902 { 9 | public String reverseString(String s) { 10 | if (null == s || s.length() <= 1) { 11 | return s; 12 | } 13 | 14 | char[] temp = s.toCharArray(); 15 | StringBuilder stringBuilder = new StringBuilder(); 16 | for (int i = temp.length - 1; i >= 0; --i) { 17 | stringBuilder.append(temp[i]); 18 | } 19 | return stringBuilder.toString(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/algorithm/tmop/README.md: -------------------------------------------------------------------------------- 1 | # **编程之法** 2 | 3 | | 题号 | 题目 | 4 | |:----:| ------------------------------------------------------- | 5 | | 1-1 | [字符串的旋转](./Solution001.java) | 6 | | 1-1-1 | [单词翻转](./Solution002.java) | 7 | | 1-2 | [字符串的包含](./Solution003.java) | 8 | | 1-3 | [字符串的全排列](./Solution004.java) | 9 | | 1-4 | [字符串转换成整数](./Solution005.java) | 10 | | 1-5 | [回文判断](./Solution006.java) | 11 | | 1-5-1 | [判断单链表是否为回文](./Solution007.java) | 12 | | 1-6 | [最长回文子串](./Solution008.java) | 13 | | 2-2 | [寻找和为定值的两个数](./Solution009.java) | 14 | | 2-3 | [寻找和为定值的多个数](./Solution010.java) | 15 | | 2-4 | [最大连续子数组和](./Solution011.java) | 16 | | 2-5 | [跳台阶问题](./Solution012.java) | 17 | | 2-6 | [奇偶数排序](./Solution013.java) | 18 | | 2-7 | [荷兰国旗问题](./Solution014.java) | 19 | | 2-8 | [矩阵乘法](./Solution015.java) | 20 | | 2-9 | [完美洗牌算法](./Solution016.java) | 21 | | 3-3 | [二叉树的最近公共祖先](./Solution017.java) | 22 | | 4-1 | [有序数组的查找](./Solution018.java) | 23 | | 4-2 | [行列递增矩阵的查找](./Solution019.java) | 24 | | 4-3 | [出现次数超过一半的数](./Solution020.java) | 25 | | 5-1 | [最大连续乘积子数组](./Solution021.java) | 26 | | 5-2 | [字符串编辑距离](./Solution022.java) | 27 | | 5-4 | [交替字符串](./Solution023.java) | 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/algorithm/tmop/Solution.java: -------------------------------------------------------------------------------- 1 | package algorithm.tmop; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * 时间复杂度: O(n) 7 | * 空间复杂度: O(1) 8 | * @date: 9 | */ 10 | public class Solution { 11 | 12 | public static void main(String[] args){ 13 | 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/algorithm/tmop/Solution002.java: -------------------------------------------------------------------------------- 1 | package algorithm.tmop; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 时间复杂度: O(n) 6 | * 空间复杂度: O(n) 7 | * @date: 2018/11/20 8 | */ 9 | public class Solution002 { 10 | 11 | public static void main(String[] args) { 12 | final String input = "I am a student."; 13 | 14 | System.out.println(reverseSentence(input)); 15 | } 16 | 17 | public static String reverseSentence(String text) { 18 | if (null == text || 0 >= text.length()) { 19 | return null; 20 | } 21 | 22 | String[] tmp = text.split("\\s+"); 23 | StringBuilder stringBuilder = new StringBuilder(); 24 | for (int i = tmp.length - 1; i >= 0; --i) { 25 | stringBuilder.append(tmp[i]); 26 | if (0 != i) { 27 | stringBuilder.append(" "); 28 | } 29 | } 30 | 31 | return stringBuilder.toString(); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/algorithm/tmop/Solution006.java: -------------------------------------------------------------------------------- 1 | package algorithm.tmop; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 回文判断 6 | * 时间复杂度: O(n) 7 | * 空间复杂度: O(1) 8 | * @date: 9 | */ 10 | public class Solution006 { 11 | 12 | public static void main(String[] args) { 13 | final String text1 = "abcd"; 14 | final String text2 = "abcdcba"; 15 | final String text3 = "123454321"; 16 | 17 | System.out.println(isPalindrome(text1)); 18 | System.out.println(isPalindrome(text2)); 19 | System.out.println(isPalindrome(text3)); 20 | } 21 | 22 | public static boolean isPalindrome(String str) { 23 | if (null == str) { 24 | return false; 25 | } 26 | 27 | int start = 0; 28 | int end = str.length() - 1; 29 | while (start < end) { 30 | if (str.charAt(start) != str.charAt(end)) { 31 | return false; 32 | } 33 | ++start; 34 | --end; 35 | } 36 | 37 | return true; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/algorithm/tmop/Solution010.java: -------------------------------------------------------------------------------- 1 | package algorithm.tmop; 2 | 3 | import java.util.LinkedList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 寻找和为定值的多个数 9 | * 时间复杂度: O(n!) 10 | * 空间复杂度: 11 | * @date: 12 | */ 13 | public class Solution010 { 14 | 15 | public static void main(String[] args) { 16 | sumOfKNumber(10, 10, new LinkedList<>()); 17 | } 18 | 19 | /** 20 | * n 问题转化为 n-1 问题 21 | * 1.如果取第 n 个数,则问题转化为取前 n-1 个数使得它们的和为 sum-n 22 | * 2.如果不取第 n 个数,则问题转化为取前 n-1 个数使得它们的和为 sum 23 | * 24 | * @param sum 25 | * @param n 26 | * @param answer 27 | */ 28 | public static void sumOfKNumber(int sum, int n, List answer) { 29 | if (0 >= sum || 0 >= n) { 30 | return; 31 | } 32 | 33 | // 找到一组解,直接输出 34 | if (sum == n) { 35 | for (Integer num : answer) { 36 | System.out.print(num + " "); 37 | } 38 | System.out.println(n); 39 | } 40 | 41 | answer.add(n); 42 | sumOfKNumber(sum - n, n - 1, answer); 43 | answer.remove(answer.size() - 1); 44 | sumOfKNumber(sum, n - 1, answer); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/algorithm/tmop/Solution011.java: -------------------------------------------------------------------------------- 1 | package algorithm.tmop; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 最大连续子数组和 6 | * 时间复杂度: O(n) 7 | * 空间复杂度: O(1) 8 | * @date: 9 | */ 10 | public class Solution011 { 11 | 12 | public static void main(String[] args) { 13 | int[] array = {1, -2, 3, 10, -4, 7, 2, -5}; 14 | 15 | System.out.println(maxSubArray(array)); 16 | } 17 | 18 | public static int maxSubArray(int[] array) { 19 | if (null == array || 0 >= array.length) { 20 | return 0; 21 | } 22 | 23 | // 以前一位置元素结尾的最大连续子数组的和 24 | int preSum = 0; 25 | // 最大连续子数组的和 26 | int maxSum = array[0]; 27 | for (int i = 0; i < array.length; ++i) { 28 | if (0 <= preSum) { 29 | preSum += array[i]; 30 | } else { 31 | preSum = array[i]; 32 | } 33 | 34 | if (preSum > maxSum) { 35 | maxSum = preSum; 36 | } 37 | } 38 | 39 | return maxSum; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/algorithm/tmop/Solution012.java: -------------------------------------------------------------------------------- 1 | package algorithm.tmop; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 跳台阶问题 6 | * 时间复杂度: O(n) 7 | * 空间复杂度: O(1) 8 | * @date: 9 | */ 10 | public class Solution012 { 11 | 12 | public static void main(String[] args) { 13 | System.out.println(climbStairs(5)); 14 | } 15 | 16 | /** 17 | * 初始化指定 dp[0]=1 dp[1]=1(1台阶有1种走法), 则 n 台阶总共有dp[n]种走法 18 | * @param n 19 | * @return 20 | */ 21 | public static int climbStairs(int n) { 22 | int[] dp = {1, 1, 2}; 23 | 24 | if (1 >= n) { 25 | return 1; 26 | } 27 | 28 | for (int i = 2; i <= n; ++i) { 29 | dp[2] = dp[0] + dp[1]; 30 | dp[0] = dp[1]; 31 | dp[1] = dp[2]; 32 | } 33 | 34 | return dp[2]; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/algorithm/tmop/Solution016.java: -------------------------------------------------------------------------------- 1 | package algorithm.tmop; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 完美洗牌算法 6 | * 时间复杂度: O(n) 7 | * 空间复杂度: 8 | * @date: 9 | */ 10 | public class Solution016 { 11 | 12 | public static void main(String[] args) { 13 | int[] a = {0, 1, 2, 3, 4, 5, 6, 7, 8}; 14 | 15 | locationReplace(a); 16 | } 17 | 18 | /** 19 | * 下标从1开始计数 20 | * a1,a2,a3,a4,b1,b2,b3,b4 21 | * n 为4 22 | * 1.当 i <= n 时, 该元素在新数组中的下标为: 2*i 23 | * 2.当 i > n 时, 该元素在新数组中的下标为: (2*i)%(2*n+1) 24 | * 25 | * @param a 26 | */ 27 | public static void locationReplace(int[] a) { 28 | if (null == a || 0 >= a.length) { 29 | return; 30 | } 31 | 32 | int[] b = new int[a.length]; 33 | int n = (a.length - 1) >>> 1; 34 | int n2 = n * 2; 35 | 36 | for (int i = 1; i < a.length; ++i) { 37 | if (i <= n) { 38 | b[2 * i] = a[i]; 39 | } else { 40 | b[(2 * i) % (n2 + 1)] = a[i]; 41 | } 42 | } 43 | 44 | for (int num : b) { 45 | System.out.print(num + " "); 46 | } 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/algorithm/tmop/Solution017.java: -------------------------------------------------------------------------------- 1 | package algorithm.tmop; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 二叉树的最近公共祖先 6 | * @date: 2018/12/02 7 | */ 8 | public class Solution017 { 9 | 10 | /** 11 | * 在root为根的二叉树中找A,B的LCA: 12 | * 如果找到了就返回这个LCA 13 | * 如果只碰到A,就返回A 14 | * 如果只碰到B,就返回B 15 | * 如果都没有,就返回null 16 | * 17 | * @param root 18 | * @param p 19 | * @param q 20 | * @return 21 | */ 22 | public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { 23 | if (null == root || p == root || q == root) { 24 | return root; 25 | } 26 | 27 | TreeNode left = lowestCommonAncestor(root.left, p, q); 28 | TreeNode right = lowestCommonAncestor(root.right, p, q); 29 | if (null != left && null != right) { 30 | return root; 31 | } 32 | 33 | return null != left ? left : right; 34 | } 35 | 36 | private static class TreeNode { 37 | int val; 38 | TreeNode left; 39 | TreeNode right; 40 | 41 | TreeNode(int x) { 42 | val = x; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/algorithm/tmop/Solution018.java: -------------------------------------------------------------------------------- 1 | package algorithm.tmop; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 有序数组的查找 6 | * 时间复杂度: O(logN) 7 | * 空间复杂度: O(1) 8 | * @date: 9 | */ 10 | public class Solution018 { 11 | 12 | public static void main(String[] args) { 13 | int[] array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 14 | final int target = 8; 15 | System.out.println("target=" + target + "的下标为:" + binarySearch(array, target)); 16 | } 17 | 18 | /** 19 | * 对于有序数组,首选二分查找. 20 | * 找到元素则返回该元素的下标,未找到则返回-1 21 | * 22 | * @param array 23 | * @param target 24 | * @return 25 | */ 26 | public static int binarySearch(int[] array, int target) { 27 | if (null == array || 0 >= array.length) { 28 | return -1; 29 | } 30 | 31 | int left = 0; 32 | int right = array.length - 1; 33 | while (left <= right) { 34 | int middle = left + (right - left) / 2; 35 | if (array[middle] > target) { 36 | right = middle - 1; 37 | } else if (array[middle] < target) { 38 | left = middle + 1; 39 | } else { 40 | return middle; 41 | } 42 | } 43 | return -1; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/algorithm/tmop/Solution019.java: -------------------------------------------------------------------------------- 1 | package algorithm.tmop; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 行列递增矩阵的查找 6 | * 时间复杂度: O(m+n) 7 | * 空间复杂度: O(1) 8 | * @date: 9 | */ 10 | public class Solution019 { 11 | 12 | public static void main(String[] args) { 13 | int[][] matrix = { 14 | {1, 2, 8, 9}, 15 | {2, 4, 9, 12}, 16 | {4, 7, 10, 13}, 17 | {6, 8, 11, 15}}; 18 | 19 | final int target = 6; 20 | System.out.println(matrixSearch(matrix, target)); 21 | } 22 | 23 | public static boolean matrixSearch(int[][] matrix, int target) { 24 | if (null == matrix || 0 >= matrix.length) { 25 | return false; 26 | } 27 | 28 | int i = 0; 29 | int j = matrix[0].length - 1; 30 | while (true) { 31 | if (target == matrix[i][j]) { 32 | return true; 33 | } else if (target > matrix[i][j] && i < matrix.length - 1) { 34 | ++i; 35 | } else if (target < matrix[i][j] && j > 0) { 36 | --j; 37 | } else { 38 | return false; 39 | } 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/algorithm/tmop/Solution020.java: -------------------------------------------------------------------------------- 1 | package algorithm.tmop; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 出现次数超过一半的数 6 | * 时间复杂度: O(n) 7 | * 空间复杂度: O(1) 8 | * @date: 9 | */ 10 | public class Solution020 { 11 | 12 | public static void main(String[] args) { 13 | int[] array = {3, 1, 2, 3, 3, 0, 3}; 14 | 15 | System.out.println(findNumber(array)); 16 | } 17 | 18 | public static int findNumber(int[] array) { 19 | if (null == array || 0 >= array.length) { 20 | return -1; 21 | } 22 | 23 | int number = array[0]; 24 | int count = 1; 25 | for (int i = 1; i < array.length; ++i) { 26 | if (array[i] == number) { 27 | ++count; 28 | } else { 29 | if (1 == count) { 30 | number = array[i]; 31 | } else { 32 | --count; 33 | } 34 | } 35 | } 36 | return number; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/algorithm/tmop/Solution021.java: -------------------------------------------------------------------------------- 1 | package algorithm.tmop; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 最大连续乘积子数组 6 | * 时间复杂度: O(n) 7 | * 空间复杂度: O(1) 8 | * @date: 9 | */ 10 | public class Solution021 { 11 | 12 | public static void main(String[] args) { 13 | double[] array = {-2.5, 4, 0, 3, 0.5, 8, -1}; 14 | 15 | System.out.println(maxSubArray(array)); 16 | } 17 | 18 | public static double maxSubArray(double[] array) { 19 | if (null == array || 0 >= array.length) { 20 | return 0.0D; 21 | } 22 | 23 | double ans = array[0]; 24 | double maxEnd = array[0]; 25 | double minEnd = array[0]; 26 | for (int i = 1; i < array.length; ++i) { 27 | // 当前数字为正数时,以其结尾的最大乘积子数组来自于之前的最大 28 | // 当前数字为负数时,以其结尾的最大乘积子数组来自于之前的最小 29 | double end1 = maxEnd * array[i]; 30 | double end2 = minEnd * array[i]; 31 | maxEnd = Math.max(array[i], Math.max(end1, end2)); 32 | minEnd = Math.min(array[i], Math.min(end1, end2)); 33 | 34 | ans = Math.max(ans, maxEnd); 35 | } 36 | return ans; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/bishi/Main0901.java: -------------------------------------------------------------------------------- 1 | package bishi; 2 | 3 | import java.util.HashMap; 4 | import java.util.Scanner; 5 | 6 | /** 7 | * 拼多多 8 | *

9 | * 求循环小数位置和循环体长度 10 | */ 11 | public class Main0901 { 12 | public static void main(String[] args) { 13 | Scanner sc = new Scanner(System.in); 14 | int m = sc.nextInt(); 15 | int n = sc.nextInt(); 16 | 17 | HashMap map = new HashMap<>(); 18 | int k = m % n; 19 | int count = 0; 20 | while (map.get(k) == null && k != 0) { 21 | map.put(k, count++); 22 | k *= 10; 23 | k %= n; 24 | } 25 | if (k == 0) { 26 | System.out.println(count + " " + 0); 27 | } else { 28 | System.out.println(map.get(k) + " " + (count - map.get(k))); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/main/java/bishi/Main090401.java: -------------------------------------------------------------------------------- 1 | package bishi; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 求二进制中1的个数 8 | * @date: 2018/09/04 9 | */ 10 | public class Main090401 { 11 | public static void main(String[] args) { 12 | Scanner scanner = new Scanner(System.in); 13 | long number = scanner.nextLong(); 14 | long ans = 0; 15 | 16 | while (0 != number) { 17 | ++ans; 18 | number = number & (number - 1); 19 | } 20 | System.out.println(ans); 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/bishi/Main090402.java: -------------------------------------------------------------------------------- 1 | package bishi; 2 | 3 | import java.util.Arrays; 4 | import java.util.Scanner; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 9 | * @date: 2018/09/04 10 | */ 11 | public class Main090402 { 12 | public static void main(String[] args) { 13 | Scanner scanner = new Scanner(System.in); 14 | 15 | int n = Integer.parseInt(scanner.nextLine()); 16 | int targetTime = Integer.parseInt(scanner.nextLine()); 17 | int[][] matrix = new int[n][3]; 18 | 19 | for (int i = 0; i < n; ++i) { 20 | String[] temp = scanner.nextLine().split("\\s+"); 21 | matrix[i][0] = Integer.parseInt(temp[0]); 22 | matrix[i][1] = Integer.parseInt(temp[1]); 23 | matrix[i][2] = Integer.parseInt(temp[2]); 24 | } 25 | 26 | Arrays.sort(matrix, (a, b) -> (a[0] - b[0])); 27 | 28 | boolean flag = false; 29 | for (int i = 0; i < n; ++i) { 30 | if (matrix[i][1] <= targetTime && targetTime <= matrix[i][2]) { 31 | flag = true; 32 | System.out.println(matrix[i][0]); 33 | } 34 | } 35 | if (!flag) { 36 | System.out.println("null"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/bishi/Main090601.java: -------------------------------------------------------------------------------- 1 | package bishi; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/09/06 9 | */ 10 | public class Main090601 { 11 | public static void main(String args[]) { 12 | Scanner scanner = new Scanner(System.in); 13 | int n = Integer.parseInt(scanner.nextLine()); 14 | 15 | int[] from = new int[n + 1]; 16 | int[] to = new int[n + 1]; 17 | 18 | for (int i = 1; i < n; ++i) { 19 | String[] temp = scanner.nextLine().split("\\s+"); 20 | int x = Integer.parseInt(temp[0]); 21 | int y = Integer.parseInt(temp[1]); 22 | from[i] = x; 23 | to[i] = y; 24 | } 25 | 26 | if (n <= 4) { 27 | System.out.println(n); 28 | } else { 29 | System.out.println(n + 3); 30 | } 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/bishi/Main090702.java: -------------------------------------------------------------------------------- 1 | package bishi; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/09/06 9 | */ 10 | public class Main090702 { 11 | public static void main(String args[]) { 12 | Scanner scanner = new Scanner(System.in); 13 | int testNumber = Integer.parseInt(scanner.nextLine()); 14 | 15 | while (0 < testNumber--) { 16 | String[] temp = scanner.nextLine().split("\\s+"); 17 | int n = Integer.parseInt(temp[0]); 18 | int k = Integer.parseInt(temp[1]); 19 | int leave = n - k; 20 | if (0 == k || n == k) { 21 | System.out.println("0 0"); 22 | continue; 23 | } 24 | if (2 >= n) { 25 | System.out.println("0 0"); 26 | continue; 27 | } 28 | 29 | int min = 0, max = leave; 30 | if (k <= leave) { 31 | max = k - 1; 32 | } 33 | 34 | 35 | System.out.println(min + " " + max); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/bishi/Main0909001.java: -------------------------------------------------------------------------------- 1 | package bishi; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | */ 7 | public class Main0909001 { 8 | public static void main(String[] args) { 9 | Scanner sc = new Scanner(System.in); 10 | int testNumber = Integer.parseInt(sc.nextLine()); 11 | 12 | while (0 < testNumber--) { 13 | int n = sc.nextInt(); 14 | int m = sc.nextInt(); 15 | 16 | int[][] matrix = new int[m][2]; 17 | for (int i = 0; i < m; ++i) { 18 | matrix[i][0] = sc.nextInt(); 19 | matrix[i][1] = sc.nextInt(); 20 | } 21 | 22 | if (0 == (n + m) % 2) { 23 | System.out.println("NO"); 24 | } 25 | System.out.println("YES"); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/main/java/bishi/Main0909002.java: -------------------------------------------------------------------------------- 1 | package bishi; 2 | 3 | import java.util.Arrays; 4 | import java.util.Scanner; 5 | 6 | /** 7 | */ 8 | public class Main0909002 { 9 | public static void main(String[] args) { 10 | Scanner scanner = new Scanner(System.in); 11 | int n = Integer.parseInt(scanner.nextLine()); 12 | 13 | int[][] matrix = new int[n][3]; 14 | for (int i = 0; i < n; ++i) { 15 | matrix[i][0] = scanner.nextInt(); 16 | matrix[i][1] = scanner.nextInt(); 17 | matrix[i][2] = scanner.nextInt(); 18 | } 19 | 20 | Arrays.sort(matrix, (a, b) -> (a[0] - b[0])); 21 | 22 | int ans = 0; 23 | for (int i = 0; i < n; ++i) { 24 | for (int j = 0; j < n; ++j) { 25 | if ((matrix[i][0] < matrix[j][0]) && 26 | (matrix[i][1] < matrix[j][1]) && 27 | (matrix[i][2] < matrix[j][2])) { 28 | ++ans; 29 | break; 30 | } 31 | } 32 | } 33 | 34 | System.out.println(ans); 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/java/bishi/Main090901.java: -------------------------------------------------------------------------------- 1 | package bishi; 2 | 3 | import java.util.HashSet; 4 | import java.util.Scanner; 5 | import java.util.Set; 6 | 7 | /** 8 | * @author: mayuan 9 | * @desc: 10 | * @date: 2018/09/09 11 | */ 12 | public class Main090901 { 13 | public static void main(String args[]) { 14 | Scanner scanner = new Scanner(System.in); 15 | 16 | String str = scanner.nextLine(); 17 | 18 | int maxLength = 0; 19 | Set set = new HashSet<>(); 20 | 21 | int count = 0; 22 | for (int i = 0; i < str.length(); ++i) { 23 | char c = str.charAt(i); 24 | if (!set.contains(c)) { 25 | set.add(c); 26 | ++count; 27 | if (maxLength < count) { 28 | maxLength = count; 29 | } 30 | } else { 31 | count = 1; 32 | if (maxLength < count) { 33 | maxLength = count; 34 | } 35 | set.clear(); 36 | set.add(c); 37 | } 38 | } 39 | 40 | System.out.println(maxLength); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/bishi/Main091601.java: -------------------------------------------------------------------------------- 1 | package bishi; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | */ 7 | public class Main091601 { 8 | public static void main(String[] args) { 9 | Scanner scanner = new Scanner(System.in); 10 | int n = Integer.parseInt(scanner.nextLine()); 11 | int[] numbers = new int[n]; 12 | int[] sum = new int[n]; 13 | 14 | for (int i = 0; i < n; ++i) { 15 | numbers[i] = scanner.nextInt(); 16 | if (0 != i) { 17 | sum[i] = sum[i - 1] + numbers[i]; 18 | } else { 19 | sum[i] = numbers[0]; 20 | } 21 | } 22 | 23 | boolean hasAnswer = false; 24 | int max = (numbers[0] > numbers[1]) ? numbers[0] : numbers[1]; 25 | for (int i = 2; i < n; ++i) { 26 | max = (numbers[i] > max) ? numbers[i] : max; 27 | if (max < sum[i] - max) { 28 | hasAnswer = true; 29 | System.out.println(i + 1); 30 | break; 31 | } 32 | } 33 | 34 | if (!hasAnswer) { 35 | System.out.println(-1); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/bishi/iqiyi/Main091501.java: -------------------------------------------------------------------------------- 1 | package bishi.iqiyi; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | */ 7 | public class Main091501 { 8 | public static void main(String[] args) { 9 | Scanner sc = new Scanner(System.in); 10 | 11 | String[] numbers = sc.nextLine().split("\\s+"); 12 | int k = Integer.parseInt(sc.nextLine()); 13 | 14 | for (int i = 0; i < numbers.length; i += k) { 15 | reverse(numbers, i, i + k - 1); 16 | } 17 | 18 | for (int i = 0; i < numbers.length; ++i) { 19 | System.out.print(numbers[i] + " "); 20 | } 21 | } 22 | 23 | private static void reverse(String[] strs, int start, int end) { 24 | if (end >= strs.length) { 25 | return; 26 | } 27 | 28 | while (start < end) { 29 | String temp = strs[start]; 30 | strs[start] = strs[end]; 31 | strs[end] = temp; 32 | 33 | ++start; 34 | --end; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/java/bishi/iqiyi/Main091502.java: -------------------------------------------------------------------------------- 1 | package bishi.iqiyi; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | */ 7 | public class Main091502 { 8 | public static void main(String[] args) { 9 | Scanner sc = new Scanner(System.in); 10 | 11 | int n = Integer.parseInt(sc.nextLine()); 12 | 13 | if (n < 5) { 14 | System.out.println(0); 15 | return; 16 | } 17 | 18 | int sum = 0; 19 | int pre = 0; 20 | int current = 0; 21 | for (int i = 5; i <= n; ++i) { 22 | current = pre + countNumberOf5(i); 23 | 24 | sum += current; 25 | 26 | pre = current; 27 | } 28 | 29 | System.out.println(sum); 30 | } 31 | 32 | public static int countNumberOf5(int n) { 33 | int ans = 0; 34 | 35 | if (5 > n || 0 != (n % 5)) { 36 | return ans; 37 | } else { 38 | ++ans; 39 | return ans + countNumberOf5(n / 5); 40 | } 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/main/java/concurrent/CountDownLatchExample.java: -------------------------------------------------------------------------------- 1 | package concurrent; 2 | 3 | import java.util.concurrent.CountDownLatch; 4 | import java.util.concurrent.ExecutorService; 5 | import java.util.concurrent.Executors; 6 | 7 | /** 8 | * @author: mayuan 9 | * @desc: 用来控制一个线程等待多个线程。(某个线程等待多个线程到达) 10 | * 维护了一个计数器 cnt,每次调用 countDown() 方法会让计数器的值减 1,减到 0 的时候,那个因为调用 await() 方法而在等待的线程就会被唤醒。 11 | * @date: 2018/09/14 12 | */ 13 | public class CountDownLatchExample { 14 | 15 | public static void main(String[] args) { 16 | final int totalThread = 10; 17 | 18 | CountDownLatch countDownLatch = new CountDownLatch(totalThread); 19 | 20 | ExecutorService executorService = Executors.newCachedThreadPool(); 21 | for (int i = 0; i < totalThread; ++i) { 22 | executorService.execute(() -> { 23 | System.out.println("hello CountDownLatch."); 24 | countDownLatch.countDown(); 25 | }); 26 | } 27 | try { 28 | countDownLatch.await(); 29 | } catch (InterruptedException e) { 30 | e.printStackTrace(); 31 | } 32 | System.out.println("all come."); 33 | executorService.shutdown(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt01/TryConcurrency.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt01; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/06/27 9 | */ 10 | public class TryConcurrency { 11 | public static void main(String[] args) { 12 | new Thread(TryConcurrency::enjoyMusic).start(); 13 | new Thread(TryConcurrency::browseNews).start(); 14 | } 15 | 16 | private static void browseNews() { 17 | while (true) { 18 | System.out.println("游览网页中..."); 19 | sleep(1); 20 | } 21 | } 22 | 23 | private static void enjoyMusic() { 24 | while (true) { 25 | System.out.println("听音乐中..."); 26 | sleep(1); 27 | } 28 | } 29 | 30 | private static void sleep(int seconds) { 31 | if (seconds < 0) { 32 | seconds = 0; 33 | } 34 | 35 | try { 36 | TimeUnit.SECONDS.sleep(seconds); 37 | } catch (InterruptedException e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt02/DaemonThread.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt02; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/06/28 7 | */ 8 | public class DaemonThread { 9 | 10 | public static void main(String[] args) throws InterruptedException { 11 | Thread thread = new Thread(() -> { 12 | while (true) { 13 | try { 14 | Thread.sleep(1); 15 | } catch (InterruptedException e) { 16 | e.printStackTrace(); 17 | } 18 | } 19 | }); 20 | // 守护线程具备自动结束生命周期的特性 21 | thread.setDaemon(true); 22 | thread.start(); 23 | 24 | Thread.sleep(2_000L); 25 | System.out.println("Main thread finished lifecycle."); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt02/ThreadConstruction.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt02; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/06/28 7 | */ 8 | public class ThreadConstruction { 9 | 10 | public static void main(String[] args) { 11 | System.out.println(args.length); 12 | System.out.println(args); 13 | 14 | 15 | Thread t1 = new Thread("t1"); 16 | 17 | ThreadGroup group = new ThreadGroup("TestGroup"); 18 | Thread t2 = new Thread(group, "t2"); 19 | 20 | ThreadGroup mainGroup = Thread.currentThread().getThreadGroup(); 21 | 22 | System.out.println("Main thread belong to " + mainGroup.getName() + " group."); 23 | System.out.println("t1 thread belong to " + t1.getThreadGroup().getName() + " group."); 24 | System.out.println("t2 thread belong to " + t2.getThreadGroup().getName() + " group."); 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt03/CurrentThread.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt03; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/06/30 7 | */ 8 | public class CurrentThread { 9 | public static void main(String[] args) { 10 | Thread thread = new Thread() { 11 | @Override 12 | public void run() { 13 | System.out.println("当前线程名:" + Thread.currentThread().getName()); 14 | System.out.println(Thread.currentThread() == this); 15 | } 16 | }; 17 | thread.start(); 18 | 19 | String name = Thread.currentThread().getName(); 20 | System.out.println("当前线程名:" + name); 21 | System.out.println("main".equals(name)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt03/FlagThreadExit.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt03; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/07/01 9 | */ 10 | public class FlagThreadExit { 11 | 12 | public static void main(String[] args) throws InterruptedException { 13 | MyTask t = new MyTask(); 14 | t.start(); 15 | 16 | TimeUnit.SECONDS.sleep(5); 17 | System.out.println("System will be shutdown."); 18 | t.close(); 19 | } 20 | 21 | static class MyTask extends Thread { 22 | private volatile boolean closed = false; 23 | 24 | @Override 25 | public void run() { 26 | System.out.println("I will start work."); 27 | while (!closed && !isInterrupted()) { 28 | 29 | } 30 | System.out.println("I will be exiting."); 31 | } 32 | 33 | public void close() { 34 | this.closed = true; 35 | this.interrupt(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt03/ThreadInterrupt.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt03; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/06/30 9 | */ 10 | public class ThreadInterrupt { 11 | public static void main(String[] args) throws InterruptedException { 12 | Thread thread = new Thread(() -> { 13 | try { 14 | TimeUnit.MINUTES.sleep(1); 15 | } catch (InterruptedException e) { 16 | System.out.println("Oh, i am be interrupted."); 17 | e.printStackTrace(); 18 | } 19 | }); 20 | thread.start(); 21 | 22 | TimeUnit.MILLISECONDS.sleep(2); 23 | thread.interrupt(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt03/ThreadInterrupted.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt03; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/06/30 9 | */ 10 | public class ThreadInterrupted { 11 | public static void main(String[] args) throws InterruptedException { 12 | Thread thread = new Thread(() -> { 13 | while (true) { 14 | 15 | } 16 | }); 17 | thread.start(); 18 | 19 | TimeUnit.MILLISECONDS.sleep(2); 20 | System.out.printf("Thread is interrupted ? %s\n", thread.isInterrupted()); 21 | thread.interrupt(); 22 | System.out.printf("Thread is interrupted ? %s\n", thread.isInterrupted()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt03/ThreadInterrupted2.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt03; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/06/30 9 | */ 10 | public class ThreadInterrupted2 { 11 | public static void main(String[] args) throws InterruptedException { 12 | Thread thread = new Thread() { 13 | @Override 14 | public void run() { 15 | while (true) { 16 | try { 17 | TimeUnit.MINUTES.sleep(1); 18 | } catch (InterruptedException e) { 19 | System.out.printf("I am be interrupted ? %s\n", isInterrupted()); 20 | } 21 | } 22 | } 23 | }; 24 | thread.setDaemon(true); 25 | thread.start(); 26 | 27 | TimeUnit.MILLISECONDS.sleep(2); 28 | System.out.printf("Thread be interrupted ? %s\n", thread.isInterrupted()); 29 | Thread.interrupted(); 30 | System.out.printf("Thread be interrupted ? %s\n", thread.isInterrupted()); 31 | TimeUnit.MILLISECONDS.sleep(2); 32 | System.out.printf("Thread be interrupted ? %s\n", thread.isInterrupted()); 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt03/ThreadInterrupted3.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt03; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/06/30 9 | */ 10 | public class ThreadInterrupted3 { 11 | public static void main(String[] args) throws InterruptedException { 12 | Thread thread = new Thread() { 13 | @Override 14 | public void run() { 15 | while (true) { 16 | boolean fl = Thread.interrupted(); 17 | if (fl){ 18 | System.out.print("**************"); 19 | } 20 | System.out.println(fl); 21 | } 22 | } 23 | }; 24 | thread.setDaemon(true); 25 | thread.start(); 26 | 27 | TimeUnit.MILLISECONDS.sleep(2); 28 | thread.interrupt(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt03/ThreadInterrupted4.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt03; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/06/30 9 | */ 10 | public class ThreadInterrupted4 { 11 | public static void main(String[] args) { 12 | System.out.println("Main thread is interrupted? " + Thread.interrupted()); 13 | 14 | Thread.currentThread().interrupt(); 15 | 16 | System.out.println("Main thread is interrupted? " + Thread.currentThread().isInterrupted()); 17 | 18 | try { 19 | TimeUnit.MINUTES.sleep(1); 20 | } catch (InterruptedException e) { 21 | System.out.println("I will be interrupted still."); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt03/ThreadPriority.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt03; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/06/30 9 | */ 10 | public class ThreadPriority { 11 | 12 | public static void main(String[] args) { 13 | Thread t1 = new Thread(() -> { 14 | while (true) { 15 | System.out.println("t1"); 16 | try { 17 | TimeUnit.SECONDS.sleep(2); 18 | } catch (InterruptedException e) { 19 | e.printStackTrace(); 20 | } 21 | } 22 | }); 23 | // 线程优先级最小为 1, 最大为 10, 默认为 5. 且不能大于线程所在 group 的优先级. 24 | t1.setPriority(3); 25 | 26 | Thread t2 = new Thread(() -> { 27 | while (true) { 28 | System.out.println("t2"); 29 | try { 30 | TimeUnit.SECONDS.sleep(2); 31 | } catch (InterruptedException e) { 32 | e.printStackTrace(); 33 | } 34 | } 35 | }); 36 | t2.setPriority(10); 37 | 38 | t1.start(); 39 | t2.start(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt03/ThreadPriority2.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt03; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/06/30 7 | */ 8 | public class ThreadPriority2 { 9 | 10 | public static void main(String[] args) { 11 | ThreadGroup group = new ThreadGroup("testGroup"); 12 | // 将线程组的优先级指定为 7 13 | group.setMaxPriority(7); 14 | // 定义一个线程,将线程加入到 group 中 15 | Thread thread = new Thread(group, "test-thread"); 16 | // 企图将线程的优先级设定为 10 17 | thread.setPriority(10); 18 | // 企图未遂 19 | System.out.println("线程真实优先级为: " + thread.getPriority()); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt03/ThreadPriority3.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt03; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/06/30 7 | */ 8 | public class ThreadPriority3 { 9 | public static void main(String[] args) { 10 | Thread t1 = new Thread(); 11 | System.out.println("t1 priority " + t1.getPriority()); 12 | 13 | Thread t2 = new Thread(() -> { 14 | Thread t3 = new Thread(); 15 | System.out.println("t3 priority " + t3.getPriority()); 16 | }); 17 | 18 | t2.setPriority(6); 19 | t2.start(); 20 | System.out.println("t2 priority " + t2.getPriority()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt03/ThreadSleep.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt03; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/06/29 7 | */ 8 | public class ThreadSleep { 9 | public static void main(String[] args) { 10 | new Thread(() -> { 11 | long startTime = System.currentTimeMillis(); 12 | sleep(2_000L); 13 | long endTime = System.currentTimeMillis(); 14 | System.out.println(String.format("Current Thread Total spend %d ms", (endTime - startTime))); 15 | }).start(); 16 | 17 | long startTime = System.currentTimeMillis(); 18 | sleep(3_000L); 19 | long endTime = System.currentTimeMillis(); 20 | System.out.println(String.format("Main Thread total spend %d ms", (endTime - startTime))); 21 | 22 | } 23 | 24 | private static void sleep(long ms) { 25 | try { 26 | if (ms < 0) { 27 | ms = 0; 28 | } 29 | Thread.sleep(ms); 30 | } catch (InterruptedException e) { 31 | 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt03/ThreadYield.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt03; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/06/29 9 | */ 10 | public class ThreadYield { 11 | 12 | public static void main(String[] args) { 13 | IntStream.range(0, 2).mapToObj(ThreadYield::create).forEach(Thread::start); 14 | } 15 | 16 | private static Thread create(int index) { 17 | return new Thread(() -> { 18 | if (0 == index) { 19 | Thread.yield(); 20 | } 21 | System.out.println(index); 22 | }); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt04/Mutex.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt04; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/07/01 9 | */ 10 | public class Mutex { 11 | private final static Object MUTEX = new Object(); 12 | 13 | public void accessResource() { 14 | synchronized (MUTEX) { 15 | try { 16 | TimeUnit.MINUTES.sleep(10); 17 | } catch (InterruptedException e) { 18 | e.printStackTrace(); 19 | } 20 | } 21 | } 22 | 23 | public static void main(String[] args) { 24 | final Mutex mutex = new Mutex(); 25 | 26 | for (int i = 0; i < 5; i++) { 27 | new Thread(mutex::accessResource).start(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt04/ThisMonitor.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt04; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import static java.lang.Thread.currentThread; 6 | 7 | /** 8 | * @author: mayuan 9 | * @desc: 10 | * @date: 2018/07/02 11 | */ 12 | public class ThisMonitor { 13 | 14 | public static void main(String[] args) { 15 | ThisMonitor thisMonitor = new ThisMonitor(); 16 | new Thread(thisMonitor::method1, "T1").start(); 17 | new Thread(thisMonitor::method2, "T2").start(); 18 | } 19 | 20 | public synchronized void method1() { 21 | System.out.println(currentThread().getName() + " enter to method1."); 22 | try { 23 | TimeUnit.MINUTES.sleep(10); 24 | } catch (InterruptedException e) { 25 | e.printStackTrace(); 26 | } 27 | } 28 | 29 | public synchronized void method2() { 30 | System.out.println(currentThread().getName() + " enter to method2."); 31 | try { 32 | TimeUnit.MINUTES.sleep(10); 33 | } catch (InterruptedException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt04/ThisMonitor2.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt04; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import static java.lang.Thread.currentThread; 6 | 7 | /** 8 | * @author: mayuan 9 | * @desc: 10 | * @date: 2018/07/02 11 | */ 12 | public class ThisMonitor2 { 13 | 14 | public static void main(String[] args) { 15 | ThisMonitor2 thisMonitor = new ThisMonitor2(); 16 | new Thread(thisMonitor::method1, "T1").start(); 17 | new Thread(thisMonitor::method2, "T2").start(); 18 | } 19 | 20 | public synchronized void method1() { 21 | System.out.println(currentThread().getName() + " enter to method1."); 22 | try { 23 | TimeUnit.MINUTES.sleep(10); 24 | } catch (InterruptedException e) { 25 | e.printStackTrace(); 26 | } 27 | } 28 | 29 | public void method2() { 30 | synchronized (this) { 31 | System.out.println(currentThread().getName() + " enter to method2."); 32 | try { 33 | TimeUnit.MINUTES.sleep(10); 34 | } catch (InterruptedException e) { 35 | e.printStackTrace(); 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt04/TicketWindowRunnable.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt04; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/01 7 | */ 8 | public class TicketWindowRunnable implements Runnable { 9 | private int index = 1; 10 | 11 | private final static int MAX = 50; 12 | 13 | private final static Object MUTEX = new Object(); 14 | 15 | @Override 16 | public void run() { 17 | synchronized (MUTEX) { 18 | while (index <= MAX) { 19 | System.out.println(Thread.currentThread() + " 的号码是:" + (index++)); 20 | } 21 | } 22 | } 23 | 24 | public static void main(String[] args) { 25 | final TicketWindowRunnable task = new TicketWindowRunnable(); 26 | 27 | Thread t1 = new Thread(task, "1号窗口"); 28 | 29 | Thread t2 = new Thread(task, "2号窗口"); 30 | 31 | Thread t3 = new Thread(task, "3号窗口"); 32 | 33 | Thread t4 = new Thread(task, "4号窗口"); 34 | 35 | t1.start(); 36 | t2.start(); 37 | t3.start(); 38 | t4.start(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt05/EventClient.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt05; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/07/03 9 | */ 10 | public class EventClient { 11 | 12 | public static void main(String[] args) { 13 | final EventQueue eventQueue = new EventQueue(); 14 | new Thread(() -> { 15 | while (true) { 16 | eventQueue.offer(new EventQueue.Event()); 17 | } 18 | }, "Producer").start(); 19 | 20 | new Thread(() -> { 21 | while (true) { 22 | eventQueue.take(); 23 | try { 24 | TimeUnit.SECONDS.sleep(10); 25 | } catch (InterruptedException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | }, "Consumer").start(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt06/ThreadGroupCreateror.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt06; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/04 7 | */ 8 | public class ThreadGroupCreateror { 9 | public static void main(String[] args) { 10 | ThreadGroup currentGroup = Thread.currentThread().getThreadGroup(); 11 | 12 | ThreadGroup group1 = new ThreadGroup("Group1"); 13 | 14 | System.out.println(currentGroup.getName()); 15 | System.out.println(group1.getParent() == currentGroup); 16 | 17 | ThreadGroup group2 = new ThreadGroup("Group2"); 18 | 19 | System.out.println(group1.getName()); 20 | System.out.println(group2.getParent() == group1); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt07/CaptureThreadException.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt07; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/07/05 9 | */ 10 | public class CaptureThreadException { 11 | public static void main(String[] args) { 12 | Thread.setDefaultUncaughtExceptionHandler((t, e) -> { 13 | System.out.println(t.getName() + " occur exception."); 14 | e.printStackTrace(); 15 | }); 16 | 17 | final Thread thread = new Thread(() -> { 18 | try { 19 | TimeUnit.SECONDS.sleep(2); 20 | } catch (InterruptedException e) { 21 | } 22 | 23 | System.out.println(1 / 0); 24 | }, "Test-Thread"); 25 | 26 | thread.start(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt07/EmptyExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt07; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/07/05 9 | */ 10 | public class EmptyExceptionHandler { 11 | 12 | public static void main(String[] args) { 13 | ThreadGroup mainGroup = Thread.currentThread().getThreadGroup(); 14 | System.out.println(mainGroup.getName()); 15 | System.out.println(mainGroup.getParent()); 16 | System.out.println(mainGroup.getParent().getParent()); 17 | 18 | final Thread thread = new Thread(() -> { 19 | try { 20 | TimeUnit.SECONDS.sleep(2); 21 | } catch (InterruptedException e) { 22 | } 23 | 24 | System.out.println(1 / 0); 25 | }, "Test-Thread"); 26 | 27 | thread.start(); 28 | 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt09/ActiveLoadTest.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt09; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/07 7 | */ 8 | public class ActiveLoadTest { 9 | public static void main(String[] args) { 10 | System.out.println(Child.y); 11 | // System.out.println(Child.x); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt09/Child.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt09; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/07 7 | */ 8 | public class Child extends Parent { 9 | static { 10 | System.out.println("The child will be initialized."); 11 | } 12 | 13 | public static int x = 10; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt09/ClassInit.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt09; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | import java.util.stream.IntStream; 5 | 6 | /** 7 | * @author: mayuan 8 | * @desc: 9 | * @date: 2018/07/07 10 | */ 11 | public class ClassInit { 12 | 13 | static { 14 | try { 15 | System.out.println("The ClassInit static code block will be invoke."); 16 | TimeUnit.MINUTES.sleep(10); 17 | } catch (InterruptedException e) { 18 | e.printStackTrace(); 19 | } 20 | } 21 | 22 | public static void main(String[] args) { 23 | IntStream.range(0, 5).forEach(i -> new Thread((ClassInit::new))); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt09/Parent.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt09; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/07 7 | */ 8 | public class Parent { 9 | static { 10 | System.out.println("The parent is initialized"); 11 | } 12 | 13 | public static int y = 100; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt09/Price.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt09; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/08 7 | */ 8 | public class Price { 9 | 10 | final static Price instance = new Price(2.8); 11 | 12 | static double initPrice = 20; 13 | 14 | double currentPrice; 15 | 16 | public Price(double discount){ 17 | currentPrice = initPrice - discount; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt09/PriceTest.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt09; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/08 7 | */ 8 | public class PriceTest { 9 | public static void main(String[] args) { 10 | System.out.println(Price.instance.currentPrice); 11 | Price price = new Price(2.8); 12 | System.out.println(price.currentPrice); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt09/Singleton.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt09; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/07 7 | */ 8 | public class Singleton { 9 | 10 | private static int x = 0; 11 | 12 | private static int y; 13 | 14 | private static Singleton instance = new Singleton(); 15 | 16 | private Singleton() { 17 | x++; 18 | y++; 19 | } 20 | 21 | public static Singleton getInstance() { 22 | return instance; 23 | } 24 | 25 | public static void main(String[] args) { 26 | Singleton singleton = Singleton.getInstance(); 27 | System.out.println(singleton.x); 28 | System.out.println(singleton.y); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt09/Singleton2.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt09; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/07 7 | */ 8 | public class Singleton2 { 9 | 10 | private static Singleton2 instance = new Singleton2(); 11 | 12 | private static int x = 0; 13 | 14 | private static int y; 15 | 16 | private Singleton2() { 17 | x++; 18 | y++; 19 | } 20 | 21 | public static Singleton2 getInstance() { 22 | return instance; 23 | } 24 | 25 | public static void main(String[] args) { 26 | Singleton2 singleton = Singleton2.getInstance(); 27 | System.out.println(singleton.x); 28 | System.out.println(singleton.y); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt09/StaticInitTest.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt09; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/08 7 | */ 8 | public class StaticInitTest { 9 | 10 | static int count = 2; 11 | 12 | static { 13 | System.out.println("StaticInitTest"); 14 | name = "Java 编程"; 15 | } 16 | 17 | static String name = "疯狂Java讲义"; 18 | 19 | public static void main(String[] args) { 20 | System.out.println("count: " + count); 21 | System.out.println("name: " + name); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt10/ApplicationClassLoader.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt10; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/09 7 | */ 8 | public class ApplicationClassLoader { 9 | public static void main(String[] args) { 10 | System.out.println(System.getProperty("java.class.path")); 11 | System.out.println(ApplicationClassLoader.class.getClassLoader()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt10/BootstrapClassLoader.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt10; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/09 7 | */ 8 | public class BootstrapClassLoader { 9 | public static void main(String[] args) { 10 | System.out.println("Bootstrap:" + String.class.getClassLoader()); 11 | System.out.println(System.getProperty("sun.boot.class.path")); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt10/ExtClassLoader.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt10; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/09 7 | */ 8 | public class ExtClassLoader { 9 | public static void main(String[] args) { 10 | System.out.println(System.getProperty("java.ext.dirs")); 11 | System.out.println(ExtClassLoader.class.getClassLoader()); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/concurrent/cpt12/VolatileFoo.java: -------------------------------------------------------------------------------- 1 | package concurrent.cpt12; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * @author: mayuan 7 | * @desc: 8 | * @date: 2018/07/09 9 | */ 10 | public class VolatileFoo { 11 | 12 | final static int MAX = 5; 13 | static int init_value = 0; 14 | 15 | public static void main(String[] args) { 16 | new Thread(() -> { 17 | int localValue = init_value; 18 | while (localValue < MAX) { 19 | if (localValue != init_value) { 20 | System.out.println("The init_value is updated to " + init_value); 21 | localValue = init_value; 22 | } 23 | } 24 | }, "Reader").start(); 25 | 26 | new Thread(() -> { 27 | int localValue = init_value; 28 | while (localValue < MAX) { 29 | System.out.println("The init_value will be changed to " + (++localValue)); 30 | init_value = localValue; 31 | try { 32 | TimeUnit.SECONDS.sleep(2); 33 | } catch (InterruptedException e) { 34 | e.printStackTrace(); 35 | } 36 | } 37 | }, "Updater").start(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/design/builder/Client.java: -------------------------------------------------------------------------------- 1 | package design.builder; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class Client { 9 | public static void main(String[] args) { 10 | MyStringBuilder msb = new MyStringBuilder(); 11 | final int count = 26; 12 | for (int i = 0; i < count; i++) { 13 | msb.append((char) ('A' + i)); 14 | } 15 | System.out.println(msb.toString()); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/design/builder/MyStringBuilder.java: -------------------------------------------------------------------------------- 1 | package design.builder; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class MyStringBuilder extends AbstractStringBuilder { 9 | public MyStringBuilder() { 10 | super(16); 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | return new String(value, 0, count); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/design/chainofresponsibility/Client.java: -------------------------------------------------------------------------------- 1 | package design.chainofresponsibility; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class Client { 9 | public static void main(String[] args) { 10 | Handler handler1 = new ConcreteHandler1(null); 11 | Handler handler2 = new ConcreteHandler2(handler1); 12 | 13 | Request request1 = new Request(RequestType.type1, "request1"); 14 | handler2.handleRequest(request1); 15 | 16 | Request request2 = new Request(RequestType.type2, "request2"); 17 | handler2.handleRequest(request2); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/design/chainofresponsibility/ConcreteHandler1.java: -------------------------------------------------------------------------------- 1 | package design.chainofresponsibility; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class ConcreteHandler1 extends Handler { 9 | 10 | public ConcreteHandler1(Handler successor) { 11 | super(successor); 12 | } 13 | 14 | @Override 15 | protected void handleRequest(Request request) { 16 | if (request.getType() == RequestType.type1) { 17 | System.out.println(request.getName() + " is handle by ConcreteHandler1"); 18 | return; 19 | } 20 | if (null != successor) { 21 | successor.handleRequest(request); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/design/chainofresponsibility/ConcreteHandler2.java: -------------------------------------------------------------------------------- 1 | package design.chainofresponsibility; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class ConcreteHandler2 extends Handler { 9 | 10 | public ConcreteHandler2(Handler successor) { 11 | super(successor); 12 | } 13 | 14 | @Override 15 | protected void handleRequest(Request request) { 16 | if (request.getType() == RequestType.type2) { 17 | System.out.println(request.getName() + " is handle by ConcreteHandler2"); 18 | return; 19 | } 20 | if (null != successor) { 21 | successor.handleRequest(request); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/design/chainofresponsibility/Handler.java: -------------------------------------------------------------------------------- 1 | package design.chainofresponsibility; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public abstract class Handler { 9 | protected Handler successor; 10 | 11 | public Handler(Handler successor) { 12 | this.successor = successor; 13 | } 14 | 15 | protected abstract void handleRequest(Request request); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/design/chainofresponsibility/Request.java: -------------------------------------------------------------------------------- 1 | package design.chainofresponsibility; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class Request { 9 | private RequestType type; 10 | private String name; 11 | 12 | public Request(RequestType type, String name) { 13 | this.type = type; 14 | this.name = name; 15 | } 16 | 17 | public RequestType getType() { 18 | return this.type; 19 | } 20 | 21 | public String getName() { 22 | return this.name; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/design/chainofresponsibility/RequestType.java: -------------------------------------------------------------------------------- 1 | package design.chainofresponsibility; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public enum RequestType { 9 | /** 10 | * 类型1 11 | */ 12 | type1, 13 | /** 14 | * 类型2 15 | */ 16 | type2 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/design/command/Client.java: -------------------------------------------------------------------------------- 1 | package design.command; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class Client { 9 | public static void main(String[] args) { 10 | Invoker invoker = new Invoker(); 11 | Light light = new Light(); 12 | 13 | Command lightOnCommand = new LightOnCommand(light); 14 | Command lightOffCommand = new LightOffCommand(light); 15 | 16 | invoker.setOnCommand(lightOnCommand, 0); 17 | invoker.setOffCommand(lightOffCommand, 0); 18 | 19 | invoker.onButtonWasPushed(0); 20 | invoker.offButtonWasPushed(0); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/design/command/Command.java: -------------------------------------------------------------------------------- 1 | package design.command; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public interface Command { 9 | void execute(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/design/command/Invoker.java: -------------------------------------------------------------------------------- 1 | package design.command; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class Invoker { 9 | private Command[] onCommands; 10 | private Command[] offCommands; 11 | private final int slotNum = 7; 12 | 13 | public Invoker() { 14 | this.onCommands = new Command[slotNum]; 15 | this.offCommands = new Command[slotNum]; 16 | } 17 | 18 | public void setOnCommand(Command command, int slot) { 19 | onCommands[slot] = command; 20 | } 21 | 22 | public void setOffCommand(Command command, int slot) { 23 | offCommands[slot] = command; 24 | } 25 | 26 | public void onButtonWasPushed(int slot) { 27 | onCommands[slot].execute(); 28 | } 29 | 30 | public void offButtonWasPushed(int slot) { 31 | offCommands[slot].execute(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/design/command/Light.java: -------------------------------------------------------------------------------- 1 | package design.command; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class Light { 9 | public void on() { 10 | System.out.println("Light is on!"); 11 | } 12 | 13 | public void off() { 14 | System.out.println("Light is off!"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/design/command/LightOffCommand.java: -------------------------------------------------------------------------------- 1 | package design.command; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class LightOffCommand implements Command { 9 | Light light; 10 | 11 | public LightOffCommand(Light light) { 12 | this.light = light; 13 | } 14 | 15 | @Override 16 | public void execute() { 17 | light.off(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/design/command/LightOnCommand.java: -------------------------------------------------------------------------------- 1 | package design.command; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class LightOnCommand implements Command { 9 | Light light; 10 | 11 | public LightOnCommand(Light light) { 12 | this.light = light; 13 | } 14 | 15 | @Override 16 | public void execute() { 17 | light.on(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/design/prototype/Client.java: -------------------------------------------------------------------------------- 1 | package design.prototype; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class Client { 9 | public static void main(String[] args) { 10 | Prototype prototype = new ConcretePrototype("abc"); 11 | Prototype clone = prototype.myClone(); 12 | System.out.println(clone); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/design/prototype/ConcretePrototype.java: -------------------------------------------------------------------------------- 1 | package design.prototype; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class ConcretePrototype extends Prototype { 9 | 10 | private String field; 11 | 12 | public ConcretePrototype(String f) { 13 | this.field = f; 14 | } 15 | 16 | @Override 17 | Prototype myClone() { 18 | return new ConcretePrototype(field); 19 | } 20 | 21 | @Override 22 | public String toString() { 23 | return field; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/design/prototype/Prototype.java: -------------------------------------------------------------------------------- 1 | package design.prototype; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public abstract class Prototype { 9 | abstract Prototype myClone(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/design/simplefactory/Client.java: -------------------------------------------------------------------------------- 1 | package design.simplefactory; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class Client { 9 | public static void main(String[] args) { 10 | SimpleFactory simpleFactory = new SimpleFactory(); 11 | Product product = simpleFactory.createProduct(1); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/design/simplefactory/ConcreteProduct.java: -------------------------------------------------------------------------------- 1 | package design.simplefactory; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class ConcreteProduct implements Product{ 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/design/simplefactory/ConcreteProduct1.java: -------------------------------------------------------------------------------- 1 | package design.simplefactory; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class ConcreteProduct1 implements Product{ 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/design/simplefactory/ConcreteProduct2.java: -------------------------------------------------------------------------------- 1 | package design.simplefactory; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class ConcreteProduct2 implements Product{ 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/design/simplefactory/Product.java: -------------------------------------------------------------------------------- 1 | package design.simplefactory; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public interface Product { 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/design/simplefactory/SimpleFactory.java: -------------------------------------------------------------------------------- 1 | package design.simplefactory; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 6 | * @date: 2018/07/14 7 | */ 8 | public class SimpleFactory { 9 | public Product createProduct(int type) { 10 | if (1 == type) { 11 | return new ConcreteProduct1(); 12 | } else if (2 == type) { 13 | return new ConcreteProduct2(); 14 | } else { 15 | return new ConcreteProduct(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/design/singleton/Singleton01.java: -------------------------------------------------------------------------------- 1 | package design.singleton; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 懒汉式 - 线程不安全 6 | * @date: 2018/07/13 7 | */ 8 | public class Singleton01 { 9 | 10 | private static Singleton01 uniqueInstance; 11 | 12 | private Singleton01() { 13 | } 14 | 15 | public static Singleton01 getUniqueInstance() { 16 | if (null == uniqueInstance) { 17 | uniqueInstance = new Singleton01(); 18 | } 19 | return uniqueInstance; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/design/singleton/Singleton02.java: -------------------------------------------------------------------------------- 1 | package design.singleton; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 懒汉式 - 线程安全 6 | * @date: 2018/07/13 7 | */ 8 | public class Singleton02 { 9 | private static Singleton02 uniqueInstance; 10 | 11 | private Singleton02() { 12 | } 13 | 14 | public static synchronized Singleton02 getUniqueInstance() { 15 | if (null == uniqueInstance) { 16 | uniqueInstance = new Singleton02(); 17 | } 18 | return uniqueInstance; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/design/singleton/Singleton03.java: -------------------------------------------------------------------------------- 1 | package design.singleton; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 饿汉式 - 线程安全 6 | * @date: 2018/07/13 7 | */ 8 | public class Singleton03 { 9 | private static Singleton03 uniqueInstance = new Singleton03(); 10 | 11 | private Singleton03() { 12 | } 13 | 14 | public static Singleton03 getUniqueInstance() { 15 | return uniqueInstance; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/design/singleton/Singleton04.java: -------------------------------------------------------------------------------- 1 | package design.singleton; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 双重校验锁 - 线程安全 6 | * @date: 2018/07/13 7 | */ 8 | public class Singleton04 { 9 | private volatile static Singleton04 uniqueInstance; 10 | 11 | private Singleton04() { 12 | } 13 | 14 | public static Singleton04 getUniqueInstance() { 15 | if (null == uniqueInstance) { 16 | synchronized (Singleton04.class) { 17 | if (null == uniqueInstance) { 18 | uniqueInstance = new Singleton04(); 19 | } 20 | } 21 | } 22 | return uniqueInstance; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/design/singleton/Singleton05.java: -------------------------------------------------------------------------------- 1 | package design.singleton; 2 | 3 | /** 4 | * @author: mayuan 5 | * @desc: 静态内部类实现 6 | * @date: 2018/07/13 7 | */ 8 | public class Singleton05 { 9 | 10 | private Singleton05() { 11 | } 12 | 13 | private static class SingletonHolder { 14 | private static final Singleton05 INSTANCE = new Singleton05(); 15 | } 16 | 17 | public static Singleton05 getUniqueInstance() { 18 | return SingletonHolder.INSTANCE; 19 | } 20 | 21 | } 22 | --------------------------------------------------------------------------------