├── .classpath ├── .gitignore ├── .idea ├── codeStyles │ └── codeStyleConfig.xml ├── encodings.xml ├── markdown-navigator.xml ├── markdown-navigator │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── uiDesigner.xml └── vcs.xml ├── .project ├── .settings └── org.eclipse.jdt.core.prefs ├── AlgorithmCode.iml ├── README.md ├── bin └── .gitignore └── src ├── ali2019 ├── Main.java ├── Main2.java ├── Main3.java └── MaxWorkinghourGap.java ├── jd └── Solution1.java ├── leetcode ├── all │ ├── solution101_200 │ │ ├── Solution111.java │ │ ├── Solution112.java │ │ ├── Solution125.java │ │ ├── Solution160.java │ │ ├── Solution167.java │ │ └── Solution188.java │ ├── solution1_100 │ │ ├── Solution100.java │ │ ├── Solution13.java │ │ ├── Solution15.java │ │ ├── Solution16.java │ │ ├── Solution18.java │ │ ├── Solution2.java │ │ ├── Solution27.java │ │ ├── Solution28.java │ │ ├── Solution3.java │ │ ├── Solution32.java │ │ ├── Solution35.java │ │ ├── Solution38.java │ │ ├── Solution43.java │ │ ├── Solution53.java │ │ ├── Solution58.java │ │ ├── Solution62.java │ │ ├── Solution63.java │ │ ├── Solution64.java │ │ ├── Solution66.java │ │ ├── Solution67.java │ │ ├── Solution69.java │ │ ├── Solution7.java │ │ ├── Solution8.java │ │ ├── Solution83.java │ │ ├── Solution9.java │ │ └── Solution91.java │ ├── solution201_300 │ │ ├── Solution226.java │ │ └── Solution257.java │ ├── solution301_400 │ │ ├── Solution303.java │ │ ├── Solution304.java │ │ ├── Solution349.java │ │ ├── Solution354.java │ │ └── Solution383.java │ ├── solution401_500 │ │ ├── Solution404.java │ │ ├── Solution434.java │ │ ├── Solution437.java │ │ ├── Solution442.java │ │ ├── Solution443.java │ │ ├── Solution448.java │ │ └── Solution459.java │ ├── solution501_600 │ │ ├── Solution520.java │ │ ├── Solution541.java │ │ ├── Solution543.java │ │ ├── Solution551.java │ │ ├── Solution557.java │ │ ├── Solution559.java │ │ ├── Solution563.java │ │ ├── Solution572.java │ │ ├── Solution589.java │ │ └── Solution590.java │ ├── solution601_700 │ │ ├── Solution606.java │ │ ├── Solution653.java │ │ ├── Solution684.java │ │ ├── Solution687.java │ │ └── Solution698.java │ ├── solution701_800 │ │ ├── Solution746.java │ │ └── Solution779.java │ └── solution801_900 │ │ ├── Solution859.java │ │ └── Solution872.java └── common │ ├── AMGraph.java │ ├── GraphUtils.java │ ├── LinkedUtils.java │ ├── ListNode.java │ ├── OtherUtils.java │ ├── TreeNode.java │ └── TreeUtils.java ├── masai └── GuShen.java ├── offer ├── FindFirstCommonNodeSolution.java ├── FindKthToTailSolution.java ├── HasSubtreeSolution.java ├── MergeSolution.java ├── MirrorSolution.java ├── ReOrderArraySolution.java ├── RectCoverSolution.java └── ReverseListSolution.java ├── other ├── Baicizhan1.java ├── Baicizhan2.java ├── Baidu1.java ├── Baidu2.java ├── Baidu3.java ├── GraphTest.java ├── Mogujie1.java ├── Mogujie2.java ├── ShenCe.java ├── ShenCe1.java ├── ShenCe2.java ├── ShenCeInterview1.java ├── ShenCeInterview2.java ├── Shunwang.java ├── Wanmei1.java ├── Xunlei1.java ├── Xunlei2.java ├── XunleiTest1.java ├── XunleiTest2.java └── ZhaoShang2018_1.java ├── pattern ├── chain │ ├── AbstractLogger.java │ ├── Client.java │ ├── ConsoleLogger.java │ ├── ErrorLogger.java │ └── FileLogger.java ├── command │ ├── BuyStock.java │ ├── Client.java │ ├── Invoker.java │ ├── Order.java │ ├── SellStock.java │ └── Stock.java ├── iterator │ ├── Client.java │ ├── Container.java │ ├── Iterator.java │ └── NameRepository.java ├── mediator │ ├── ChatRoom.java │ ├── Client.java │ └── User.java ├── memento │ ├── CareTaker.java │ ├── Client.java │ ├── Memento.java │ └── Originator.java └── observer │ ├── Client.java │ ├── Observer.java │ ├── Observer1.java │ ├── Observer2.java │ └── Subject.java ├── sort ├── ArrayUtils.java ├── Buddle.java ├── Buddle2.java ├── DownToUpMergeSort.java ├── Heap.java ├── HeapSort.java ├── Insertion.java ├── MergeSort.java ├── QuickSort.java ├── Selection.java ├── Shell.java ├── Sort.java ├── ThreeWayQuickSort.java └── UpToDownMergeSort.java ├── sort2 ├── BuddleSort.java ├── Insertion.java ├── QuickSort.java └── Selection.java ├── tencent ├── Main1.java ├── Main2.java ├── Main3.java ├── Main4.java └── Main6.java └── utils └── ArrayUtils.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | AlgorithmCode 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /AlgorithmCode.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /bin/.gitignore: -------------------------------------------------------------------------------- 1 | /leetcode/ 2 | -------------------------------------------------------------------------------- /src/ali2019/Main.java: -------------------------------------------------------------------------------- 1 | package ali2019; 2 | 3 | 4 | import java.util.Scanner; 5 | 6 | /** 7 | * 阿里客户端模拟笔试 8 | * 9 | * 内存回收:相邻页面不能同时回收,求最大回收的内存 10 | * 输入: 11 | * 3 12 | * 1 2 3 13 | * 14 | * 输出:4 15 | * 回收1和3 16 | * 17 | * @author 刘壮飞 18 | * https://github.com/zfman. 19 | * https://blog.csdn.net/lzhuangfei. 20 | */ 21 | public class Main { 22 | public static int done(int[] m){ 23 | int[] dp=new int[m.length]; 24 | 25 | if(m.length==0) return 0; 26 | if(m.length==1) return m[0]; 27 | if(m.length==2) return Math.max(m[0],m[1]); 28 | 29 | dp[0]=m[0]; 30 | dp[1]=Math.max(m[0],m[1]); 31 | 32 | for(int i=2;idp[i-1]) dp[i]=m[i]+dp[i-2]; 34 | else{ 35 | dp[i]=dp[i-1]; 36 | } 37 | } 38 | return dp[m.length-1]; 39 | } 40 | public static void main(String[] args){ 41 | Scanner scanner=new Scanner(System.in); 42 | int n=scanner.nextInt(); 43 | int[] m=new int[n]; 44 | for(int i=0;in) { 43 | System.out.println("不存在"); 44 | }else{ 45 | done(m,n,m,n,tag,0,result,0); 46 | String s=""; 47 | for(int i=0;i=n) return; 68 | if(tX>=tag.length) return; 69 | if(nowMmax) max=tmp; 31 | } 32 | return max; 33 | } 34 | 35 | public static void main(String[] args){ 36 | int[] a={ 37 | 1,3,15,10,9 38 | }; 39 | //output:6 40 | int r=maxWorkinghourGap(a); 41 | System.out.println(r); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/jd/Solution1.java: -------------------------------------------------------------------------------- 1 | package jd; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * 集合(京东2017秋招真题) 7 | * 8 | * 给你两个集合,要求 {A} + {B}。 9 | * 10 | * 注:同一个集合中不会有两个相同的元素。 11 | * 12 | * 输入 13 | * 多组(不超过 5 组)数据。 14 | * 每组输入数据分为三行,第一行有两个数字 n,m($0<n,m\leq10000$),分别表示集合 A 和集合 B 的元素个数。后两行分别表示集合 A 和集合 B。每个元素为不超出 int 范围的整数,每个元素之间有一个空格隔开。 15 | * 16 | * 17 | * 样例输入 18 | * 1 2 19 | * 1 20 | * 2 3 21 | * 1 2 22 | * 1 23 | * 1 2 24 | * 25 | * 26 | * 输出 27 | * 针对每组数据输出一行数据,表示合并后的集合,要求从小到大输出,每个元素之间有一个空格隔开。 28 | * 29 | * 样例输出 30 | * 1 2 3 31 | * 1 2 32 | * 33 | * 时间限制 34 | * C/C++语言:1000MS其它语言:3000MS 35 | * 内存限制 36 | * C/C++语言:65536KB其它语言:589824KB 37 | * 38 | * @author 刘壮飞 39 | * https://github.com/zfman. 40 | * https://blog.csdn.net/lzhuangfei. 41 | */ 42 | public class Solution1 { 43 | public static void main(String[] args){ 44 | Scanner scanner=new Scanner(System.in); 45 | while (scanner.hasNextInt()){ 46 | int aN=scanner.nextInt(); 47 | int bN=scanner.nextInt(); 48 | int[] a=new int[aN]; 49 | int[] b=new int[bN]; 50 | int[] c=new int[aN+bN]; 51 | int i=0,j=0,k=0; 52 | 53 | //输入 54 | for(int m=0;m4->11->2。 23 | * 24 | * @author 刘壮飞 25 | * https://github.com/zfman. 26 | * https://blog.csdn.net/lzhuangfei. 27 | */ 28 | public class Solution112 { 29 | public boolean hasPathSum(TreeNode root, int sum) { 30 | if (root == null) return false; 31 | return adjust(root, 0, sum); 32 | } 33 | 34 | public boolean adjust(TreeNode root, int s, int target) { 35 | if (root != null) { 36 | if (root.left == null && root.right == null) { 37 | s += root.val; 38 | if (target == s) { 39 | return true; 40 | } 41 | } 42 | boolean b1 = adjust(root.left, root.val + s, target); 43 | boolean b2 = adjust(root.right, root.val + s, target); 44 | if (b1 || b2) return true; 45 | } 46 | 47 | return false; 48 | } 49 | 50 | public static void main(String[] args) { 51 | String s = "5,4,11,7,#,#,2,#,#,#,8,13,#,#,4,#,1,#,#"; 52 | int sum = 22; 53 | TreeNode root = TreeUtils.stringToTreeWith(s, ","); 54 | boolean r = new Solution112().hasPathSum(root, sum); 55 | System.out.println(r); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/leetcode/all/solution101_200/Solution125.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution101_200; 2 | 3 | /** 4 | * 125. 验证回文串 5 | * 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。 6 | * 7 | * 说明:本题中,我们将空字符串定义为有效的回文串。 8 | * 9 | * 示例 1: 10 | * 输入: "A man, a plan, a canal: Panama" 11 | * 输出: true 12 | * 13 | * 示例 2: 14 | * 输入: "race a car" 15 | * 输出: false 16 | * 17 | * @author 刘壮飞 18 | * https://github.com/zfman. 19 | * https://blog.csdn.net/lzhuangfei. 20 | */ 21 | public class Solution125 { 22 | 23 | /** 24 | * 从前往后,从后往前逐位比较 25 | * 注意:要过滤掉非字符、非数字的符号 26 | * @param s 27 | * @return 28 | */ 29 | public boolean isPalindrome(String s) { 30 | int i=0; 31 | int j=s.length()-1; 32 | while (i <= j) { 33 | while(i=0&&!isCharAndNumber(s.charAt(j))) j--; 35 | if(i>s.length()||j<0) break; 36 | if(!isSame(s.charAt(i),s.charAt(j))) return false; 37 | i++; 38 | j--; 39 | } 40 | return true; 41 | } 42 | 43 | /** 44 | * 判断是否相等,忽略大小写 45 | * @param ch1 46 | * @param ch2 47 | * @return 48 | */ 49 | public boolean isSame(char ch1,char ch2){ 50 | return (ch1+"").toLowerCase().equals((ch2+"").toLowerCase()); 51 | } 52 | 53 | /** 54 | * 判断是否为合法字符 55 | * @param ch 56 | * @return 57 | */ 58 | public boolean isCharAndNumber(char ch){ 59 | if(ch>='A'&&ch<='Z') return true; 60 | if(ch>='a'&&ch<='z') return true; 61 | if(ch>='0'&&ch<='9') return true; 62 | return false; 63 | } 64 | 65 | public static void main(String[] args) { 66 | String s = "0P"; 67 | boolean r = new Solution125().isPalindrome(s); 68 | System.out.println(r);//false 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/leetcode/all/solution101_200/Solution160.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution101_200; 2 | 3 | import leetcode.common.LinkedUtils; 4 | import leetcode.common.ListNode; 5 | 6 | /** 7 | * 160. 相交链表 8 | * 编写一个程序,找到两个单链表相交的起始节点。 9 | * 10 | * 11 | * 12 | * 例如,下面的两个链表: 13 | * 14 | * A: a1 → a2 15 | * ↘ 16 | * c1 → c2 → c3 17 | * ↗ 18 | * B: b1 → b2 → b3 19 | * 在节点 c1 开始相交。 20 | * 21 | * 22 | * 23 | * 注意: 24 | * 25 | * 如果两个链表没有交点,返回 null. 26 | * 在返回结果后,两个链表仍须保持原有的结构。 27 | * 可假定整个链表结构中没有循环。 28 | * 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。 29 | * 30 | * 31 | * 致谢: 32 | * 特别感谢 @stellari 添加此问题并创建所有测试用例。 33 | * 34 | * @author 刘壮飞 35 | * https://github.com/zfman. 36 | * https://blog.csdn.net/lzhuangfei. 37 | */ 38 | public class Solution160 { 39 | 40 | /** 41 | * 求出两个链表的长度m,n,长链表的指针先走|n-m|,然后再同步走 42 | * 两个链表相交,那么相交部分的长度是相同的 43 | * @param headA 44 | * @param headB 45 | * @return 46 | */ 47 | public ListNode getIntersectionNode(ListNode headA, ListNode headB) { 48 | if(headA==null||headB==null) return null; 49 | int lenA=length(headA); 50 | int lenB=length(headB); 51 | ListNode nodeA=headA; 52 | ListNode nodeB=headB; 53 | int k=0; 54 | 55 | if(lenA>lenB){ 56 | while(k7->8 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/leetcode/all/solution101_200/Solution167.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution101_200; 2 | 3 | /** 4 | * 167. 两数之和 II - 输入有序数组 5 | * 给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。 6 | * 7 | * 函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。 8 | * 9 | * 说明: 10 | * 11 | * 返回的下标值(index1 和 index2)不是从零开始的。 12 | * 你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。 13 | * 14 | * 示例: 15 | * 输入: numbers = [2, 7, 11, 15], target = 9 16 | * 输出: [1,2] 17 | * 解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。 18 | * 19 | * @author 刘壮飞 20 | * https://github.com/zfman. 21 | * https://blog.csdn.net/lzhuangfei. 22 | */ 23 | public class Solution167 { 24 | 25 | /** 26 | * 使用了一个比较笨的方法: 27 | * 从第1个数开始,分别与之后的数字求和 28 | * 29 | * 注意:这个方法如果不优化的话是过不了测试集的,有个测试集非常的长 30 | * 优化:去掉无用的比较,如果发现sum>target,那么本轮就没有继续比较的必要了 31 | * 32 | * @param numbers 33 | * @param target 34 | * @return 35 | */ 36 | public int[] twoSum(int[] numbers, int target) { 37 | int[] r = new int[2]; 38 | if (numbers == null || numbers.length == 0) return r; 39 | 40 | for (int i = 0; i < numbers.length - 1; i++) { 41 | for (int j = i + 1; j < numbers.length; j++) { 42 | int sum = numbers[i] + numbers[j]; 43 | if(sum>target) break; 44 | if (sum == target) { 45 | r[0] = i + 1; 46 | r[1] = j + 1; 47 | return r; 48 | } 49 | } 50 | } 51 | return r; 52 | } 53 | 54 | public static void main(String[] args) { 55 | int[] numbers = { 56 | 3,24,50,79,88,150,345 57 | }; 58 | int target = 200; 59 | int[] r = new Solution167().twoSum(numbers, target); 60 | for(int i=0;i> generate(int numRows) { 42 | int i=3; 43 | List> r=new ArrayList<>(); 44 | if (numRows<=0) return r; 45 | 46 | List list1=new ArrayList<>(); 47 | list1.add(1); 48 | r.add(list1); 49 | if(numRows==1) return r; 50 | 51 | List list2=new ArrayList<>(); 52 | list2.add(1); 53 | list2.add(1); 54 | r.add(list2); 55 | if(numRows==2) return r; 56 | 57 | List pre=list2; 58 | 59 | while (i<=numRows){ 60 | List list=new ArrayList<>(); 61 | r.add(list); 62 | list.add(1); 63 | int t=0; 64 | while(t> r = new Solution188().generate(numRows); 78 | System.out.println(r); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution100.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | import leetcode.common.TreeNode; 4 | import leetcode.common.TreeUtils; 5 | 6 | /** 7 | * 100. 相同的树 8 | * 给定两个二叉树,编写一个函数来检验它们是否相同。 9 | * 10 | * 如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。 11 | * 12 | * 示例 1: 13 | * 14 | * 输入: 1 1 15 | * / \ / \ 16 | * 2 3 2 3 17 | * 18 | * [1,2,3], [1,2,3] 19 | * 20 | * 输出: true 21 | * 22 | * 示例 2: 23 | * 24 | * 输入: 1 1 25 | * / \ 26 | * 2 2 27 | * 28 | * [1,2], [1,null,2] 29 | * 30 | * 输出: false 31 | * 32 | * 示例 3: 33 | * 34 | * 输入: 1 1 35 | * / \ / \ 36 | * 2 1 1 2 37 | * 38 | * [1,2,1], [1,1,2] 39 | * 40 | * 输出: false 41 | * 42 | * @author 刘壮飞 43 | * https://github.com/zfman. 44 | * https://blog.csdn.net/lzhuangfei. 45 | */ 46 | public class Solution100 { 47 | public boolean isSameTree(TreeNode p, TreeNode q) { 48 | //p,q不一致 49 | if(p==null&&q!=null) return false; 50 | if(p!=null&&q==null) return false; 51 | 52 | //判断左子树、右子树 53 | if(p!=null&&q!=null){ 54 | if(!isSameTree(p.left,q.left)||!isSameTree(p.right,q.right)) return false; 55 | if(p.val!=q.val) return false; 56 | } 57 | return true; 58 | } 59 | 60 | public static void main(String[] args) { 61 | String pstr="12##4##"; 62 | String qstr="12##3##"; 63 | TreeNode p=TreeUtils.stringToTree(pstr); 64 | TreeNode q=TreeUtils.stringToTree(qstr); 65 | boolean b = new Solution100().isSameTree(p, q); 66 | System.out.println(b); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution13.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 罗马数字转整数. 8 | * 罗马数字包含以下七种字符:I, V, X, L,C,D 和 M。 9 | * 10 | * 字符 数值 11 | * I 1 12 | * V 5 13 | * X 10 14 | * L 50 15 | * C 100 16 | * D 500 17 | * M 1000 18 | * 例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。 19 | * 20 | * 通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况: 21 | * 22 | * I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。 23 | * X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 24 | * C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。 25 | * 给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。 26 | * 27 | * 示例 1: 28 | * 输入: "III" 29 | * 输出: 3 30 | * 31 | * 示例 2: 32 | * 输入: "IV" 33 | * 输出: 4 34 | * 35 | * 示例 3: 36 | * 输入: "IX" 37 | * 输出: 9 38 | * 39 | * 示例 4: 40 | * 输入: "LVIII" 41 | * 输出: 58 42 | * 解释: C = 100, L = 50, XXX = 30, III = 3. 43 | * 44 | * 示例 5: 45 | * 输入: "MCMXCIV" 46 | * 输出: 1994 47 | * 解释: M = 1000, CM = 900, XC = 90, IV = 4. 48 | * 49 | * @author 刘壮飞 50 | * https://github.com/zfman. 51 | * https://blog.csdn.net/lzhuangfei. 52 | */ 53 | public class Solution13 { 54 | 55 | /** 56 | * 遍历字符串,如果该字符的值小于等于上一个字符的值,直接 57 | * 加上当前字符表示的值即可;反之,将上一个字符表示的值减去, 58 | * 加上当前字符表示的值与上一个字符表示的值的差 59 | * 60 | * @param s 61 | * @return 62 | */ 63 | public int romanToInt(String s) { 64 | Map map=initMap(); 65 | if(s==null||s.length()==0) return 0; 66 | 67 | int value=0; 68 | for(int i=0;i initMap() { 89 | Map map=new HashMap<>(); 90 | map.put('I',1); 91 | map.put('V',5); 92 | map.put('X',10); 93 | map.put('L',50); 94 | map.put('C',100); 95 | map.put('D',500); 96 | map.put('M',1000); 97 | return map; 98 | } 99 | 100 | public static void main(String[] args){ 101 | String s="MCMXCIV"; 102 | int r=new Solution13().romanToInt(s); 103 | System.out.println(r);//1994 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution15.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | /** 8 | * 15. 三数之和 9 | * 10 | * 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。 11 | * 12 | * 注意:答案中不可以包含重复的三元组。 13 | * 14 | * 例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], 15 | * 16 | * 满足要求的三元组集合为: 17 | * [ 18 | * [-1, 0, 1], 19 | * [-1, -1, 2] 20 | * ] 21 | * 22 | * @author 刘壮飞 23 | * https://github.com/zfman. 24 | * https://blog.csdn.net/lzhuangfei. 25 | */ 26 | public class Solution15 { 27 | 28 | /** 29 | * 双指针:先排序,然后指定第一个数,求解后面两数之和等于该数的相反数 30 | * i指向第一个数之后的一个数,j指向末尾 31 | * 如果此时三数之和等于0,那么将三个数记录 32 | * 如果三数之和>0,j向前移动 33 | * 如果三数之和<0,i向后移动 34 | * 35 | * 注意去重 36 | * 37 | * @param nums 38 | * @return 39 | */ 40 | public List> threeSum(int[] nums) { 41 | List> r=new ArrayList<>(); 42 | Arrays.sort(nums); 43 | for(int i=0;i0) continue; 47 | //以下一行用来去重 48 | if(i>0&&nums[i]==nums[i-1]) continue; 49 | 50 | while(k0){ 60 | v--; 61 | }else{ 62 | k++; 63 | } 64 | } 65 | } 66 | return r; 67 | } 68 | 69 | public static void main(String[] args){ 70 | int[] nums={ 71 | -4,-2,1,-5,-4,-4,4,-2,0,4,0,-2,3,1,-5,0 72 | }; 73 | List> r=new Solution15().threeSum(nums); 74 | for(List l:r){ 75 | for(Integer i:l){ 76 | System.out.print(i+" "); 77 | } 78 | System.out.println(); 79 | } 80 | } 81 | } 82 | 83 | 84 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution16.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * 7 | * 16. 最接近的三数之和 8 | * 9 | * 给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。 10 | * 11 | * 例如,给定数组 nums = [-1,2,1,-4], 和 target = 1. 12 | * 13 | * 与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2). 14 | * 15 | * @author 刘壮飞 16 | * https://github.com/zfman. 17 | * https://blog.csdn.net/lzhuangfei. 18 | */ 19 | public class Solution16 { 20 | 21 | /** 22 | * 双指针,类似 Solution15 23 | * 不需要去重 24 | * 25 | * @param nums 26 | * @param target 27 | * @return 28 | */ 29 | public int threeSumClosest(int[] nums, int target) { 30 | Arrays.sort(nums); 31 | int minDistance=Integer.MAX_VALUE;//最小距离 32 | int minSum=0;//最小和 33 | for(int i=0;itarget){ 40 | v--; 41 | }else{ 42 | k++; 43 | } 44 | //保存最小和、最小距离 45 | if(Math.abs(sum-target)> fourSum(int[] nums, int target) { 33 | List> res = new ArrayList<>(); 34 | Arrays.sort(nums); 35 | for (int i = 0; i < nums.length ; i++) { 36 | if(i>0&&nums[i]==nums[i-1]) continue;//对第1个数去重 37 | for (int j = i + 1; j < nums.length ; j++) { 38 | if(j>i+1&&nums[j]==nums[j-1]) continue;//对第2个数去重 39 | int k = j + 1;//前指针 40 | int v = nums.length - 1;//后指针 41 | while (k < v) { 42 | int sum = nums[i] + nums[j] + nums[k] + nums[v]; 43 | if (sum == target) { 44 | res.add(Arrays.asList(nums[i], nums[j], nums[k], nums[v])); 45 | //去重 46 | while (k < v && nums[k] == nums[k + 1]) k++; 47 | while (k < v && nums[v] == nums[v - 1]) v--; 48 | k++; 49 | v--; 50 | } else if (sum > target) { 51 | v--; 52 | } else { 53 | k++; 54 | } 55 | } 56 | } 57 | } 58 | return res; 59 | } 60 | 61 | public static void main(String[] args) { 62 | int[] nums = { 63 | -1,2,2,-5,0,-1,4 64 | }; 65 | int target = 3; 66 | List> r = new Solution18().fourSum(nums, target); 67 | for (List l : r) { 68 | for (Integer i : l) { 69 | System.out.print(i + " "); 70 | } 71 | System.out.println(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution2.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | import leetcode.common.LinkedUtils; 4 | import leetcode.common.ListNode; 5 | 6 | /** 7 | * 两数相加. 8 | * https://leetcode-cn.com/problems/add-two-numbers/description/ 9 | * 10 | * 给定两个非空链表来表示两个非负整数。位数按照逆序方式存储,它们的每个节点只存储单个数字。将两数相加返回一个新的链表。 11 | * 你可以假设除了数字 0 之外,这两个数字都不会以零开头。 12 | * 13 | * 示例: 14 | * 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 15 | * 输出:7 -> 0 -> 8 16 | * 原因:342 + 465 = 807 17 | * 18 | * @author 刘壮飞 19 | * https://github.com/zfman. 20 | * https://blog.csdn.net/lzhuangfei. 21 | */ 22 | public class Solution2 { 23 | public ListNode addTwoNumbers(ListNode l1, ListNode l2) { 24 | ListNode node = new ListNode(-1);//头节点 25 | ListNode p = node;//指示执行到的位置 26 | int plusOne = 0;//是否进位 27 | 28 | while (l1 != null || l2 != null) { 29 | //计算对应位和 30 | int v1 = (l1 != null) ? l1.val : 0; 31 | int v2 = (l2 != null) ? l2.val : 0; 32 | int r = v1 + v2 + plusOne; 33 | 34 | //之和大于9,减去十即为该值,并进位 35 | if (r > 9) { 36 | plusOne = 1; 37 | ListNode tmp = new ListNode(r - 10); 38 | p.next = tmp; 39 | p = tmp; 40 | } else { 41 | plusOne = 0; 42 | ListNode tmp = new ListNode(r); 43 | p.next = tmp; 44 | p = tmp; 45 | } 46 | if (l1 != null) l1 = l1.next; 47 | if (l2 != null) l2 = l2.next; 48 | } 49 | 50 | //如果最后一位仍然需要进位,创建节点 51 | if (plusOne == 1) { 52 | p.next = new ListNode(1); 53 | } 54 | return node.next; 55 | } 56 | 57 | public static void main(String[] args) { 58 | //你的算法必须是高效的,否则下面这个测试集是过不去的 59 | int[] list1 = { 60 | 2,4,3,2,4,3,2,4,3,2, 61 | 4,3,2,4,3,2,4,3,2,4, 62 | 3,2,4,3,2,4,3,2,4,3, 63 | 2,4,3,2,4,3,2,4,3,2, 64 | 4,3,2,4,3,2,4,3,2,4, 65 | 3,2,4,3,2,4,3,2,4,3,9 }; 66 | int[] list2 = { 67 | 5,6,4,2,4,3,2,4,3,2, 68 | 4,3,2,4,3,2,4,3,2,4, 69 | 3,2,4,3,2,4,3,2,4,3, 70 | 2,4,3,2,4,3,2,4,3,2, 71 | 4,3,2,4,3,2,4,3,2,4, 72 | 3,2,4,3,2,4,3,9,9,9,9 }; 73 | 74 | ListNode l1 = LinkedUtils.arrayToLinkedList(list1); 75 | ListNode l2 = LinkedUtils.arrayToLinkedList(list2); 76 | 77 | ListNode root = new Solution2().addTwoNumbers(l1, l2); 78 | LinkedUtils.print(root); 79 | } 80 | } -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution27.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | /** 4 | * 27.移除元素. 5 | * 给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。 6 | * 7 | * 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 8 | * 9 | * 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。 10 | * 11 | * 示例 1: 12 | * 给定 nums = [3,2,2,3], val = 3, 13 | * 14 | * 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。 15 | * 16 | * 你不需要考虑数组中超出新长度后面的元素。 17 | * 18 | * 示例 2: 19 | * 给定 nums = [0,1,2,2,3,0,4,2], val = 2, 20 | * 21 | * 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。 22 | * 23 | * 注意这五个元素可为任意顺序。 24 | * 25 | * 你不需要考虑数组中超出新长度后面的元素。 26 | * 27 | * 说明: 28 | * 29 | * 为什么返回数值是整数,但输出的答案是数组呢? 30 | * 31 | * 请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。 32 | * 33 | * 你可以想象内部操作如下: 34 | * 35 | * // nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 36 | * int len = removeElement(nums, val); 37 | * 38 | * // 在函数里修改输入数组对于调用者是可见的。 39 | * // 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。 40 | * for (int i = 0; i < len; i++) { 41 | * print(nums[i]); 42 | * } 43 | * 44 | * @author 刘壮飞 45 | * https://github.com/zfman. 46 | * https://blog.csdn.net/lzhuangfei. 47 | */ 48 | public class Solution27 { 49 | 50 | /** 51 | * 从前往后找等于val的位置,从后往前找不等于val的位置 52 | * 交换两者,继续寻找,当i>=j时停止. 53 | * 注意边界问题. 54 | * 55 | * @param nums 数组 56 | * @param val 待删除的值 57 | * @return 58 | */ 59 | public int removeElement(int[] nums, int val) { 60 | if (nums == null || nums.length == 0) return 0; 61 | int i = 0, j = nums.length - 1; 62 | 63 | while (i < j) { 64 | for (; i < nums.length && nums[i] != val; i++) ; 65 | for (; j >= 0 && nums[j] == val; j--) ; 66 | if (i >= nums.length || j < 0 || i >= j) break; 67 | 68 | int tmp = nums[i]; 69 | nums[i] = nums[j]; 70 | nums[j] = tmp; 71 | 72 | i++; 73 | j--; 74 | } 75 | 76 | for (int m = 0; m < nums.length; m++) { 77 | if (nums[m] == val) return m; 78 | } 79 | return nums.length; 80 | } 81 | 82 | public static void main(String[] args) { 83 | int[] nums = { 84 | 4, 5 85 | }; 86 | int val = 5; 87 | int r = new Solution27().removeElement(nums, val); 88 | System.out.println(r); 89 | for (int i = 0; i < nums.length; i++) { 90 | System.out.print(nums[i] + " "); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution28.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | /** 4 | * 28. 实现strStr(). 5 | * 实现 strStr() 函数。 6 | * 7 | * 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。 8 | * 9 | * 示例 1: 10 | * 输入: haystack = "hello", needle = "ll" 11 | * 输出: 2 12 | * 13 | * 示例 2: 14 | * 输入: haystack = "aaaaa", needle = "bba" 15 | * 输出: -1 16 | * 17 | * 说明: 18 | * 19 | * 当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。 20 | * 21 | * 对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。 22 | * 23 | * @author 刘壮飞 24 | * https://github.com/zfman. 25 | * https://blog.csdn.net/lzhuangfei. 26 | */ 27 | public class Solution28 { 28 | 29 | /** 30 | * 暴力法 31 | * @param haystack 32 | * @param needle 33 | * @return 34 | */ 35 | public int strStr(String haystack, String needle) { 36 | int len1=haystack.length(); 37 | int len2=needle.length(); 38 | if(len2==0) return 0; 39 | else if(len1==0) return -1; 40 | 41 | int i=0,j=0; 42 | while(i=len2) return i-len2; 53 | return -1; 54 | } 55 | 56 | public static void main(String[] args) { 57 | String haystack=""; 58 | String needle="ll"; 59 | int r=new Solution28().strStr(haystack,needle); 60 | System.out.println(r); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution3.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | /** 4 | * 无重复字符的最长子串. 5 | * 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public class Solution3 { 11 | public int lengthOfLongestSubstring(String s) { 12 | if(s==null) return 0; 13 | if(s.length()<2) return s.length(); 14 | 15 | 16 | return 0; 17 | } 18 | 19 | public static void main(String[] args){ 20 | String s=""; 21 | int r=new Solution3().lengthOfLongestSubstring(s); 22 | System.out.println(r); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution32.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * 32. 最长有效括号 7 | * 8 | * 给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。 9 | * 10 | * 示例 1: 11 | * 12 | * 输入: "(()" 13 | * 输出: 2 14 | * 解释: 最长有效括号子串为 "()" 15 | * 示例 2: 16 | * 17 | * 输入: ")()())" 18 | * 输出: 4 19 | * 解释: 最长有效括号子串为 "()()" 20 | * 21 | * @author 刘壮飞 22 | * https://github.com/zfman. 23 | * https://blog.csdn.net/lzhuangfei. 24 | */ 25 | public class Solution32 { 26 | 27 | /** 28 | * 动态规划解法 29 | * @param s 30 | * @return 31 | */ 32 | public int longestValidParentheses2(String s) { 33 | int[] dp=new int[s.length()]; 34 | int max=0; 35 | int pre=0; 36 | if(s==null||s.trim().equals("")) return 0; 37 | 38 | for(int i=1;i=0&&s.charAt(pre)=='('){ 42 | dp[i]=dp[i-1]+2+(pre>0?dp[pre-1]:0); 43 | if(dp[i]>max) max=dp[i]; 44 | } 45 | } 46 | } 47 | 48 | // for(int i=0;i stack=new Stack<>(); 69 | int c=0;//当前未被匹配的左括号的数量 70 | for(int i=0;ihigh) return low; 46 | if(value==nums[middle]) return middle; 47 | else if(value 7 | * 示例 1: 8 | * 输入: num1 = "2", num2 = "3" 9 | * 输出: "6" 10 | *

11 | * 示例 2: 12 | * 输入: num1 = "123", num2 = "456" 13 | * 输出: "56088" 14 | *

15 | * 说明: 16 | * num1 和 num2 的长度小于110。 17 | * num1 和 num2 只包含数字 0-9。 18 | * num1 和 num2 均不以零开头,除非是数字 0 本身。 19 | * 不能使用任何标准库的大数类型(比如 BigInteger)或直接将输入转换为整数来处理。 20 | * 21 | * @author 刘壮飞 22 | * https://github.com/zfman. 23 | * https://blog.csdn.net/lzhuangfei. 24 | */ 25 | public class Solution43 { 26 | public String multiply(String num1, String num2) { 27 | return null; 28 | } 29 | 30 | public static void main(String[] args) { 31 | String num1="123"; 32 | String num2="456"; 33 | String r=new Solution43().multiply(num1,num2); 34 | System.out.println(r); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution53.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | /** 4 | * 53.最大子序和. 5 | * 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 6 | * 7 | * 示例: 8 | * 输入: [-2,1,-3,4,-1,2,1,-5,4], 9 | * 输出: 6 10 | * 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 11 | * 12 | * 进阶: 13 | * 14 | * 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。 15 | * 16 | * @author 刘壮飞 17 | * https://github.com/zfman. 18 | * https://blog.csdn.net/lzhuangfei. 19 | */ 20 | public class Solution53 { 21 | public int maxSubArray(int[] nums) { 22 | if (nums.length ==0) return 0; 23 | int sum = nums[0]; 24 | int tmp=nums[0]; 25 | for(int i=1;i0){ 27 | tmp+=nums[i]; 28 | if(tmp>sum) sum=tmp; 29 | }else{ 30 | tmp=nums[i]; 31 | if(tmp>sum) sum=tmp; 32 | } 33 | } 34 | return sum; 35 | } 36 | 37 | public static void main(String[] args) { 38 | int[] nums = { 39 | -2, 1, -3, 4, -1, 2, 1, -5, 4 40 | }; 41 | int r = new Solution53().maxSubArray(nums); 42 | System.out.println(r); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution58.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | /** 4 | * 58. 最后一个单词的长度. 5 | * 给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度。 6 | * 7 | * 如果不存在最后一个单词,请返回 0 。 8 | * 9 | * 说明:一个单词是指由字母组成,但不包含任何空格的字符串。 10 | * 11 | * 示例: 12 | * 输入: "Hello World" 13 | * 输出: 5 14 | * 15 | * @author 刘壮飞 16 | * https://github.com/zfman. 17 | * https://blog.csdn.net/lzhuangfei. 18 | */ 19 | public class Solution58 { 20 | 21 | /** 22 | * 很简单,切分为数组,取最后一个元素即可 23 | * @param s 24 | * @return 25 | */ 26 | public int lengthOfLastWord(String s) { 27 | if(s==null||s.length()==0) return 0; 28 | String[] a=s.trim().split(" +"); 29 | if(a==null||a.length==0) return 0; 30 | return a[a.length-1].length(); 31 | } 32 | 33 | public static void main(String[] args) { 34 | String s = "Hello World"; 35 | int r = new Solution58().lengthOfLastWord(s); 36 | System.out.println(r); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution62.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | /** 4 | * 62. 不同路径 5 | * 6 | * 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。 7 | * 8 | * 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。 9 | * 10 | * 问总共有多少条不同的路径? 11 | * 12 | * 13 | * 例如,上图是一个7 x 3 的网格。有多少可能的路径? 14 | * 15 | * 说明:m 和 n 的值均不超过 100。 16 | * 17 | * 示例 1: 18 | * 19 | * 输入: m = 3, n = 2 20 | * 输出: 3 21 | * 解释: 22 | * 从左上角开始,总共有 3 条路径可以到达右下角。 23 | * 1. 向右 -> 向右 -> 向下 24 | * 2. 向右 -> 向下 -> 向右 25 | * 3. 向下 -> 向右 -> 向右 26 | * 27 | * 示例 2: 28 | * 29 | * 输入: m = 7, n = 3 30 | * 输出: 28 31 | * 32 | * @author 刘壮飞 33 | * https://github.com/zfman. 34 | * https://blog.csdn.net/lzhuangfei. 35 | */ 36 | public class Solution62 { 37 | 38 | /** 39 | * 使用动态规划求解. 40 | * 41 | * 第一行、第一列设为1,从第二行第二列开始, 42 | * 该位置的路径数等于左侧的路径数+上侧的路径数, 43 | * 机器人到达右下角的路径未arr[m-1][n-1] 44 | * 45 | * @param m 46 | * @param n 47 | * @return 48 | */ 49 | public int uniquePaths(int m, int n) { 50 | int[][] arr=new int[m][n]; 51 | for(int i=0;i 向右 -> 向下 -> 向下 31 | * 2. 向下 -> 向下 -> 向右 -> 向右 32 | * 33 | * @author 刘壮飞 34 | * https://github.com/zfman. 35 | * https://blog.csdn.net/lzhuangfei. 36 | */ 37 | public class Solution63 { 38 | /** 39 | * 本题目增加了障碍物,所以在初始化时需要注意 40 | * 41 | * 初始化时将第一行、第一列障碍物位置以及其之后的位置初始化为0,其他位置为1 42 | * 计算时,如果该位置为障碍物,置0,否则置为上策和左侧的和 43 | * 44 | * @param obstacleGrid 45 | * @return 46 | */ 47 | public int uniquePathsWithObstacles(int[][] obstacleGrid) { 48 | if(obstacleGrid.length<1) return 0; 49 | int m=obstacleGrid.length; 50 | int n=obstacleGrid[0].length; 51 | int[][] count=new int[m][n]; 52 | 53 | //初始化 54 | boolean cannotContinue1=false; 55 | boolean cannotContinue2=false; 56 | for(int i=0;i=0;i--){ 38 | if(digits[i]<9){ 39 | digits[i]+=1; 40 | break; 41 | }else { 42 | digits[i]=0; 43 | } 44 | } 45 | if(i<0){ 46 | int[] r=new int[digits.length+1]; 47 | r[0]=1; 48 | for(int m=1;m= 0; i--) { 47 | char ch1 = a.charAt(i); 48 | char ch2 = b.charAt(i); 49 | int k=ch1-'0'+(ch2-'0'); 50 | if(plusOne) k=k+1; 51 | if (k>1) { 52 | k=k-2; 53 | r = k+ r; 54 | plusOne=true; 55 | } else { 56 | r=k+r; 57 | plusOne=false; 58 | } 59 | } 60 | if(i<0&&plusOne){ 61 | r="1"+r; 62 | } 63 | return r; 64 | } 65 | 66 | public static void main(String[] args) { 67 | String a = "1010"; 68 | String b = "1011"; 69 | String r = new Solution67().addBinary(a, b); 70 | System.out.println(r);//10101 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution69.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | /** 4 | * 69. x 的平方根 5 | * 实现 int sqrt(int x) 函数。 6 | * 7 | * 计算并返回 x 的平方根,其中 x 是非负整数。 8 | * 9 | * 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。 10 | * 11 | * 示例 1: 12 | * 输入: 4 13 | * 输出: 2 14 | * 15 | * 示例 2: 16 | * 输入: 8 17 | * 输出: 2 18 | * 说明: 8 的平方根是 2.82842..., 19 | * 由于返回类型是整数,小数部分将被舍去。 20 | * 21 | * @author 刘壮飞 22 | * https://github.com/zfman. 23 | * https://blog.csdn.net/lzhuangfei. 24 | */ 25 | public class Solution69 { 26 | 27 | /** 28 | * 调用系统库 29 | * @param x 30 | * @return 31 | */ 32 | public int mySqrt(int x) { 33 | return (int)Math.sqrt(x); 34 | } 35 | 36 | /** 37 | * 这个方法我还不太理解,备注 38 | * @param x 39 | * @return 40 | */ 41 | public int mySqrt2(int x) { 42 | if(x<=1) return x; 43 | long m=x; 44 | while(m>x/m){ 45 | m=(m+x/m)/2; 46 | } 47 | return (int)m; 48 | } 49 | 50 | public static void main(String[] args) { 51 | int x = 8; 52 | int r = new Solution69().mySqrt(x); 53 | int r2=new Solution69().mySqrt2(x); 54 | System.out.println("Method1:"+r); 55 | System.out.println("Method2:"+r2); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution7.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | /** 4 | * 反转整数. 5 | * 给定一个 32 位有符号整数,将整数中的数字进行反转。 6 | *

7 | * 示例 1: 8 | * 输入: 123 9 | * 输出: 321 10 | *

11 | * 示例 2: 12 | * 输入: -123 13 | * 输出: -321 14 | *

15 | * 示例 3: 16 | * 输入: 120 17 | * 输出: 21 18 | *

19 | * 注意: 20 | * 假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。根据这个假设,如果反转后的整数溢出,则返回 0。 21 | * 22 | * @author 刘壮飞 23 | * https://github.com/zfman. 24 | * https://blog.csdn.net/lzhuangfei. 25 | */ 26 | public class Solution7 { 27 | 28 | /** 29 | * 用long保存结果.从低位开始计算,注意负数的处理 30 | * @param x 31 | * @return 32 | */ 33 | public int reverse(int x) { 34 | int head=1; 35 | if(x<0) { 36 | x=-x; 37 | head=-1; 38 | } 39 | 40 | int t=x%10; 41 | long r=0; 42 | x=x/10; 43 | while(x!=0){ 44 | r=(r+t)*10; 45 | t=x%10; 46 | x=x/10; 47 | } 48 | r=(r+t); 49 | 50 | if((head*r>(Math.pow(2,31)-1))||(head*r<-1*(Math.pow(2,31)-1))) return 0; 51 | return (int)(head*r); 52 | } 53 | 54 | public static void main(String[] args){ 55 | int x=-123; 56 | int r=new Solution7().reverse(x); 57 | System.out.println(r); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution8.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | /** 4 | * 未完成 5 | * @author 刘壮飞 6 | * https://github.com/zfman. 7 | * https://blog.csdn.net/lzhuangfei. 8 | */ 9 | public class Solution8 { 10 | 11 | public int myAtoi(String str) { 12 | return 0; 13 | } 14 | 15 | public static void main(String[] args){ 16 | String str="+-2"; 17 | int r=new Solution8().myAtoi(str); 18 | System.out.println(r); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution83.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | import leetcode.common.LinkedUtils; 4 | import leetcode.common.ListNode; 5 | 6 | /** 7 | * 83. 删除排序链表中的重复元素. 8 | * 给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。 9 | * 10 | * 示例 1: 11 | * 输入: 1->1->2 12 | * 输出: 1->2 13 | * 14 | * 示例 2: 15 | * 输入: 1->1->2->3->3 16 | * 输出: 1->2->3 17 | * 18 | * @author 刘壮飞 19 | * https://github.com/zfman. 20 | * https://blog.csdn.net/lzhuangfei. 21 | */ 22 | public class Solution83 { 23 | /** 24 | * 从第二个元素开始,和它之前的元素比较, 25 | * 如果相同,删除当前节点,继续比较直至末尾 26 | * @param head 27 | * @return 28 | */ 29 | public ListNode deleteDuplicates(ListNode head) { 30 | ListNode p=head,q=null; 31 | while(p!=null){ 32 | if(q!=null&&p.val==q.val) { 33 | q.next=p.next; 34 | p=q.next; 35 | }else{ 36 | q=p; 37 | p=p.next; 38 | } 39 | } 40 | 41 | return head; 42 | } 43 | 44 | public static void main(String[] args) { 45 | int[] array={ 46 | 1,1,2,2,2,2,2 47 | }; 48 | ListNode head=LinkedUtils.arrayToLinkedList(array); 49 | ListNode r=new Solution83().deleteDuplicates(head); 50 | LinkedUtils.print(r); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution9.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | /** 4 | * 回文数. 5 | * 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 6 | * 7 | * 示例 1: 8 | * 输入: 121 9 | * 输出: true 10 | * 11 | * 示例 2: 12 | * 输入: -121 13 | * 输出: false 14 | * 解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。 15 | * 16 | * 示例 3: 17 | * 输入: 10 18 | * 输出: false 19 | * 解释: 从右向左读, 为 01 。因此它不是一个回文数。 20 | * 21 | * 进阶: 22 | * 23 | * 你能不将整数转为字符串来解决这个问题吗? 24 | * 25 | * @author 刘壮飞 26 | * https://github.com/zfman. 27 | * https://blog.csdn.net/lzhuangfei. 28 | */ 29 | public class Solution9 { 30 | 31 | /** 32 | * 反转所有的数字,比较和原值是否相同. 33 | * 34 | * @param x 35 | * @return 36 | */ 37 | public boolean isPalindrome(int x) { 38 | int t=x; 39 | if(x<0) return false; 40 | if(x<10) return true; 41 | long m=0; 42 | while(x!=0){ 43 | m=(m+x%10)*10; 44 | x=x/10; 45 | } 46 | 47 | m=m/10; 48 | if(m==t) return true; 49 | return false; 50 | } 51 | 52 | /** 53 | * 反转一半的数字. 54 | * 详见题目解析 55 | * 56 | * 首先,我们应该处理一些临界情况。所有负数都不可能是回文, 57 | * 例如:-123 不是回文,因为 - 不等于 3。所以我们可以对所有负数返回 false。 58 | * 59 | * 现在,让我们来考虑如何反转后半部分的数字。 60 | * 对于数字 1221,如果执行 1221 % 10,我们将得到最后一位数字 1,要得到倒数第二位数字, 61 | * 我们可以先通过除以 10 把最后一位数字从 1221 中移除,1221 / 10 = 122,再求出上一步结果除以10的余数, 62 | * 122 % 10 = 2,就可以得到倒数第二位数字。如果我们把最后一位数字乘以10,再加上倒数第二位数字, 63 | * 1 * 10 + 2 = 12,就得到了我们想要的反转后的数字。 如果继续这个过程,我们将得到更多位数的反转数字。 64 | * 65 | * 现在的问题是,我们如何知道反转数字的位数已经达到原始数字位数的一半? 66 | * 67 | * 我们将原始数字除以 10,然后给反转后的数字乘上 10,所以,当原始数字小于反转后的数字时,就意味着我们已经处理了一半位数的数字。 68 | * 69 | * @param x 70 | * @return 71 | */ 72 | public boolean isPalindrome2(int x) { 73 | // 特殊情况: 74 | // 如上所述,当 x < 0 时,x 不是回文数。 75 | // 同样地,如果数字的最后一位是 0,为了使该数字为回文, 76 | // 则其第一位数字也应该是 0 77 | // 只有 0 满足这一属性 78 | if(x<0||(x%10==0&&x!=0)) return false; 79 | 80 | int revertedNumber=0; 81 | while(x>revertedNumber){ 82 | revertedNumber=revertedNumber*10+x%10; 83 | x/=10; 84 | } 85 | 86 | // 当数字长度为奇数时,我们可以通过 revertedNumber/10 去除处于中位的数字。 87 | // 例如,当输入为 12321 时,在 while 循环的末尾我们可以得到 x = 12,revertedNumber = 123, 88 | // 由于处于中位的数字不影响回文(它总是与自己相等),所以我们可以简单地将其去除。 89 | return x==revertedNumber||x==revertedNumber/10; 90 | } 91 | 92 | public static void main(String[] args) { 93 | int x=1000000001; 94 | boolean b = new Solution9().isPalindrome(x); 95 | boolean b2 = new Solution9().isPalindrome2(x); 96 | System.out.println("Method1:"+b); 97 | System.out.println("Method2:"+b2); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/leetcode/all/solution1_100/Solution91.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution1_100; 2 | 3 | /** 4 | * 91. 解码方法 5 | * 6 | * 一条包含字母 A-Z 的消息通过以下方式进行了编码: 7 | * 8 | * 'A' -> 1 9 | * 'B' -> 2 10 | * ... 11 | * 'Z' -> 26 12 | * 给定一个只包含数字的非空字符串,请计算解码方法的总数。 13 | * 14 | * 示例 1: 15 | * 16 | * 输入: "12" 17 | * 输出: 2 18 | * 解释: 它可以解码为 "AB"(1 2)或者 "L"(12)。 19 | * 示例 2: 20 | * 21 | * 输入: "226" 22 | * 输出: 3 23 | * 解释: 它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。 24 | * 25 | * @author 刘壮飞 26 | * https://github.com/zfman. 27 | * https://blog.csdn.net/lzhuangfei. 28 | */ 29 | public class Solution91 { 30 | 31 | /** 32 | * 1.长度小于1,返回0 33 | * 2.dp的长度比字符串长度多一个,第一位默认为1 34 | * 3.对s中的每个字符: 35 | * ch为'0',该位置为0,否则,为上一个值 36 | * 如果可以和上个元素组合为符合的数字, 37 | * 那么该位置等于该位置的值+上上个位置的值 38 | * 39 | * @param s 40 | * @return 41 | */ 42 | public int numDecodings(String s) { 43 | if(s==null||s.length()<1) return 0; 44 | int[] dp=new int[s.length()+1]; 45 | dp[0]=1; 46 | for(int i=1;i<=s.length();i++){ 47 | dp[i]=s.charAt(i-1)=='0'?0:dp[i-1]; 48 | if(i>1&&(s.charAt(i-2)=='1'||(s.charAt(i-2)=='2'&&s.charAt(i-1)<='6'))){ 49 | dp[i]+=dp[i-2]; 50 | } 51 | } 52 | return dp[s.length()]; 53 | } 54 | 55 | public static void main(String[] args){ 56 | String s="110"; 57 | int r=new Solution91().numDecodings(s); 58 | System.out.println(r); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/leetcode/all/solution201_300/Solution226.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution201_300; 2 | 3 | import leetcode.common.TreeNode; 4 | import leetcode.common.TreeUtils; 5 | 6 | /** 7 | * 226. 翻转二叉树 8 | * 9 | * 翻转一棵二叉树。 10 | * 11 | * 示例: 12 | * 13 | * 输入: 14 | * 15 | * 4 16 | * / \ 17 | * 2 7 18 | * / \ / \ 19 | * 1 3 6 9 20 | * 输出: 21 | * 22 | * 4 23 | * / \ 24 | * 7 2 25 | * / \ / \ 26 | * 9 6 3 1 27 | * 备注: 28 | * 这个问题是受到 Max Howell 的 原问题 启发的 : 29 | * 30 | * 谷歌:我们90%的工程师使用您编写的软件(Homebrew),但是您却无法在面试时在白板上写出翻转二叉树这道题,这太糟糕了。 31 | * 32 | * @author 刘壮飞 33 | * https://github.com/zfman. 34 | * https://blog.csdn.net/lzhuangfei. 35 | */ 36 | public class Solution226 { 37 | public TreeNode invertTree(TreeNode root) { 38 | doThing(root); 39 | return root; 40 | } 41 | 42 | public void doThing(TreeNode root) { 43 | if(root!=null){ 44 | doThing(root.left); 45 | doThing(root.right); 46 | TreeNode tmp=root.left; 47 | root.left=root.right; 48 | root.right=tmp; 49 | } 50 | } 51 | 52 | public static void main(String[] args){ 53 | TreeNode root=TreeUtils.stringToTree("421##3##76##9##"); 54 | TreeNode r=new Solution226().invertTree(root); 55 | TreeUtils.travser(r); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/leetcode/all/solution201_300/Solution257.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution201_300; 2 | 3 | import leetcode.common.TreeNode; 4 | import leetcode.common.TreeUtils; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | /** 10 | * 257. 二叉树的所有路径 11 | * 12 | * 给定一个二叉树,返回所有从根节点到叶子节点的路径。 13 | * 14 | * 说明: 叶子节点是指没有子节点的节点。 15 | * 16 | * 示例: 17 | * 18 | * 输入: 19 | * 20 | * 1 21 | * / \ 22 | * 2 3 23 | * \ 24 | * 5 25 | * 26 | * 输出: ["1->2->5", "1->3"] 27 | * 28 | * 解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3 29 | * 30 | * @author 刘壮飞 31 | * https://github.com/zfman. 32 | * https://blog.csdn.net/lzhuangfei. 33 | */ 34 | public class Solution257 { 35 | public List binaryTreePaths(TreeNode root) { 36 | List list=new ArrayList<>(); 37 | todo(root,list,""); 38 | return list; 39 | } 40 | 41 | public void todo(TreeNode root,List list,String s) { 42 | String tmp=(s.length()==0?"":s+"->"); 43 | if(root!=null){ 44 | if(root.left==null&&root.right==null) { 45 | list.add(tmp+root.val); 46 | }else{ 47 | todo(root.left,list,tmp+root.val); 48 | todo(root.right,list,tmp+root.val); 49 | } 50 | } 51 | } 52 | 53 | public static void main(String[] args){ 54 | TreeNode root=TreeUtils.stringToTree("12#5##3##"); 55 | List r=new Solution257().binaryTreePaths(root); 56 | for(String s:r){ 57 | System.out.println(s); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/leetcode/all/solution301_400/Solution303.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution301_400; 2 | 3 | /** 4 | * 303. 区域和检索 - 数组不可变 5 | * 6 | * 给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点。 7 | * 8 | * 示例: 9 | * 10 | * 给定 nums = [-2, 0, 3, -5, 2, -1],求和函数为 sumRange() 11 | * 12 | * sumRange(0, 2) -> 1 13 | * sumRange(2, 5) -> -1 14 | * sumRange(0, 5) -> -3 15 | * 说明: 16 | * 17 | * 你可以假设数组不可变。 18 | * 会多次调用 sumRange 方法。 19 | * 20 | * 两种方法 21 | * 22 | * @author 刘壮飞 23 | * https://github.com/zfman. 24 | * https://blog.csdn.net/lzhuangfei. 25 | */ 26 | public class Solution303 { 27 | public static void main(String[] args) { 28 | int[] nums = { 29 | -2, 0, 3, -5, 2, -1 30 | }; 31 | NumArray array = new NumArray(nums); 32 | int r1 = array.sumRange(0,2); 33 | int r2=array.sumRange(2,5); 34 | int r3=array.sumRange(0,5); 35 | System.out.println("Method1:"+r1+" "+r2+" "+r3); 36 | 37 | NumArray2 array2 = new NumArray2(nums); 38 | int m1 = array.sumRange(0,2); 39 | int m2=array.sumRange(2,5); 40 | int m3=array.sumRange(0,5); 41 | System.out.println("Method2:"+m1+" "+m2+" "+m3); 42 | } 43 | } 44 | 45 | /** 46 | * 第一种方法 47 | */ 48 | class NumArray { 49 | 50 | int[] nums; 51 | 52 | public NumArray(int[] nums) { 53 | this.nums=nums; 54 | } 55 | 56 | public int sumRange(int i, int j) { 57 | if(i<0||j>=nums.length||i>j) return 0; 58 | int sum=0; 59 | for(;i<=j;i++){ 60 | sum+=nums[i]; 61 | } 62 | return sum; 63 | } 64 | } 65 | 66 | /** 67 | * 第二种方法,推荐 68 | * 69 | * 由于数组是不可变的,所以在构造函数初始化时将上一个元素与当前值的和给计算出来 70 | */ 71 | class NumArray2 { 72 | 73 | int[] sum; 74 | 75 | public NumArray2(int[] nums) { 76 | sum=new int[nums.length+1]; 77 | sum[0]=0; 78 | for(int i=1;i 8 22 | * sumRegion(1, 1, 2, 2) -> 11 23 | * sumRegion(1, 2, 2, 4) -> 12 24 | * 说明: 25 | * 26 | * 你可以假设矩阵不可变。 27 | * 会多次调用 sumRegion 方法。 28 | * 你可以假设 row1 ≤ row2 且 col1 ≤ col2。 29 | * 30 | * @author 刘壮飞 31 | * https://github.com/zfman. 32 | * https://blog.csdn.net/lzhuangfei. 33 | */ 34 | public class Solution304 { 35 | public static void main(String[] args) { 36 | int[][] matrix = { 37 | {3, 0, 1, 4, 2}, 38 | {5, 6, 3, 2, 1}, 39 | {1, 2, 0, 1, 5}, 40 | {4, 1, 0, 1, 7}, 41 | {1, 0, 3, 0, 5} 42 | }; 43 | NumMatrix numMatrix= new NumMatrix(matrix); 44 | int m1 = numMatrix.sumRegion(2, 1, 4, 3); 45 | int m2 = numMatrix.sumRegion(1, 1, 2, 2); 46 | int m3 = numMatrix.sumRegion(1, 2, 2, 4); 47 | System.out.println("Method2:" + m1 + " " + m2 + " " + m3); 48 | } 49 | } 50 | 51 | /** 52 | * 必须使用高效的算法,否则通不过的 53 | */ 54 | class NumMatrix { 55 | 56 | //dp[i][j]:从(0,0)->(i,j)围成的矩形的和 57 | int[][] dp; 58 | 59 | public NumMatrix(int[][] matrix) { 60 | if(matrix.length<=0||matrix[0].length<=0){ 61 | this.dp=null; 62 | return; 63 | } 64 | this.dp=new int[matrix.length][matrix[0].length]; 65 | 66 | //初始化,按行累加 67 | for(int i=0;i(i,j)围成的矩形的和. 84 | * 取值的时候需要注意边界值 85 | * 86 | * @param row1 起始行 87 | * @param col1 起始列 88 | * @param row2 终止行 89 | * @param col2 中止列 90 | * @return 91 | */ 92 | public int sumRegion(int row1, int col1, int row2, int col2) { 93 | if(dp==null) return 0; 94 | if(row1==0){ 95 | if(col1==0){ 96 | return dp[row2][col2]; 97 | } 98 | return dp[row2][col2]-dp[row2][col1-1]; 99 | }else{ 100 | if(col1==0){ 101 | return dp[row2][col2]-dp[row1-1][col2]; 102 | } 103 | return dp[row2][col2]-dp[row1-1][col2]-dp[row2][col1-1]+dp[row1-1][col1-1]; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/leetcode/all/solution301_400/Solution349.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution301_400; 2 | 3 | import utils.ArrayUtils; 4 | 5 | import java.util.Arrays; 6 | import java.util.HashMap; 7 | import java.util.HashSet; 8 | import java.util.Set; 9 | 10 | /** 11 | * 349. 两个数组的交集 12 | * 13 | * 给定两个数组,编写一个函数来计算它们的交集。 14 | * 15 | * 示例 1: 16 | * 17 | * 输入: nums1 = [1,2,2,1], nums2 = [2,2] 18 | * 输出: [2] 19 | * 示例 2: 20 | * 21 | * 输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4] 22 | * 输出: [9,4] 23 | * 说明: 24 | * 25 | * 输出结果中的每个元素一定是唯一的。 26 | * 我们可以不考虑输出结果的顺序。 27 | * 28 | * @author 刘壮飞 29 | * https://github.com/zfman. 30 | * https://blog.csdn.net/lzhuangfei. 31 | */ 32 | public class Solution349 { 33 | /** 34 | * 利用哈希表或者 35 | * 先排序后使用双指针,如果指针指向相同,说明出现一个交集元素 36 | * 37 | * @param nums1 38 | * @param nums2 39 | * @return 40 | */ 41 | public int[] intersection(int[] nums1, int[] nums2) { 42 | HashMap map = new HashMap(); 43 | Set set = new HashSet<>();//去重 44 | for (int i = 0; i < nums1.length; i++) { 45 | if (!map.containsKey(nums1[i])) map.put(nums1[i], 0); 46 | else map.put(nums1[i], map.get(nums1[i]) + 1); 47 | } 48 | 49 | for (int i = 0; i < nums2.length; i++) { 50 | if (map.containsKey(nums2[i])) { 51 | set.add(nums2[i]); 52 | } 53 | } 54 | 55 | int[] r = new int[set.size()]; 56 | int i = 0; 57 | for (Integer val : set) { 58 | r[i++] = val; 59 | } 60 | return r; 61 | } 62 | 63 | public static void main(String[] args) { 64 | int[] nums1 = { 65 | 4, 9, 5 66 | }; 67 | int[] nums2 = { 68 | 9, 4, 9, 8, 4 69 | }; 70 | int[] r = new Solution349().intersection(nums1, nums2); 71 | ArrayUtils.printArray(r); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/leetcode/all/solution301_400/Solution354.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution301_400; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * 354. 俄罗斯套娃信封问题 7 | * 8 | * 给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。 9 | * 10 | * 请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。 11 | * 12 | * 说明: 13 | * 不允许旋转信封。 14 | * 15 | * 示例: 16 | * 17 | * 输入: envelopes = [[5,4],[6,4],[6,7],[2,3]] 18 | * 输出: 3 19 | * 解释: 最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。 20 | * 21 | * @author 刘壮飞 22 | * https://github.com/zfman. 23 | * https://blog.csdn.net/lzhuangfei. 24 | */ 25 | public class Solution354 { 26 | 27 | /** 28 | * 先对宽度递增排序,然后对高度计算“最长递增子序列的长度” 29 | * @param envelopes 30 | * @return 31 | */ 32 | public int maxEnvelopes(int[][] envelopes) { 33 | if (envelopes.length == 0) return 0; 34 | int[] dp = new int[envelopes.length]; 35 | Arrays.fill(dp, 1); 36 | sort(envelopes); 37 | int max = 1; 38 | for (int i = 1; i < envelopes.length; i++) { 39 | for (int j = 0; j < i; j++) { 40 | if (envelopes[i][0]>envelopes[j][0]&&envelopes[i][1] > envelopes[j][1]) { 41 | dp[i] = Math.max(dp[i], dp[j] + 1); 42 | } 43 | } 44 | if (dp[i] > max) max = dp[i]; 45 | } 46 | return max; 47 | } 48 | 49 | public void sort(int[][] envelopes) { 50 | for (int i = 0; i < envelopes.length - 1; i++) { 51 | for (int j = i + 1; j < envelopes.length; j++) { 52 | if (envelopes[i][0] > envelopes[j][0]) { 53 | int[] tmp = envelopes[i]; 54 | envelopes[i] = envelopes[j]; 55 | envelopes[j] = tmp; 56 | } 57 | } 58 | } 59 | } 60 | 61 | public static void main(String[] args) { 62 | int[][] envelopes = { 63 | {5,4},{6,4},{6,7},{2,3} 64 | }; 65 | // 2,4 5,4 6,4 6,7 66 | // 1 1 1 1 67 | 68 | int r = new Solution354().maxEnvelopes(envelopes); 69 | System.out.println(r); 70 | } 71 | 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/leetcode/all/solution301_400/Solution383.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution301_400; 2 | 3 | /** 4 | * 383. 赎金信 5 | * 6 | * 给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串ransom能不能由第二个字符串magazines里面的字符构成。如果可以构成,返回 true ;否则返回 false。 7 | * 8 | * (题目说明:为了不暴露赎金信字迹,要从杂志上搜索各个需要的字母,组成单词来表达意思。) 9 | * 10 | * 注意: 11 | * 12 | * 你可以假设两个字符串均只含有小写字母。 13 | * 14 | * canConstruct("a", "b") -> false 15 | * canConstruct("aa", "ab") -> false 16 | * canConstruct("aa", "aab") -> true 17 | * 18 | * @author 刘壮飞 19 | * https://github.com/zfman. 20 | * https://blog.csdn.net/lzhuangfei. 21 | */ 22 | public class Solution383 { 23 | public boolean canConstruct(String ransomNote, String magazine) { 24 | int[] a=new int[26]; 25 | for(char ch:magazine.toCharArray()){ 26 | a[ch-'a']++; 27 | } 28 | for(char ch:ransomNote.toCharArray()){ 29 | a[ch-'a']--; 30 | } 31 | 32 | for(int i=0;i 3 32 | * 2. 5 -> 2 -> 1 33 | * 3. -3 -> 11 34 | * 35 | * @author 刘壮飞 36 | * https://github.com/zfman. 37 | * https://blog.csdn.net/lzhuangfei. 38 | */ 39 | public class Solution437 { 40 | private int pathCount=0; 41 | 42 | public int pathSum(TreeNode root, int sum) { 43 | todo(root,sum); 44 | return pathCount; 45 | } 46 | 47 | /** 48 | * 以root为起始点开始计算路径长度 49 | * @param root 50 | * @param sum 51 | */ 52 | public void todo(TreeNode root, int sum) { 53 | if(root!=null){ 54 | doThing(root,sum,0); 55 | todo(root.left,sum); 56 | todo(root.right,sum); 57 | } 58 | } 59 | 60 | public void doThing(TreeNode node, int sum,int now) { 61 | if(node==null) return; 62 | if(now+node.val==sum) pathCount++; 63 | if(node.left!=null||node.right!=null){ 64 | doThing(node.left,sum,now+node.val); 65 | doThing(node.right,sum,now+node.val); 66 | } 67 | } 68 | 69 | public static void main(String[] args){ 70 | // sout:3 71 | TreeNode root=TreeUtils.stringToTreeWith("5 4 11 7 # # 2 # # # 8 13 # # 4 5 # # 1 # #"," "); 72 | int sum=22; 73 | int r=new Solution437().pathSum(root,sum); 74 | System.out.println(r); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/leetcode/all/solution401_500/Solution442.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution401_500; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 442. 数组中重复的数据 8 | * 9 | * 给定一个整数数组 a,其中1 ≤ a[i] ≤ n (n为数组长度), 其中有些元素出现两次而其他元素出现一次。 10 | * 11 | * 找到所有出现两次的元素。 12 | * 13 | * 你可以不用到任何额外空间并在O(n)时间复杂度内解决这个问题吗? 14 | * 15 | * 示例: 16 | * 17 | * 输入: 18 | * [4,3,2,7,8,2,3,1] 19 | * 20 | * 输出: 21 | * [2,3] 22 | * 23 | * @author 刘壮飞 24 | * https://github.com/zfman. 25 | * https://blog.csdn.net/lzhuangfei. 26 | */ 27 | public class Solution442 { 28 | 29 | /** 30 | * 使用桶排序的思想(不需要排序). 31 | * 这句话是关键:1 ≤ a[i] ≤ n (n为数组长度), 32 | * v[i]:桶,下标与nums[i]值对应 33 | * 34 | * @param nums 35 | * @return 36 | */ 37 | public List findDuplicates(int[] nums) { 38 | List r = new ArrayList<>(); 39 | int[] v=new int[nums.length+1]; 40 | for (int i = 0; i < nums.length; i++) { 41 | v[nums[i]]++; 42 | } 43 | for(int i=1;i=2) r.add(i); 45 | } 46 | return r; 47 | } 48 | 49 | public static void main(String[] args) { 50 | int[] nums = { 51 | 4, 3, 2, 7, 8, 2, 3, 1 52 | }; 53 | List r = new Solution442().findDuplicates(nums); 54 | for (Integer i : r) { 55 | System.out.print(i + " "); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/leetcode/all/solution401_500/Solution443.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution401_500; 2 | 3 | /** 4 | * 443. 压缩字符串 5 | * 6 | * 给定一组字符,使用原地算法将其压缩。 7 | * 8 | * 压缩后的长度必须始终小于或等于原数组长度。 9 | * 10 | * 数组的每个元素应该是长度为1 的字符(不是 int 整数类型)。 11 | * 12 | * 在完成原地修改输入数组后,返回数组的新长度。 13 | * 14 | * 15 | * 16 | * 进阶: 17 | * 你能否仅使用O(1) 空间解决问题? 18 | * 19 | * 20 | * 21 | * 示例 1: 22 | * 23 | * 输入: 24 | * ["a","a","b","b","c","c","c"] 25 | * 26 | * 输出: 27 | * 返回6,输入数组的前6个字符应该是:["a","2","b","2","c","3"] 28 | * 29 | * 说明: 30 | * "aa"被"a2"替代。"bb"被"b2"替代。"ccc"被"c3"替代。 31 | * 示例 2: 32 | * 33 | * 输入: 34 | * ["a"] 35 | * 36 | * 输出: 37 | * 返回1,输入数组的前1个字符应该是:["a"] 38 | * 39 | * 说明: 40 | * 没有任何字符串被替代。 41 | * 示例 3: 42 | * 43 | * 输入: 44 | * ["a","b","b","b","b","b","b","b","b","b","b","b","b"] 45 | * 46 | * 输出: 47 | * 返回4,输入数组的前4个字符应该是:["a","b","1","2"]。 48 | * 49 | * 说明: 50 | * 由于字符"a"不重复,所以不会被压缩。"bbbbbbbbbbbb"被“b12”替代。 51 | * 注意每个数字在数组中都有它自己的位置。 52 | * 注意: 53 | * 54 | * 所有字符都有一个ASCII值在[35, 126]区间内。 55 | * 1 <= len(chars) <= 1000。 56 | * 57 | * @author 刘壮飞 58 | * https://github.com/zfman. 59 | * https://blog.csdn.net/lzhuangfei. 60 | */ 61 | public class Solution443 { 62 | /** 63 | * 该算法没有满足题目要求,空间占用不是O(1) 64 | * 思路: 65 | * 遍历,计算重复字符的长度,遇到和上个字符相同时,令计数器+1 66 | * 遇到不同时,令上次相同的字符和长度组合为一个字符串,加入到str中 67 | * 遍历结束后令上次相同的字符和长度组合为一个字符串,加入到str中 68 | * 69 | * @param chars 70 | * @return 71 | */ 72 | public int compress(char[] chars) { 73 | if(chars.length==1) return 1; 74 | 75 | //得出str 76 | char ch=chars[0]; 77 | String str=""; 78 | int c=1; 79 | for(int i=1;i1) str+=ch+""+c; 84 | else str+=ch; 85 | c=1; 86 | } 87 | ch=chars[i]; 88 | } 89 | //最后匹配到存储到str 90 | if(c>1) str+=ch+""+c; 91 | else str+=ch; 92 | 93 | //修改chars数组的值 94 | for(int i=0;i findDuplicates(int[] nums) { 38 | List r = new ArrayList<>(); 39 | int[] v=new int[nums.length+1]; 40 | for (int i = 0; i < nums.length; i++) { 41 | v[nums[i]]++; 42 | } 43 | for(int i=1;i r = new Solution448().findDuplicates(nums); 54 | for (Integer i : r) { 55 | System.out.print(i + " "); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/leetcode/all/solution401_500/Solution459.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution401_500; 2 | 3 | /** 4 | * 未完成 5 | * @author 刘壮飞 6 | * https://github.com/zfman. 7 | * https://blog.csdn.net/lzhuangfei. 8 | */ 9 | public class Solution459 { 10 | public boolean repeatedSubstringPattern(String s) { 11 | for(int i=0;i='A'&&ch1<='Z'){ 45 | if(ch2>='A'&&ch2<='Z'){ 46 | type=1; 47 | }else type=2; 48 | }else{ 49 | if(ch2>='A'&&ch2<='Z'){ 50 | return false; 51 | }else type=2; 52 | } 53 | 54 | //遍历后续字符 55 | for(int i=2;i='a'&&ch<='z') return false; 59 | }else if(type==2){//后续字符全为小写 60 | if(ch>='A'&&ch<='Z') return false; 61 | } 62 | } 63 | return true; 64 | } 65 | public static void main(String[] args){ 66 | String words="FlaG"; 67 | boolean r=new Solution520().detectCapitalUse(words); 68 | System.out.println(r); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/leetcode/all/solution501_600/Solution541.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution501_600; 2 | 3 | /** 4 | * 541. 反转字符串 II 5 | * 6 | * 给定一个字符串和一个整数 k,你需要对从字符串开头算起的每个 2k 个字符的前k个字符进行反转。如果剩余少于 k 个字符,则将剩余的所有全部反转。如果有小于 2k 但大于或等于 k 个字符,则反转前 k 个字符,并将剩余的字符保持原样。 7 | * 8 | * 示例: 9 | * 10 | * 输入: s = "abcdefg", k = 2 11 | * 输出: "bacdfeg" 12 | * 要求: 13 | * 14 | * 该字符串只包含小写的英文字母。 15 | * 给定字符串的长度和 k 在[1, 10000]范围内。 16 | * 17 | * @author 刘壮飞 18 | * https://github.com/zfman. 19 | * https://blog.csdn.net/lzhuangfei. 20 | */ 21 | public class Solution541 { 22 | public String reverseStr(String s, int k) { 23 | if(s==null||s.equals("")) return ""; 24 | if(s.length()=0;i--){ 36 | str+=s.charAt(i); 37 | } 38 | return str; 39 | } 40 | 41 | public static void main(String[] args) { 42 | String s = "abcdefg"; 43 | int k = 2; 44 | String r = new Solution541().reverseStr(s, k); 45 | System.out.println(r); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/leetcode/all/solution501_600/Solution543.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution501_600; 2 | 3 | import leetcode.common.TreeNode; 4 | import leetcode.common.TreeUtils; 5 | 6 | /** 7 | * 543. 二叉树的直径 8 | * 9 | * 给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过根结点。 10 | * 11 | * 示例 : 12 | * 给定二叉树 13 | * 14 | * 1 15 | * / \ 16 | * 2 3 17 | * / \ 18 | * 4 5 19 | * 返回 3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。 20 | * 21 | * 注意:两结点之间的路径长度是以它们之间边的数目表示。 22 | * 23 | * @author 刘壮飞 24 | * https://github.com/zfman. 25 | * https://blog.csdn.net/lzhuangfei. 26 | */ 27 | public class Solution543 { 28 | private int maxVal=0; 29 | public int diameterOfBinaryTree(TreeNode root) { 30 | todo(root); 31 | return maxVal; 32 | } 33 | 34 | /** 35 | * 以root为起始点,计算左右子树的深度之和,记录最大值 36 | * @param root 37 | */ 38 | public void todo(TreeNode root) { 39 | if(root!=null){ 40 | int v=depth(root.left)+depth(root.right); 41 | if(v>maxVal) maxVal=v; 42 | todo(root.left); 43 | todo(root.right); 44 | } 45 | } 46 | 47 | /** 48 | * 求解树深度 49 | * @param root 50 | * @return 51 | */ 52 | public int depth(TreeNode root) { 53 | if(root==null) return 0; 54 | return Math.max(depth(root.left),depth(root.right))+1; 55 | } 56 | 57 | public static void main(String[] args){ 58 | TreeNode root=TreeUtils.stringToTree("124##5##3##"); 59 | int r=new Solution543().diameterOfBinaryTree(root); 60 | System.out.println(r); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/leetcode/all/solution501_600/Solution551.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution501_600; 2 | 3 | /** 4 | * 551. 学生出勤纪录 I 5 | * 6 | * 给定一个字符串来代表一个学生的出勤纪录,这个纪录仅包含以下三个字符: 7 | * 8 | * 'A' : Absent,缺勤 9 | * 'L' : Late,迟到 10 | * 'P' : Present,到场 11 | * 如果一个学生的出勤纪录中不超过一个'A'(缺勤)并且不超过两个连续的'L'(迟到),那么这个学生会被奖赏。 12 | * 13 | * 你需要根据这个学生的出勤纪录判断他是否会被奖赏。 14 | * 15 | * 示例 1: 16 | * 17 | * 输入: "PPALLP" 18 | * 输出: True 19 | * 示例 2: 20 | * 21 | * 输入: "PPALLL" 22 | * 输出: False 23 | * 24 | * @author 刘壮飞 25 | * https://github.com/zfman. 26 | * https://blog.csdn.net/lzhuangfei. 27 | */ 28 | public class Solution551 { 29 | 30 | public boolean checkRecord(String s) { 31 | int aCount=0;//char A count 32 | int sameCount=0; //same char count 33 | 34 | for(int i=0;i2) break; 40 | } 41 | return aCount<=1&&sameCount<=2; 42 | } 43 | 44 | public static void main(String[] args) { 45 | String s = "PPALLP"; 46 | boolean r = new Solution551().checkRecord(s); 47 | System.out.println(r); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/leetcode/all/solution501_600/Solution557.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution501_600; 2 | 3 | /** 4 | * 557. 反转字符串中的单词 III 5 | * 6 | * 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。 7 | * 8 | * 示例 1: 9 | * 10 | * 输入: "Let's take LeetCode contest" 11 | * 输出: "s'teL ekat edoCteeL tsetnoc" 12 | * 注意:在字符串中,每个单词由单个空格分隔,并且字符串中不会有任何额外的空格。 13 | * 14 | * @author 刘壮飞 15 | * https://github.com/zfman. 16 | * https://blog.csdn.net/lzhuangfei. 17 | */ 18 | public class Solution557 { 19 | public String reverseWords(String s) { 20 | String[] arr=s.split(" "); 21 | String str=""; 22 | for(int i=0;i=0;i--){ 31 | str+=s.charAt(i); 32 | } 33 | return str; 34 | } 35 | 36 | public static void main(String[] args) { 37 | String s = "Let's take LeetCode contest"; 38 | String r = new Solution557().reverseWords(s); 39 | System.out.println(r); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/leetcode/all/solution501_600/Solution559.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution501_600; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 559. N叉树的最大深度 8 | * 9 | * 给定一个N叉树,找到其最大深度。 10 | * 11 | * 最大深度是指从根节点到最远叶子节点的最长路径上的节点总数。 12 | * 13 | * 例如,给定一个 3叉树 : 14 | * 15 | * https://leetcode-cn.com/static/images/problemset/NaryTreeExample.png 16 | * 17 | * 我们应返回其最大深度,3。 18 | * 19 | * 说明: 20 | * 21 | * 树的深度不会超过 1000。 22 | * 树的节点总不会超过 5000。 23 | * 24 | * @author 刘壮飞 25 | * https://github.com/zfman. 26 | * https://blog.csdn.net/lzhuangfei. 27 | */ 28 | public class Solution559 { 29 | public int maxDepth(Node root) { 30 | if(root==null) return 0; 31 | if(root.children==null) return 1; 32 | int max=0; 33 | for(Node node:root.children){ 34 | int t=maxDepth(node); 35 | if(t>max) max=t; 36 | } 37 | return max+1; 38 | } 39 | 40 | public static void main(String[] args){ 41 | Node node5=new Node(5,null); 42 | Node node6=new Node(6,null); 43 | List children3=new ArrayList<>(); 44 | children3.add(node5); 45 | children3.add(node6); 46 | 47 | Node node3=new Node(3,children3); 48 | Node node2=new Node(2,null); 49 | Node node4=new Node(4,null); 50 | 51 | List children1=new ArrayList<>(); 52 | children1.add(node3); 53 | children1.add(node2); 54 | children1.add(node4); 55 | Node root=new Node(1,children1); 56 | 57 | int r=new Solution559().maxDepth(root); 58 | System.out.println(r); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/leetcode/all/solution501_600/Solution563.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution501_600; 2 | 3 | import leetcode.common.TreeNode; 4 | import leetcode.common.TreeUtils; 5 | 6 | /** 7 | * 563. 二叉树的坡度 8 | * 9 | * 给定一个二叉树,计算整个树的坡度。 10 | * 11 | * 一个树的节点的坡度定义即为,该节点左子树的结点之和和右子树结点之和的差的绝对值。空结点的的坡度是0。 12 | * 13 | * 整个树的坡度就是其所有节点的坡度之和。 14 | * 15 | * 示例: 16 | * 17 | * 输入: 18 | * 1 19 | * / \ 20 | * 2 3 21 | * 输出: 1 22 | * 解释: 23 | * 结点的坡度 2 : 0 24 | * 结点的坡度 3 : 0 25 | * 结点的坡度 1 : |2-3| = 1 26 | * 树的坡度 : 0 + 0 + 1 = 1 27 | * 注意: 28 | * 29 | * 任何子树的结点的和不会超过32位整数的范围。 30 | * 坡度的值不会超过32位整数的范围。 31 | * 32 | * @author 刘壮飞 33 | * https://github.com/zfman. 34 | * https://blog.csdn.net/lzhuangfei. 35 | */ 36 | public class Solution563 { 37 | /** 38 | * 计算各个节点的坡度和 39 | * @param root 40 | * @return 41 | */ 42 | public int findTilt(TreeNode root) { 43 | if(root==null) return 0; 44 | return findTilt(root.left)+findTilt(root.right)+Math.abs(todo(root.left)-todo(root.right)); 45 | } 46 | 47 | /** 48 | * 计算以root为起始点的坡度值 49 | * @param root 50 | * @return 51 | */ 52 | public int todo(TreeNode root) { 53 | if(root==null) return 0; 54 | if(root.left==null&&root.right==null){ 55 | return root.val; 56 | } 57 | return root.val+todo(root.left)+todo(root.right); 58 | } 59 | 60 | public static void main(String[] args){ 61 | TreeNode root=TreeUtils.stringToTree("124###35###"); 62 | int r=new Solution563().findTilt(root); 63 | System.out.println(r); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/leetcode/all/solution501_600/Solution572.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution501_600; 2 | 3 | import leetcode.common.TreeNode; 4 | import leetcode.common.TreeUtils; 5 | 6 | /** 7 | * 572. 另一个树的子树 8 | * 9 | * 给定两个非空二叉树 s 和 t,检验 s 中是否包含和 t 具有相同结构和节点值的子树。s 的一个子树包括 s 的一个节点和这个节点的所有子孙。s 也可以看做它自身的一棵子树。 10 | * 11 | * 示例 1: 12 | * 给定的树 s: 13 | * 14 | * 3 15 | * / \ 16 | * 4 5 17 | * / \ 18 | * 1 2 19 | * 给定的树 t: 20 | * 21 | * 4 22 | * / \ 23 | * 1 2 24 | * 返回 true,因为 t 与 s 的一个子树拥有相同的结构和节点值。 25 | * 26 | * 示例 2: 27 | * 给定的树 s: 28 | * 29 | * 3 30 | * / \ 31 | * 4 5 32 | * / \ 33 | * 1 2 34 | * / 35 | * 0 36 | * 给定的树 t: 37 | * 38 | * 4 39 | * / \ 40 | * 1 2 41 | * 返回 false。 42 | * 43 | * @author 刘壮飞 44 | * https://github.com/zfman. 45 | * https://blog.csdn.net/lzhuangfei. 46 | */ 47 | public class Solution572 { 48 | public boolean isSubtree(TreeNode s, TreeNode t) { 49 | return s!=null&&(isSubtree(s.left,t)||isSubtree(s.right,t)||isSample(s,t)); 50 | } 51 | 52 | public boolean isSample(TreeNode s, TreeNode t) { 53 | if(s==null&&t==null) return true; 54 | else if(s==null||t==null) return false; 55 | else{ 56 | return s.val==t.val&&isSample(s.left,t.left)&&isSample(s.right,t.right); 57 | } 58 | } 59 | 60 | public static void main(String[] args){ 61 | TreeNode s=TreeUtils.stringToTree("341##2##5##"); 62 | TreeNode t=TreeUtils.stringToTree("41##2##"); 63 | boolean r=new Solution572().isSubtree(s,t); 64 | System.out.println(r); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/leetcode/all/solution501_600/Solution589.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution501_600; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 589. N叉树的前序遍历(未使用迭代算法) 8 | * 9 | * 给定一个N叉树,返回其节点值的前序遍历。 10 | * 11 | * 例如,给定一个 3叉树 : 12 | * 13 | * https://leetcode-cn.com/static/images/problemset/NaryTreeExample.png 14 | * 15 | * 返回其前序遍历: [1,3,5,6,2,4]。 16 | * 说明: 递归法很简单,你可以使用迭代法完成此题吗? 17 | * 18 | * @author 刘壮飞 19 | * https://github.com/zfman. 20 | * https://blog.csdn.net/lzhuangfei. 21 | */ 22 | class Solution589 { 23 | 24 | public List preorder(Node root) { 25 | List list=new ArrayList<>(); 26 | todo(root,list); 27 | return list; 28 | } 29 | 30 | public void todo(Node root,List list) { 31 | if(root!=null){ 32 | list.add(root.val); 33 | if(root.children!=null){ 34 | for(Node node:root.children){ 35 | todo(node,list); 36 | } 37 | } 38 | } 39 | } 40 | 41 | public static void main(String[] args){ 42 | Node node5=new Node(5,null); 43 | Node node6=new Node(6,null); 44 | List children3=new ArrayList<>(); 45 | children3.add(node5); 46 | children3.add(node6); 47 | 48 | Node node3=new Node(3,children3); 49 | Node node2=new Node(2,null); 50 | Node node4=new Node(4,null); 51 | 52 | List children1=new ArrayList<>(); 53 | children1.add(node3); 54 | children1.add(node2); 55 | children1.add(node4); 56 | Node root=new Node(1,children1); 57 | 58 | List r=new Solution589().preorder(root); 59 | for(Integer i:r){ 60 | System.out.print(i+" "); 61 | } 62 | 63 | } 64 | } 65 | 66 | class Node { 67 | public int val; 68 | public List children; 69 | 70 | public Node() {} 71 | 72 | public Node(int _val,List _children) { 73 | val = _val; 74 | children = _children; 75 | } 76 | }; 77 | -------------------------------------------------------------------------------- /src/leetcode/all/solution501_600/Solution590.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution501_600; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 590. N叉树的后序遍历(未使用迭代算法) 8 | * 9 | * 给定一个N叉树,返回其节点值的后序遍历。 10 | * 11 | * 例如,给定一个 3叉树 : 12 | * 13 | * https://leetcode-cn.com/static/images/problemset/NaryTreeExample.png 14 | * 15 | * 返回其后序遍历: [5,6,3,2,4,1]. 16 | * 说明: 递归法很简单,你可以使用迭代法完成此题吗? 17 | * 18 | * @author 刘壮飞 19 | * https://github.com/zfman. 20 | * https://blog.csdn.net/lzhuangfei. 21 | */ 22 | class Solution590 { 23 | 24 | public List postorder(Node root) { 25 | List list=new ArrayList<>(); 26 | todo(root,list); 27 | return list; 28 | } 29 | 30 | public void todo(Node root,List list) { 31 | if(root!=null){ 32 | if(root.children!=null){ 33 | for(Node node:root.children){ 34 | todo(node,list); 35 | } 36 | } 37 | list.add(root.val); 38 | } 39 | } 40 | 41 | public static void main(String[] args){ 42 | Node node5=new Node(5,null); 43 | Node node6=new Node(6,null); 44 | List children3=new ArrayList<>(); 45 | children3.add(node5); 46 | children3.add(node6); 47 | 48 | Node node3=new Node(3,children3); 49 | Node node2=new Node(2,null); 50 | Node node4=new Node(4,null); 51 | 52 | List children1=new ArrayList<>(); 53 | children1.add(node3); 54 | children1.add(node2); 55 | children1.add(node4); 56 | Node root=new Node(1,children1); 57 | 58 | List r=new Solution590().postorder(root); 59 | for(Integer i:r){ 60 | System.out.print(i+" "); 61 | } 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/leetcode/all/solution601_700/Solution606.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution601_700; 2 | 3 | import leetcode.common.TreeNode; 4 | import leetcode.common.TreeUtils; 5 | 6 | /** 7 | * 606. 根据二叉树创建字符串 8 | * 9 | * 你需要采用前序遍历的方式,将一个二叉树转换成一个由括号和整数组成的字符串。 10 | * 11 | * 空节点则用一对空括号 "()" 表示。而且你需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。 12 | * 13 | * 示例 1: 14 | * 15 | * 输入: 二叉树: [1,2,3,4] 16 | * 1 17 | * / \ 18 | * 2 3 19 | * / 20 | * 4 21 | * 22 | * 输出: "1(2(4))(3)" 23 | * 24 | * 解释: 原本将是“1(2(4)())(3())”, 25 | * 在你省略所有不必要的空括号对之后, 26 | * 它将是“1(2(4))(3)”。 27 | * 示例 2: 28 | * 29 | * 输入: 二叉树: [1,2,3,null,4] 30 | * 1 31 | * / \ 32 | * 2 3 33 | * \ 34 | * 4 35 | * 36 | * 输出: "1(2()(4))(3)" 37 | * 38 | * 解释: 和第一个示例相似, 39 | * 除了我们不能省略第一个对括号来中断输入和输出之间的一对一映射关系。 40 | * 41 | * @author 刘壮飞 42 | * https://github.com/zfman. 43 | * https://blog.csdn.net/lzhuangfei. 44 | */ 45 | public class Solution606 { 46 | public String tree2str(TreeNode t) { 47 | if(t==null) return ""; 48 | String left=tree2str(t.left); 49 | String right=tree2str(t.right); 50 | 51 | //叶子节点 52 | if(left.equals("")&&right.equals("")){ 53 | return t.val+""; 54 | } 55 | //右子树为null 56 | else if(!left.equals("")&&right.equals("")){ 57 | return t.val+"("+left+")"; 58 | } 59 | //非叶子节点&&右子树不为null 60 | else { 61 | return t.val+"("+left+")("+right+")"; 62 | } 63 | } 64 | 65 | public static void main(String[] args){ 66 | TreeNode t=TreeUtils.stringToTree("123##4###"); 67 | String s=new Solution606().tree2str(t); 68 | System.out.println(s); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/leetcode/all/solution601_700/Solution653.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution601_700; 2 | 3 | import leetcode.common.TreeNode; 4 | import leetcode.common.TreeUtils; 5 | 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | 9 | /** 10 | * 653. 两数之和 IV - 输入 BST 11 | * 12 | * 给定一个二叉搜索树和一个目标结果,如果 BST 中存在两个元素且它们的和等于给定的目标结果,则返回 true。 13 | * 14 | * 案例 1: 15 | * 16 | * 输入: 17 | * 5 18 | * / \ 19 | * 3 6 20 | * / \ \ 21 | * 2 4 7 22 | * 23 | * Target = 9 24 | * 25 | * 输出: True 26 | * 27 | * 28 | * 案例 2: 29 | * 30 | * 输入: 31 | * 5 32 | * / \ 33 | * 3 6 34 | * / \ \ 35 | * 2 4 7 36 | * 37 | * Target = 28 38 | * 39 | * 输出: False 40 | * 41 | * @author 刘壮飞 42 | * https://github.com/zfman. 43 | * https://blog.csdn.net/lzhuangfei. 44 | */ 45 | public class Solution653 { 46 | 47 | /** 48 | * 我的思路是:把树中元素存储到集合中,然后对集合二重循环求解和 49 | * 50 | * 以下是别人的思路,代码很简洁高效,学习学习 51 | * 52 | * @param root 53 | * @param k 54 | * @return 55 | */ 56 | public boolean findTarget(TreeNode root, int k) { 57 | Set set=new HashSet<>(); 58 | return todo(root,k,set); 59 | } 60 | 61 | public boolean todo(TreeNode root, int k, Set set) { 62 | if(root==null) return false; 63 | if(set.contains(k-root.val)) return true; 64 | set.add(root.val); 65 | return todo(root.left,k,set)||todo(root.right,k,set); 66 | } 67 | 68 | public static void main(String[] args){ 69 | TreeNode root=TreeUtils.stringToTree("532##4##6#7##"); 70 | boolean r=new Solution653().findTarget(root,9); 71 | System.out.println(r); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/leetcode/all/solution601_700/Solution684.java: -------------------------------------------------------------------------------- 1 | package leetcode.all.solution601_700; 2 | 3 | import utils.ArrayUtils; 4 | 5 | /** 6 | * 684. 冗余连接 7 | * 8 | * 在本问题中, 树指的是一个连通且无环的无向图。 9 | * 10 | * 输入一个图,该图由一个有着N个节点 (节点值不重复1, 2, ..., N) 的树及一条附加的边构成。附加的边的两个顶点包含在1到N中间,这条附加的边不属于树中已存在的边。 11 | * 12 | * 结果图是一个以边组成的二维数组。每一个边的元素是一对[u, v] ,满足 u < v,表示连接顶点u 和v的无向图的边。 13 | * 14 | * 返回一条可以删去的边,使得结果图是一个有着N个节点的树。如果有多个答案,则返回二维数组中最后出现的边。答案边 [u, v] 应满足相同的格式 u < v。 15 | * 16 | * 示例 1: 17 | * 18 | * 输入: [[1,2], [1,3], [2,3]] 19 | * 输出: [2,3] 20 | * 解释: 给定的无向图为: 21 | * 1 22 | * / \ 23 | * 2 - 3 24 | * 示例 2: 25 | * 26 | * 输入: [[1,2], [2,3], [3,4], [1,4], [1,5]] 27 | * 输出: [1,4] 28 | * 解释: 给定的无向图为: 29 | * 5 - 1 - 2 30 | * | | 31 | * 4 - 3 32 | * 注意: 33 | * 34 | * 输入的二维数组大小在 3 到 1000。 35 | * 二维数组中的整数在1到N之间,其中N是输入数组的大小。 36 | * 37 | * @author 刘壮飞 38 | * https://github.com/zfman. 39 | * https://blog.csdn.net/lzhuangfei. 40 | */ 41 | public class Solution684 { 42 | public int[] findRedundantConnection(int[][] edges) { 43 | int[] union=new int[edges.length+1];//映射关系 44 | int[] r=new int[2];//返回结果 45 | for(int i=0;inums.length) return false; 28 | int sum=0; 29 | for(int i=0;itarget) return false; 39 | if(k==0&&nums.length==number) return true; 40 | if(curSum==target) return todo(nums,k-1,0,0,target,v,number); 41 | for(int i=start;i list1=new ArrayList<>(); 33 | List list2=new ArrayList<>(); 34 | todo(root1,list1); 35 | todo(root2,list2); 36 | if(list1.toString().equals(list2.toString())) return true; 37 | return false; 38 | } 39 | 40 | public void todo(TreeNode root, List list) { 41 | if(root!=null){ 42 | if(root.left==null&&root.right==null){ 43 | list.add(root.val); 44 | } 45 | todo(root.left,list); 46 | todo(root.right,list); 47 | } 48 | } 49 | 50 | public static void main(String[] args){ 51 | TreeNode root1=TreeUtils.stringToTree("12##3##"); 52 | TreeNode root2=TreeUtils.stringToTree("13##2##"); 53 | boolean b=new Solution872().leafSimilar(root1,root2); 54 | System.out.println(b); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/leetcode/common/AMGraph.java: -------------------------------------------------------------------------------- 1 | package leetcode.common; 2 | 3 | /** 4 | * 临界矩阵存储图 5 | * @author 刘壮飞 6 | * https://github.com/zfman. 7 | * https://blog.csdn.net/lzhuangfei. 8 | */ 9 | public class AMGraph { 10 | public int[][] arcs; 11 | public int vexNum; 12 | public int arcNum; 13 | } 14 | -------------------------------------------------------------------------------- /src/leetcode/common/GraphUtils.java: -------------------------------------------------------------------------------- 1 | package leetcode.common; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public class GraphUtils { 11 | 12 | /** 13 | * 无向图输入 14 | */ 15 | public static AMGraph cin(){ 16 | Scanner scanner = new Scanner(System.in); 17 | System.out.println("顶点数 边数:"); 18 | int vexNum = scanner.nextInt(); 19 | int arcNum = scanner.nextInt(); 20 | 21 | int[] vexs = new int[vexNum + 1]; 22 | int[][] arcs = new int[vexNum + 1][vexNum + 1]; 23 | for (int i = 1; i <= vexNum; i++) { 24 | vexs[i] = i; 25 | } 26 | 27 | System.out.println("顶点1 顶点2(表示1-2有一条边):"); 28 | for (int i = 1; i <= arcNum; i++) { 29 | int pos1 = scanner.nextInt(); 30 | int pos2 = scanner.nextInt(); 31 | arcs[pos1][pos2] = 1; 32 | arcs[pos2][pos1] = 1; 33 | } 34 | 35 | AMGraph graph=new AMGraph(); 36 | graph.arcs=arcs; 37 | graph.vexNum=vexNum; 38 | graph.arcNum=arcNum; 39 | 40 | return graph; 41 | } 42 | 43 | /** 44 | * 输出 45 | * @param graph 46 | */ 47 | public static void print(AMGraph graph){ 48 | if(graph.arcs==null) return; 49 | int[][] arcs=graph.arcs; 50 | for (int i = 1; i < arcs.length; i++) { 51 | for (int j = 1; j < arcs[i].length; j++) 52 | System.out.print(arcs[i][j] + " "); 53 | System.out.println(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/leetcode/common/LinkedUtils.java: -------------------------------------------------------------------------------- 1 | package leetcode.common; 2 | 3 | /** 4 | * 链表工具类 5 | * @author 刘壮飞 6 | * https://github.com/zfman. 7 | * https://blog.csdn.net/lzhuangfei. 8 | */ 9 | public class LinkedUtils { 10 | 11 | /** 12 | * 数组转化为链表 13 | * @param array 14 | * @return 15 | */ 16 | public static ListNode arrayToLinkedList(int[] array){ 17 | if(array==null) return null; 18 | //head node 19 | ListNode root=new ListNode(-1); 20 | ListNode p=root; 21 | 22 | int size=array.length; 23 | int i=0; 24 | while(i"); 45 | } 46 | root=root.next; 47 | } 48 | System.out.println(); 49 | } 50 | } 51 | 52 | /** 53 | * 求链表长度 54 | * @param root 55 | * @return 56 | */ 57 | public static int length(ListNode root) { 58 | if(root==null) return 0; 59 | int n=0; 60 | while(root!=null){ 61 | root=root.next; 62 | n++; 63 | } 64 | return n; 65 | } 66 | 67 | /** 68 | * 返回指向链表尾部的指针 69 | * @param root 70 | * @return 71 | */ 72 | public static ListNode moveToTail(ListNode root) { 73 | if(root==null) return null; 74 | ListNode tail=root; 75 | while(tail.next!=null){ 76 | tail=tail.next; 77 | } 78 | return tail; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/leetcode/common/ListNode.java: -------------------------------------------------------------------------------- 1 | package leetcode.common; 2 | 3 | public class ListNode { 4 | public int val; 5 | public ListNode next; 6 | 7 | public ListNode(int val) { 8 | this.val=val; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/leetcode/common/OtherUtils.java: -------------------------------------------------------------------------------- 1 | package leetcode.common; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public class OtherUtils { 9 | // 最大公约数 10 | public static int get_gcd(int a, int b) { 11 | int max, min; 12 | min=Math.min(a,b); 13 | max=Math.max(a,b); 14 | 15 | if (max % min != 0) { 16 | return get_gcd(min, max % min); 17 | } else 18 | return min; 19 | 20 | } 21 | 22 | // 最小公倍数 23 | public static int get_lcm(int a, int b) { 24 | return a * b / get_gcd(a, b); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/leetcode/common/TreeNode.java: -------------------------------------------------------------------------------- 1 | package leetcode.common; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public class TreeNode { 9 | public int val; 10 | public TreeNode left; 11 | public TreeNode right; 12 | 13 | public TreeNode(int x) { 14 | val = x; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/leetcode/common/TreeUtils.java: -------------------------------------------------------------------------------- 1 | package leetcode.common; 2 | 3 | import java.util.Stack; 4 | 5 | /** 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public class TreeUtils { 11 | 12 | public static int k=0; 13 | 14 | public static int k2=0; 15 | 16 | /** 17 | * 根据string创建树:节点的值小于等于9 18 | * 19 | * 20 | * @param s 先序的序列,空使用#表示 21 | * @return 22 | */ 23 | public static TreeNode stringToTree(String s){ 24 | k=0; 25 | TreeNode root=null; 26 | root=createTree(root,s); 27 | return root; 28 | } 29 | 30 | private static TreeNode createTree(TreeNode node,String s){ 31 | char ch=s.charAt(k++); 32 | if(ch=='#') return null; 33 | else{ 34 | node=new TreeNode(ch-'0'); 35 | node.left=createTree(node.left,s); 36 | node.right=createTree(node.right,s); 37 | return node; 38 | } 39 | } 40 | 41 | /** 42 | * 符号以空格分隔,节点上的值可以大于9 43 | * @param str 44 | * @return 45 | */ 46 | public static TreeNode stringToTreeWith(String str,String separator){ 47 | k2=0; 48 | TreeNode root=null; 49 | String[] arr=str.trim().split(separator); 50 | root=createTreeWith(root,arr); 51 | return root; 52 | } 53 | 54 | private static TreeNode createTreeWith(TreeNode node,String[] arr){ 55 | String v=arr[k2++]; 56 | if(v.equals("#")) return null; 57 | else{ 58 | node=new TreeNode(Integer.valueOf(v)); 59 | node.left=createTreeWith(node.left,arr); 60 | node.right=createTreeWith(node.right,arr); 61 | return node; 62 | } 63 | } 64 | 65 | /** 66 | * 先序遍历 67 | * @param root 68 | */ 69 | public static void travser(TreeNode root){ 70 | if(root!=null){ 71 | System.out.print(root.val+" "); 72 | travser(root.left); 73 | travser(root.right); 74 | } 75 | } 76 | 77 | /** 78 | * 中序遍历 79 | * @param root 80 | */ 81 | public static void travser2(TreeNode root){ 82 | if(root!=null){ 83 | travser2(root.left); 84 | System.out.print(root.val+" "); 85 | travser2(root.right); 86 | } 87 | } 88 | 89 | /** 90 | * 后序遍历 91 | * @param root 92 | */ 93 | public static void travser3(TreeNode root){ 94 | if(root!=null){ 95 | travser3(root.left); 96 | travser3(root.right); 97 | System.out.print(root.val+" "); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/masai/GuShen.java: -------------------------------------------------------------------------------- 1 | package masai; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * 有股神吗? 7 | * 8 | * 有,小赛就是! 9 | * 10 | * 经过严密的计算,小赛买了一支股票,他知道从他买股票的那天开始,股票会有以下变化:第一天不变,以后涨一天,跌一天,涨两天,跌一天,涨三天,跌一天...依此类推。 11 | * 12 | * 为方便计算,假设每次涨和跌皆为1,股票初始单价也为1,请计算买股票的第n天每股股票值多少钱? 13 | * 14 | * 15 | * 16 | * 输入 17 | * 输入包括多组数据; 18 | * 19 | * 每行输入一个n,1<=n<=10^9 。 20 | * 21 | * 样例输入 22 | * 1 23 | * 24 | * 2 25 | * 26 | * 3 27 | * 28 | * 4 29 | * 30 | * 5 31 | * 32 | * 输出 33 | * 请输出他每股股票多少钱,对于每组数据,输出一行。 34 | * 35 | * 样例输出 36 | * 1 37 | * 38 | * 2 39 | * 40 | * 1 41 | * 42 | * 2 43 | * 44 | * 3 45 | * 46 | * 时间限制 47 | * C/C++语言:1000MS其它语言:3000MS 48 | * 内存限制 49 | * C/C++语言:65536KB其它语言:589824KB 50 | * 51 | * 52 | */ 53 | public class GuShen { 54 | 55 | public static int doThing(int n){ 56 | int i=0,k=2,j=2; 57 | while(kn){ 34 | while(klist1.val){ 23 | tmp.next=list1; 24 | tmp=tmp.next; 25 | list1=list1.next; 26 | }else { 27 | tmp.next=list2; 28 | tmp=tmp.next; 29 | list2=list2.next; 30 | } 31 | } 32 | 33 | if(list1==null){ 34 | tmp.next=list2; 35 | } 36 | if(list2==null){ 37 | tmp.next=list1; 38 | } 39 | return list3.next; 40 | } 41 | 42 | public static void main(String[] args){ 43 | int[] arr1={ 44 | 4,8,9 45 | }; 46 | int[] arr2={ 47 | 1,6,7 48 | }; 49 | ListNode list1=LinkedUtils.arrayToLinkedList(arr1); 50 | ListNode list2=LinkedUtils.arrayToLinkedList(arr2); 51 | 52 | ListNode r=new MergeSolution().Merge(list1,list2); 53 | LinkedUtils.print(r); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/offer/MirrorSolution.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | 3 | import leetcode.common.TreeNode; 4 | import leetcode.common.TreeUtils; 5 | 6 | /** 7 | * 二叉树的镜像 8 | * 9 | * 操作给定的二叉树,将其变换为源二叉树的镜像。 10 | * 输入描述: 11 | * 二叉树的镜像定义:源二叉树 12 | * 8 13 | * / \ 14 | * 6 10 15 | * / \ / \ 16 | * 5 7 9 11 17 | * 18 | * 镜像二叉树 19 | * 8 20 | * / \ 21 | * 10 6 22 | * / \ / \ 23 | * 11 9 7 5 24 | * 25 | * 26 | * @author 刘壮飞 27 | * https://github.com/zfman. 28 | * https://blog.csdn.net/lzhuangfei. 29 | */ 30 | public class MirrorSolution { 31 | public void Mirror(TreeNode root) { 32 | if(root!=null){ 33 | TreeNode tmp=root.left; 34 | root.left=root.right; 35 | root.right=tmp; 36 | 37 | Mirror(root.left); 38 | Mirror(root.right); 39 | } 40 | } 41 | 42 | public static void main(String[] args){ 43 | String str="8,6,5,#,#,7,#,#,10,9,#,#,11,#,#"; 44 | TreeNode root=TreeUtils.stringToTreeWith(str,","); 45 | new MirrorSolution().Mirror(root); 46 | TreeUtils.travser(root); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/offer/ReOrderArraySolution.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | 3 | import utils.ArrayUtils; 4 | 5 | /** 6 | * 调整数组顺序使奇数位于偶数前面 7 | * 8 | * 输入一个整数数组,实现一个函数来调整该数组中数字的顺序, 9 | * 使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分, 10 | * 并保证奇数和奇数,偶数和偶数之间的相对位置不变。 11 | * 12 | * @author 刘壮飞 13 | * https://github.com/zfman. 14 | * https://blog.csdn.net/lzhuangfei. 15 | */ 16 | public class ReOrderArraySolution { 17 | public void reOrderArray(int [] array) { 18 | int n=array.length; 19 | int k=0;//已排好的奇数位置 20 | for(int i=0;ik){ 24 | int tmp=array[j]; 25 | array[j]=array[j-1]; 26 | array[j-1]=tmp; 27 | j--; 28 | } 29 | k++; 30 | } 31 | } 32 | } 33 | 34 | public static void main(String[] args){ 35 | //output:1,3,5,7,2,4,6 36 | int[] array={ 37 | 1,2,3,4,5,6,7 38 | }; 39 | new ReOrderArraySolution().reOrderArray(array); 40 | ArrayUtils.printArray(array); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/offer/RectCoverSolution.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | 3 | /** 4 | * 矩形覆盖 5 | * 6 | * 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。 7 | * 请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 8 | * 9 | * @author 刘壮飞 10 | * https://github.com/zfman. 11 | * https://blog.csdn.net/lzhuangfei. 12 | */ 13 | public class RectCoverSolution { 14 | public int RectCover(int target) { 15 | if(target==0) return 0; 16 | if(target==1||target==2) return target; 17 | int i=3; 18 | int tmp1=1; 19 | int tmp2=2; 20 | int v=0; 21 | while (i<=target){ 22 | v=tmp1+tmp2; 23 | tmp1=tmp2; 24 | tmp2=v; 25 | i++; 26 | } 27 | return v; 28 | } 29 | 30 | public static void main(String[] args) { 31 | int target=4; 32 | int r = new RectCoverSolution().RectCover(target); 33 | System.out.println(r); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/offer/ReverseListSolution.java: -------------------------------------------------------------------------------- 1 | package offer; 2 | 3 | import leetcode.common.LinkedUtils; 4 | import leetcode.common.ListNode; 5 | import sort.ArrayUtils; 6 | 7 | /** 8 | * 反转链表 9 | * 10 | * 输入一个链表,反转链表后,输出新链表的表头。 11 | * 12 | * @author 刘壮飞 13 | * https://github.com/zfman. 14 | * https://blog.csdn.net/lzhuangfei. 15 | */ 16 | public class ReverseListSolution { 17 | public ListNode ReverseList(ListNode head) { 18 | if(head==null) return null; 19 | //pr:指向要反转的下一个元素 20 | //p:指向当前正在反转的元素 21 | //q:指向上一个反转的元素 22 | ListNode pr=head,p=head,q=null; 23 | while (pr!=null){ 24 | pr=p.next; 25 | p.next=q; 26 | q=p; 27 | p=pr; 28 | } 29 | 30 | head=q; 31 | return head; 32 | } 33 | 34 | public static void main(String[] args){ 35 | int[] array={ 36 | 1,2,3,4,5,6 37 | }; 38 | ListNode head=LinkedUtils.arrayToLinkedList(array); 39 | ListNode r=new ReverseListSolution().ReverseList(head); 40 | LinkedUtils.print(r); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/other/Baicizhan1.java: -------------------------------------------------------------------------------- 1 | package other; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | import java.util.Scanner; 7 | 8 | /** 9 | * 时间相关 10 | * 给定两个时间,计算时针、分针、秒针走过的角度 11 | */ 12 | public class Baicizhan1 { 13 | public static void main(String[] args){ 14 | SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 15 | try { 16 | Scanner scanner=new Scanner(System.in); 17 | String str1=scanner.nextLine(); 18 | String str2=scanner.nextLine(); 19 | 20 | Date date1=sdf.parse("2018-09-20 "+str1); 21 | Date date2=sdf.parse("2018-09-20 "+str2); 22 | 23 | long d=date2.getTime()-date1.getTime(); 24 | 25 | double hv=d/120000; 26 | double mv=d/10000; 27 | double mmv=d/1000*6; 28 | System.out.println((int)hv); 29 | System.out.println((int)mv); 30 | System.out.println((int)mmv); 31 | } catch (ParseException e) { 32 | e.printStackTrace(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/other/Baicizhan2.java: -------------------------------------------------------------------------------- 1 | package other; 2 | 3 | import utils.ArrayUtils; 4 | 5 | import java.util.Scanner; 6 | 7 | /** 8 | * 合并数字(未完成) 9 | * 连续三个数字以及以上可合并 10 | * 6 11 | * 1 2 3 4 6 7 12 | * 13 | * 输出:1-4 6 7 14 | */ 15 | public class Baicizhan2 { 16 | public static void main(String[] args) { 17 | Scanner in = new Scanner(System.in); 18 | // int n=in.nextInt(); 19 | // int[] arr=new int[n]; 20 | // for(int i=0;i25){ 49 | charIndex-=26; 50 | } 51 | return (char) (charIndex+65); 52 | } 53 | 54 | public static void main(String[] args){ 55 | Scanner scanner=new Scanner(System.in); 56 | String str=scanner.nextLine(); 57 | System.out.println(todo(str)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/other/Baidu2.java: -------------------------------------------------------------------------------- 1 | package other; 2 | 3 | /** 4 | * 生日蛋糕(未完成) 5 | * 时间限制:C/C++语言 1000MS;其他语言 3000MS 6 | * 内存限制:C/C++语言 65536KB;其他语言 589824KB 7 | * 题目描述: 8 | * 今天是明明的生日,他买了一个长方体形状的水果蛋糕,其顶面是N*M的矩阵,其中k*k个格子各有一片水果,参加他的生日派对的也有k*k个人,所以他要顺着矩阵的边线横着切k-1刀,竖着也切k-1刀,把蛋糕分成k*k份,每一份包含一片水果。请问他应该怎么切。 9 | * 10 | * 输入 11 | * 第一行三个整数N,M,k。(2≤k≤N, M≤50) 12 | * 13 | * 接下来k*k行,每行两个整数x,y,表示在蛋糕顶面的第x行第y列有一片水果。(1≤x≤N, 1≤y≤M)。数据保证不存在相同的 (x, y)。 14 | * 15 | * 输出 16 | * 第一行k-1个整数,每两个数之间用空格隔开,第i个数Ai表示应该在第Ai行和第Ai+1行之间切一刀。 17 | * 18 | * 第二行k-1个整数,每两个数之间用空格隔开,第i个数Bi表示应该在第Bi列和第Bi+1列之间切一刀。 19 | * 20 | * 如果有多种切法,输出字典序最小的那种。数据保证有解。输出的每一行的末尾不应有多余的空格。 21 | * 22 | * 23 | * 样例输入 24 | * 4 4 2 25 | * 1 4 26 | * 2 2 27 | * 3 1 28 | * 3 3 29 | * 样例输出 30 | * 2 31 | * 2 32 | * 33 | * Hint 34 | * 样例解释 35 | * 00|01 36 | * 01|00 37 | * --+-- 38 | * 10|10 39 | * 00|00 40 | * 41 | * @author 刘壮飞 42 | * https://github.com/zfman. 43 | * https://blog.csdn.net/lzhuangfei. 44 | */ 45 | public class Baidu2 { 46 | } 47 | -------------------------------------------------------------------------------- /src/other/Baidu3.java: -------------------------------------------------------------------------------- 1 | package other; 2 | 3 | /** 4 | * B序(未完成) 5 | * 时间限制:C/C++语言 1000MS;其他语言 3000MS 6 | * 内存限制:C/C++语言 65536KB;其他语言 589824KB 7 | * 题目描述: 8 | * 你有1-n共n个数字可以使用,每个数字的使用次数无限制,显然共有n^n个不同的长度为n的序列。其中所有不上升序列和不下降序列统称为B序,给定n,问长度同样为n的b序有多少个,因为结果比较大,请输出答案对1000000007取模之后的结果。 9 | * 10 | * 不上升序列:从序列第二个数字开始,均小于等于前一个数字。 11 | * 12 | * 不下降序列:从序列第二个数字开始,均大于等于前一个数字。 13 | * 14 | * 输入 15 | * 输入仅包含一个正整数n(1<=n<=10^5)。 16 | * 17 | * 输出描述 18 | * 19 | * 输出 20 | * 输出仅包含一个正整数,表示答案对1000000007取模的结果。 21 | * 22 | * 23 | * 样例输入 24 | * 2 25 | * 样例输出 26 | * 4 27 | * 28 | * Hint 29 | * 输入样例2 30 | * 3 31 | * 输出样例2 32 | * 17 33 | * 34 | * @author 刘壮飞 35 | * https://github.com/zfman. 36 | * https://blog.csdn.net/lzhuangfei. 37 | */ 38 | public class Baidu3 { 39 | } 40 | -------------------------------------------------------------------------------- /src/other/GraphTest.java: -------------------------------------------------------------------------------- 1 | package other; 2 | 3 | import leetcode.common.AMGraph; 4 | import leetcode.common.GraphUtils; 5 | import utils.ArrayUtils; 6 | 7 | import java.util.LinkedList; 8 | import java.util.Queue; 9 | import java.util.Scanner; 10 | import java.util.Stack; 11 | 12 | /** 13 | * @author 刘壮飞 14 | * https://github.com/zfman. 15 | * https://blog.csdn.net/lzhuangfei. 16 | */ 17 | public class GraphTest { 18 | public static void main(String[] args) { 19 | AMGraph graph=GraphUtils.cin(); 20 | boolean[] visited=new boolean[graph.vexNum+1]; 21 | // dfs(graph,1,visited); 22 | // GraphUtils.print(graph); 23 | 24 | Queue queue=new LinkedList<>(); 25 | bfs(graph,5,visited,queue); 26 | } 27 | 28 | /** 29 | * 连通图的深度优先遍历,对于非连通图, 30 | * 应该依次将顶点作为遍历的起始点 31 | * 32 | * @param graph 图 33 | * @param v 访问的顶点 34 | * @param visited 访问标志数组 35 | */ 36 | public static void dfs(AMGraph graph, int v, boolean[] visited){ 37 | System.out.println("visited::"+v); 38 | visited[v]=true; 39 | for(int i=1;i<=graph.vexNum;i++){ 40 | if(graph.arcs[v][i]!=0&&!visited[i]) dfs(graph,i,visited); 41 | } 42 | } 43 | 44 | /** 45 | * 图的广度优先遍历 46 | * 47 | * @param graph 图 48 | * @param v 起始顶点 49 | * @param visited 访问标志数组 50 | * @param queue 队列 51 | */ 52 | public static void bfs(AMGraph graph, int v, boolean[] visited,Queue queue){ 53 | if(!visited[v]){ 54 | visited[v]=true; 55 | System.out.println("visited::"+v); 56 | queue.offer(v); 57 | } 58 | while (!queue.isEmpty()){ 59 | Integer pop=queue.poll(); 60 | if(!visited[pop]){ 61 | visited[pop]=true; 62 | System.out.println("visited::"+pop); 63 | } 64 | for(int i=1;i<=graph.vexNum;i++){ 65 | if(graph.arcs[pop][i]!=0&&!visited[i]){ 66 | queue.offer(i); 67 | } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/other/Mogujie1.java: -------------------------------------------------------------------------------- 1 | package other; 2 | 3 | 4 | import java.util.Scanner; 5 | 6 | /** 7 | * 蘑菇街-网格路径数(未完成) 8 | * 给定网格x*y,求解从左上角到右下角的路径数,每次只能向右或向下移动一格 9 | * 10 | * input: 11 | * 3 2 12 | * 13 | * output: 14 | * 10 15 | * 16 | * @author 刘壮飞 17 | * https://github.com/zfman. 18 | * https://blog.csdn.net/lzhuangfei. 19 | */ 20 | public class Mogujie1 { 21 | public static void main(String[] args){ 22 | Scanner scanner=new Scanner(System.in); 23 | int x=scanner.nextInt(); 24 | int y=scanner.nextInt(); 25 | 26 | int X=x+y-2; 27 | int r=x-1; 28 | double ret=1.0; 29 | for(int i=1;i<=x-1;i++){ 30 | ret=ret*(X-r+i)/i; 31 | } 32 | System.out.println((int)ret); 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/other/Mogujie2.java: -------------------------------------------------------------------------------- 1 | package other; 2 | 3 | import utils.ArrayUtils; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Collections; 7 | import java.util.List; 8 | import java.util.Scanner; 9 | 10 | /** 11 | * 蘑菇街 - 分词(未完成) 12 | * 13 | * 第一行是一个字符串,第二行是字典逗号分隔每一个词, 14 | * 输出分词结果,有多种分词结果使用逗号分隔 15 | * 16 | * input: 17 | * catsanddog 18 | * cat,cats,and,sand,dog 19 | * 20 | * output: 21 | * [cats and dog,cat sand dog] 22 | * 23 | * @author 刘壮飞 24 | * https://github.com/zfman. 25 | * https://blog.csdn.net/lzhuangfei. 26 | */ 27 | public class Mogujie2 { 28 | public static void main(String[] args){ 29 | Scanner scanner=new Scanner(System.in); 30 | String ling1=scanner.nextLine(); 31 | String line2=scanner.nextLine(); 32 | String[] arr=line2.substring(7,line2.length()-1).split(","); 33 | List list=new ArrayList<>(); 34 | for(int i=0;i1&&arr[1].equals(name)){ 29 | is=true; 30 | System.out.println(content); 31 | }else is=false; 32 | }else{ 33 | if(is) System.out.println(content); 34 | } 35 | } 36 | } 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/other/ShenCe1.java: -------------------------------------------------------------------------------- 1 | package other; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * 把陀峰命名改为下划线命名 7 | * 输入: 8 | * SensorsData 9 | * 10 | * 输出: 11 | * sensors_data 12 | */ 13 | public class ShenCe1 { 14 | public static void main(String[] args){ 15 | Scanner scanner=new Scanner(System.in); 16 | String str=scanner.nextLine(); 17 | String ret=""; 18 | for(int i=0;i='A'&&ch<='Z')){ 21 | char tmp=(char)((int)ch+32); 22 | if(i==0){ 23 | ret+=tmp; 24 | }else{ 25 | ret+="_"+tmp; 26 | } 27 | }else{ 28 | ret+=ch; 29 | } 30 | } 31 | System.out.println(ret); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/other/ShenCe2.java: -------------------------------------------------------------------------------- 1 | package other; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | import java.util.Scanner; 7 | 8 | /** 9 | * 神策数据 10 | * 输入两行,第一行为时钟,第二行是经过的时间,输入时钟显示的结果 11 | * 12 | * 输入: 13 | * 10:00:00 14 | * 00:11:12 15 | * 16 | * 输出: 17 | * 10:11:12 18 | * 19 | */ 20 | public class ShenCe2 { 21 | public static void main(String[] args){ 22 | Scanner scanner=new Scanner(System.in); 23 | String line1=scanner.nextLine(); 24 | String line2=scanner.nextLine(); 25 | SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 26 | SimpleDateFormat sdf2=new SimpleDateFormat("HH:mm:ss"); 27 | try { 28 | Date date1=sdf.parse("2018-09-21 "+line1); 29 | Date date2=sdf.parse("2018-09-21 "+line2); 30 | Date date3=sdf.parse("2018-09-21 00:00:00"); 31 | Date date4=new Date(date1.getTime()+(date2.getTime()-date3.getTime())); 32 | String ret=sdf2.format(date4); 33 | System.out.println(ret); 34 | } catch (ParseException e) { 35 | e.printStackTrace(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/other/ShenCeInterview1.java: -------------------------------------------------------------------------------- 1 | package other; 2 | 3 | /** 4 | * 神策数据 面试手写算法题1 - 折半查找的实现 5 | * 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public class ShenCeInterview1 { 11 | public int find(int[] arr,int l,int r,int val){ 12 | if(l>r) return -1; 13 | int middle=(l+r)/2; 14 | if(val>arr[middle]) return find(arr,middle+1,r,val); 15 | else if(valmax) max=arr[i]; 21 | } 22 | 23 | // 下标保存数字 24 | // 元素值保存的是次数 25 | // java int[] 元素默认为0 26 | int[] b=new int[max+1]; 27 | for(int i=0;i set=new HashSet<>(); 19 | for(Integer val:arr){ 20 | set.add(val); 21 | } 22 | int[] newArr=new int[set.size()]; 23 | int i=0; 24 | for(Integer val:set){ 25 | newArr[i++]=val; 26 | } 27 | for(int t=0;t list=new ArrayList<>(); 40 | for(int i=0;imax) max=list.size(); 48 | list.clear(); 49 | break; 50 | } 51 | } 52 | if(list.size()>max) max=list.size(); 53 | } 54 | return max; 55 | } 56 | /******************************结束写代码******************************/ 57 | 58 | 59 | public static void main(String[] args){ 60 | Scanner in = new Scanner(System.in); 61 | int res; 62 | 63 | String _s; 64 | try { 65 | _s = in.nextLine(); 66 | } catch (Exception e) { 67 | _s = null; 68 | } 69 | 70 | res = lengthOfSubstring(_s); 71 | System.out.println(String.valueOf(res)); 72 | 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /src/other/XunleiTest1.java: -------------------------------------------------------------------------------- 1 | package other; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * 求数列的和 7 | * 8 | * (编程题须知)(参考答案) 9 | * 10 | * 时间限制:C/C++语言 2000MS;其他语言 4000MS 11 | * 内存限制:C/C++语言 32768KB;其他语言 557056KB 12 | * 题目描述: 13 | * 数列的定义如下: 数列的第一项为n,以后各项为前一项的平方根,求数列的前m项的和。 14 | * 15 | * 输入 16 | * 输入数据有多组,每组占一行,由两个整数n(n<10000)和m(m<1000)组成,n和m的含义如前所述。 17 | * 18 | * 输出 19 | * 对于每组输入数据,输出该数列的和,每个测试实例占一行,要求精度保留2位小数。 20 | * 21 | * 22 | * 样例输入 23 | * 81 4 24 | * 2 2 25 | * 26 | * 样例输出 27 | * 94.73 28 | * 3.41 29 | * 30 | * @author 刘壮飞 31 | * https://github.com/zfman. 32 | * https://blog.csdn.net/lzhuangfei. 33 | */ 34 | public class XunleiTest1 { 35 | public static void main(String[] args){ 36 | Scanner scanner=new Scanner(System.in); 37 | while (scanner.hasNextInt()){ 38 | int first=scanner.nextInt(); 39 | int c=scanner.nextInt(); 40 | double p=first; 41 | double s=p; 42 | for(int i=1;i generateParenthesis(int n){ 33 | List ret=new ArrayList<>(); 34 | dfs(n,0,0,"",ret); 35 | return ret; 36 | } 37 | 38 | /** 39 | * 深度优先 40 | * 41 | * 1.如果满足条件,将当前str保存,否则继续 42 | * 2.左括号小于n,继续添加左括号 43 | * 3.右括号小于n&左括号大于右括号,补充右括号 44 | * 45 | * @param n 46 | * @param l 左括号数量 47 | * @param r 右括号数量 48 | * @param str 本轮次的字符串 49 | * @param ret 保存所有结果 50 | */ 51 | public void dfs(int n,int l,int r,String str,List ret){ 52 | if(l>=n&&r>=n) { 53 | ret.add(str); 54 | return; 55 | } 56 | if(lr&&r r=new ZhaoShang2018_1().generateParenthesis(3); 66 | for (String s:r){ 67 | System.out.println(s); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/pattern/chain/AbstractLogger.java: -------------------------------------------------------------------------------- 1 | package pattern.chain; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public abstract class AbstractLogger { 9 | public static final int LOG_ERROR=1; 10 | public static final int LOG_DEBUG=2; 11 | public static final int LOG_INFO=3; 12 | protected int level; 13 | protected AbstractLogger nextLogger; 14 | 15 | public abstract void write(String msg); 16 | 17 | public void logMessage(int level,String msg){ 18 | if(this.level<=level){ 19 | write(msg); 20 | } 21 | if(nextLogger!=null){ 22 | nextLogger.logMessage(level,msg); 23 | } 24 | } 25 | 26 | public void setNextLogger(AbstractLogger nextLogger) { 27 | this.nextLogger = nextLogger; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/pattern/chain/Client.java: -------------------------------------------------------------------------------- 1 | package pattern.chain; 2 | 3 | /** 4 | * 职责链模式 5 | * 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public class Client { 11 | public static void main(String[] args){ 12 | AbstractLogger errorLogger=new ErrorLogger(AbstractLogger.LOG_ERROR); 13 | AbstractLogger debugLogger=new FileLogger(AbstractLogger.LOG_DEBUG); 14 | AbstractLogger infoLogger=new ConsoleLogger(AbstractLogger.LOG_INFO); 15 | 16 | errorLogger.setNextLogger(debugLogger); 17 | debugLogger.setNextLogger(infoLogger); 18 | 19 | errorLogger.logMessage(AbstractLogger.LOG_INFO,"hello info"); 20 | errorLogger.logMessage(AbstractLogger.LOG_DEBUG,"hello debug"); 21 | errorLogger.logMessage(AbstractLogger.LOG_ERROR,"hello error"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/pattern/chain/ConsoleLogger.java: -------------------------------------------------------------------------------- 1 | package pattern.chain; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public class ConsoleLogger extends AbstractLogger { 9 | public ConsoleLogger(int level){ 10 | this.level=level; 11 | } 12 | @Override 13 | public void write(String msg) { 14 | System.out.println("ConsoleLogger::"+msg); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/pattern/chain/ErrorLogger.java: -------------------------------------------------------------------------------- 1 | package pattern.chain; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public class ErrorLogger extends AbstractLogger { 9 | public ErrorLogger(int level){ 10 | this.level=level; 11 | } 12 | @Override 13 | public void write(String msg) { 14 | System.out.println("ErrorLogger::"+msg); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/pattern/chain/FileLogger.java: -------------------------------------------------------------------------------- 1 | package pattern.chain; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public class FileLogger extends AbstractLogger { 9 | 10 | public FileLogger(int level){ 11 | this.level=level; 12 | } 13 | @Override 14 | public void write(String msg) { 15 | System.out.println("FileLogger::"+msg); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/pattern/command/BuyStock.java: -------------------------------------------------------------------------------- 1 | package pattern.command; 2 | 3 | /** 4 | * buyStock 命令 5 | * 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public class BuyStock implements Order { 11 | Stock stock; 12 | public BuyStock(Stock stock){ 13 | this.stock=stock; 14 | } 15 | @Override 16 | public void execute() { 17 | stock.buy(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/pattern/command/Client.java: -------------------------------------------------------------------------------- 1 | package pattern.command; 2 | 3 | /** 4 | * 命令模式 5 | * 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public class Client { 11 | public static void main(String[] args){ 12 | Stock stock=new Stock(); 13 | BuyStock buyStock=new BuyStock(stock); 14 | SellStock sellStock=new SellStock(stock); 15 | 16 | Invoker invoker=new Invoker(); 17 | invoker.takeOrder(buyStock); 18 | invoker.takeOrder(sellStock); 19 | invoker.placeOrders(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/pattern/command/Invoker.java: -------------------------------------------------------------------------------- 1 | package pattern.command; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 命令调用者 8 | * @author 刘壮飞 9 | * https://github.com/zfman. 10 | * https://blog.csdn.net/lzhuangfei. 11 | */ 12 | public class Invoker { 13 | public List orders=new ArrayList<>(); 14 | 15 | public void takeOrder(Order o){ 16 | orders.add(o); 17 | } 18 | 19 | public void placeOrders(){ 20 | for(Order o:orders){ 21 | o.execute(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/pattern/command/Order.java: -------------------------------------------------------------------------------- 1 | package pattern.command; 2 | 3 | /** 4 | * 命令的抽象接口 5 | * 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public interface Order { 11 | void execute(); 12 | } 13 | -------------------------------------------------------------------------------- /src/pattern/command/SellStock.java: -------------------------------------------------------------------------------- 1 | package pattern.command; 2 | 3 | /** 4 | * sellStock命令 5 | * 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public class SellStock implements Order{ 11 | Stock stock; 12 | public SellStock(Stock stock){ 13 | this.stock=stock; 14 | } 15 | 16 | @Override 17 | public void execute() { 18 | stock.sell(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/pattern/command/Stock.java: -------------------------------------------------------------------------------- 1 | package pattern.command; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public class Stock { 9 | public String name="aa"; 10 | public float quantity=4.0f; 11 | 12 | public void buy(){ 13 | System.out.println("buy::"+name+","+quantity); 14 | } 15 | 16 | public void sell(){ 17 | System.out.println("sell::"+name+","+quantity); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/pattern/iterator/Client.java: -------------------------------------------------------------------------------- 1 | package pattern.iterator; 2 | 3 | /** 4 | * 迭代器模式 5 | * @author 刘壮飞 6 | * https://github.com/zfman. 7 | * https://blog.csdn.net/lzhuangfei. 8 | */ 9 | public class Client { 10 | public static void main(String[] args){ 11 | NameRepository repository=new NameRepository(); 12 | Iterator iterator=repository.iterator(); 13 | while (iterator.hasNext()){ 14 | System.out.println(iterator.next()); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/pattern/iterator/Container.java: -------------------------------------------------------------------------------- 1 | package pattern.iterator; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public interface Container { 9 | Iterator iterator(); 10 | } 11 | -------------------------------------------------------------------------------- /src/pattern/iterator/Iterator.java: -------------------------------------------------------------------------------- 1 | package pattern.iterator; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public interface Iterator { 9 | public boolean hasNext(); 10 | public Object next(); 11 | } 12 | -------------------------------------------------------------------------------- /src/pattern/iterator/NameRepository.java: -------------------------------------------------------------------------------- 1 | package pattern.iterator; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public class NameRepository implements Container { 9 | 10 | public String names[] = {"Robert" , "John" ,"Julie" , "Lora"}; 11 | 12 | @Override 13 | public Iterator iterator() { 14 | return new NameIterator(); 15 | } 16 | 17 | class NameIterator implements Iterator{ 18 | int index; 19 | @Override 20 | public boolean hasNext() { 21 | if(index mementos=new ArrayList<>(); 13 | public void add(Memento memento){ 14 | mementos.add(memento); 15 | } 16 | public Memento get(int i){ 17 | return mementos.get(i); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/pattern/memento/Client.java: -------------------------------------------------------------------------------- 1 | package pattern.memento; 2 | 3 | /** 4 | * 备忘录模式 5 | * @author 刘壮飞 6 | * https://github.com/zfman. 7 | * https://blog.csdn.net/lzhuangfei. 8 | */ 9 | public class Client { 10 | public static void main(String[] args){ 11 | Originator originator=new Originator(); 12 | originator.setState("State 1"); 13 | System.out.println(originator.getState()); 14 | 15 | CareTaker taker=new CareTaker(); 16 | taker.add(originator.saveState()); 17 | 18 | originator.setState("State 2"); 19 | taker.add(originator.saveState()); 20 | System.out.println(originator.getState()); 21 | 22 | originator.restoreFromState(taker.get(0)); 23 | System.out.println(originator.getState()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/pattern/memento/Memento.java: -------------------------------------------------------------------------------- 1 | package pattern.memento; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public class Memento { 9 | private String state; 10 | 11 | public Memento(String state){ 12 | this.state=state; 13 | } 14 | 15 | public String getState() { 16 | return state; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/pattern/memento/Originator.java: -------------------------------------------------------------------------------- 1 | package pattern.memento; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public class Originator { 9 | String state; 10 | 11 | public void setState(String state) { 12 | this.state = state; 13 | } 14 | 15 | public String getState() { 16 | return state; 17 | } 18 | 19 | public Memento saveState(){ 20 | return new Memento(state); 21 | } 22 | 23 | public void restoreFromState(Memento memento){ 24 | this.state=memento.getState(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/pattern/observer/Client.java: -------------------------------------------------------------------------------- 1 | package pattern.observer; 2 | 3 | /** 4 | * 观察者模式 5 | * @author 刘壮飞 6 | * https://github.com/zfman. 7 | * https://blog.csdn.net/lzhuangfei. 8 | */ 9 | public class Client { 10 | public static void main(String[] args){ 11 | Subject subject=new Subject(); 12 | new Observer1(subject); 13 | new Observer2(subject); 14 | 15 | subject.setState("New State"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/pattern/observer/Observer.java: -------------------------------------------------------------------------------- 1 | package pattern.observer; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public abstract class Observer { 9 | protected Subject subject; 10 | abstract void update(); 11 | } 12 | -------------------------------------------------------------------------------- /src/pattern/observer/Observer1.java: -------------------------------------------------------------------------------- 1 | package pattern.observer; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public class Observer1 extends Observer { 9 | public Observer1(Subject subject){ 10 | this.subject=subject; 11 | this.subject.attach(this); 12 | } 13 | @Override 14 | public void update() { 15 | System.out.println("Observer1::update"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/pattern/observer/Observer2.java: -------------------------------------------------------------------------------- 1 | package pattern.observer; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public class Observer2 extends Observer { 9 | public Observer2(Subject subject){ 10 | this.subject=subject; 11 | this.subject.attach(this); 12 | } 13 | @Override 14 | public void update() { 15 | System.out.println("Observer2::update"); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/pattern/observer/Subject.java: -------------------------------------------------------------------------------- 1 | package pattern.observer; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * @author 刘壮飞 8 | * https://github.com/zfman. 9 | * https://blog.csdn.net/lzhuangfei. 10 | */ 11 | public class Subject { 12 | List observers=new ArrayList<>(); 13 | String state; 14 | 15 | public void setState(String state) { 16 | this.state = state; 17 | onNotify(); 18 | } 19 | 20 | public String getState() { 21 | return state; 22 | } 23 | 24 | public void attach(Observer observer){ 25 | observers.add(observer); 26 | } 27 | 28 | public void onNotify(){ 29 | for(Observer observer:observers){ 30 | observer.update(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/sort/ArrayUtils.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public class ArrayUtils { 9 | public static void printArray(T[] a){ 10 | if(a==null) return; 11 | for(int i=0;i void printArray(T[] a,int start){ 18 | if(a==null) return; 19 | for(int i=start;i> extends Sort { 14 | @Override 15 | public void sort(T[] nums) { 16 | int n=nums.length; 17 | for(int i=0;i sort=new Buddle<>(); 31 | sort.sort(arr); 32 | ArrayUtils.printArray(arr); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/sort/Buddle2.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | /** 4 | * 冒泡排序的改进 5 | * 6 | * 通过从左到右不断交换相邻逆序的相邻元素, 7 | * 在一轮的交换之后,可以让未排序的元素上浮到右侧。 8 | * 9 | * 在一轮循环中,如果没有发生交换,就说明数组已经是有序的,此时可以直接退出。 10 | * 11 | * @author 刘壮飞 12 | * https://github.com/zfman. 13 | * https://blog.csdn.net/lzhuangfei. 14 | */ 15 | public class Buddle2> extends Sort { 16 | @Override 17 | public void sort(T[] nums) { 18 | int n=nums.length; 19 | boolean hasSort=false; 20 | for(int i=0;i sort=new Buddle2<>(); 36 | sort.sort(arr); 37 | ArrayUtils.printArray(arr); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/sort/DownToUpMergeSort.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | /** 4 | * 自底向上归并排序 5 | * 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public class DownToUpMergeSort> extends MergeSort { 11 | 12 | /** 13 | * 先归并那些微型数组,然后成对归并得到的微型数组。 14 | * 15 | * @param nums 16 | */ 17 | @Override 18 | public void sort(T[] nums) { 19 | int n = nums.length; 20 | tmp = (T[]) new Comparable[n]; 21 | for (int i = 1; i < n; i += i) 22 | for (int j = 0; j < n - i; j += i + i) 23 | merge(nums, j, j + i - 1, Math.min(j + i + i - 1, n - 1)); 24 | } 25 | 26 | public static void main(String[] args) { 27 | Integer[] arr = { 28 | 5, 1, 8, 7, 10, 6, 9, 5, 20, 3, 0 29 | }; 30 | Sort sort = new DownToUpMergeSort<>(); 31 | sort.sort(arr); 32 | ArrayUtils.printArray(arr); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/sort/Heap.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public class Heap> { 9 | 10 | private T[] heap; 11 | private int n=0; 12 | 13 | public Heap(int maxNum){ 14 | n=maxNum; 15 | } 16 | 17 | public boolean isEmpty(){ 18 | return n==0; 19 | } 20 | 21 | protected boolean less(int i,int j){ 22 | return heap[i].compareTo(heap[j])<0; 23 | } 24 | 25 | protected void swap(int i,int j){ 26 | T t=heap[i]; 27 | heap[i]=heap[j]; 28 | heap[j]=t; 29 | } 30 | 31 | /** 32 | * 上浮 33 | * @param k 34 | */ 35 | protected void swim(int k){ 36 | while (k>1&&less(k/2,k)){ 37 | swap(k/2,k); 38 | k=k/2; 39 | } 40 | } 41 | 42 | /** 43 | * 下沉 44 | * @param k 45 | */ 46 | protected void sink(int k){ 47 | while (2*k<=n){ 48 | int j=2*k; 49 | if(j> extends Sort{ 14 | @Override 15 | public void sort(T[] nums) { 16 | int n=nums.length-1; 17 | for(int k=n/2;k>=1;k--){ 18 | sink(nums,k,n); 19 | } 20 | while(n>1){ 21 | swap(nums,1,n--); 22 | sink(nums,1,n); 23 | } 24 | } 25 | 26 | public void sink(T[] nums,int k,int n){ 27 | while(2*k<=n){ 28 | int j=2*k; 29 | if(j sort=new HeapSort<>(); 47 | sort.sort(arr); 48 | ArrayUtils.printArray(arr,1); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/sort/Insertion.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | /** 4 | * 插入排序 5 | * 6 | * 插入排序从左到右进行,每次都将当前元素插入到左侧已经排序的数组中, 7 | * 使得插入之后左部数组依然有序。 8 | * 第 j 元素是通过不断向左比较并交换来实现插入过程: 9 | * 当第 j 元素小于第 j - 1 元素,就将它们的位置交换, 10 | * 然后令 j 指针向左移动一个位置,不断进行以上操作。 11 | * 12 | * 插入排序的复杂度取决于数组的初始顺序,如果数组已经部分有序了,逆序较少,那么插入排序会很快。 13 | * 14 | * 平均情况下插入排序需要 ~N2/4 比较以及 ~N2/4 次交换; 15 | * 最坏的情况下需要 ~N2/2 比较以及 ~N2/2 次交换,最坏的情况是数组是倒序的; 16 | * 最好的情况下需要 N-1 次比较和 0 次交换,最好的情况就是数组已经有序了。 17 | * 18 | * @author 刘壮飞 19 | * https://github.com/zfman. 20 | * https://blog.csdn.net/lzhuangfei. 21 | */ 22 | public class Insertion> extends Sort { 23 | @Override 24 | public void sort(T[] nums) { 25 | int n=nums.length; 26 | for(int i=1;i0&&less(nums[j],nums[j-1]);j--){ 28 | swap(nums,j,j-1); 29 | } 30 | } 31 | } 32 | 33 | public static void main(String[] args){ 34 | Integer[] arr={ 35 | 5,1,8,7,10,6,9,5,20,3,0 36 | }; 37 | Sort sort=new Insertion<>(); 38 | sort.sort(arr); 39 | ArrayUtils.printArray(arr); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/sort/MergeSort.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | /** 4 | * 归并排序的思想是将数组分成两部分,分别进行排序,然后归并起来。 5 | * 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public abstract class MergeSort> extends Sort { 11 | 12 | protected T[] tmp; 13 | 14 | protected void merge(T[] nums, int l, int m, int h) { 15 | //i:待归并的前者的位置,j:待归并的后者的位置 16 | int i = l, j = m + 1; 17 | for (int k = l; k <= h; k++) { 18 | tmp[k] = nums[k]; 19 | } 20 | 21 | //两个子序列合并 22 | int v=l; 23 | while(i<=m&&j<=h){ 24 | if(tmp[i].compareTo(tmp[j])<=0) nums[v++]=tmp[i++]; 25 | else nums[v++]=tmp[j++]; 26 | } 27 | if(m>i){ 28 | for(;j<=h;j++) nums[v++]=tmp[j]; 29 | } 30 | if(j>h){ 31 | for(;i<=m;i++) nums[v++]=tmp[i]; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/sort/QuickSort.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | /** 8 | * 快速排序 9 | * 10 | * 快速排序通过一个切分元素将数组分为两个子数组,左子数组小于等于切分元素, 11 | * 右子数组大于等于切分元素,将这两个子数组排序也就将整个数组排序了。 12 | * 13 | *

性能分析

14 | * 15 | * 快速排序是原地排序,不需要辅助数组,但是递归调用需要辅助栈。 16 | * 17 | * 快速排序最好的情况下是每次都正好能将数组对半分,这样递归调用次数才是最少的。 18 | * 这种情况下比较次数为 CN=2CN/2+N,复杂度为 O(NlogN)。 19 | * 20 | * 最坏的情况下,第一次从最小的元素切分,第二次从第二小的元素切分,如此这般。 21 | * 因此最坏的情况下需要比较 N2/2。为了防止数组最开始就是有序的,在进行快速排序时需要随机打乱数组。 22 | * 23 | *

算法改进

24 | * 25 | * (一)切换到插入排序 26 | * 27 | * 因为快速排序在小数组中也会递归调用自己,对于小数组,插入排序比快速排序的性能更好, 28 | * 因此在小数组中可以切换到插入排序。 29 | * 30 | * (二)三数取中 31 | * 32 | * 最好的情况下是每次都能取数组的中位数作为切分元素,但是计算中位数的代价很高。 33 | * 人们发现取 3 个元素并将大小居中的元素作为切分元素的效果最好。 34 | * 35 | * (三)三向切分 36 | * 37 | * 对于有大量重复元素的数组,可以将数组切分为三部分,分别对应小于、等于和大于切分元素。 38 | * 39 | * 三向切分快速排序对于只有若干不同主键的随机数组可以在线性时间内完成排序。 40 | * 41 | * @author 刘壮飞 42 | * https://github.com/zfman. 43 | * https://blog.csdn.net/lzhuangfei. 44 | */ 45 | public class QuickSort> extends Sort { 46 | @Override 47 | public void sort(T[] nums) { 48 | shuffle(nums); 49 | sort(nums,0,nums.length-1); 50 | } 51 | 52 | public void sort(T[] nums,int l,int h){ 53 | if(l>=h) return; 54 | int j=partition(nums,l,h); 55 | sort(nums,l,j-1); 56 | sort(nums,j+1,h); 57 | } 58 | 59 | /** 60 | * 切分 61 | * @param nums 62 | * @param l 63 | * @param h 64 | * @return 65 | */ 66 | public int partition(T[] nums,int l,int h){ 67 | int i=l,j=h+1; 68 | T v=nums[l]; 69 | while(true){ 70 | while(j!=l&&less(v,nums[--j])); 71 | while(i!=h&&less(nums[++i],v)); 72 | if(i>=j) break; 73 | swap(nums,i,j); 74 | } 75 | swap(nums,l,j); 76 | return j; 77 | } 78 | 79 | /** 80 | * 打乱顺序 81 | * @param nums 82 | */ 83 | public void shuffle(T[] nums){ 84 | List list=Arrays.asList(nums); 85 | Collections.shuffle(list); 86 | list.toArray(nums); 87 | } 88 | 89 | public static void main(String[] args){ 90 | Integer[] arr={ 91 | 5,1,8,7,10,6,9,5,20,3,0 92 | }; 93 | Sort sort=new QuickSort<>(); 94 | sort.sort(arr); 95 | ArrayUtils.printArray(arr); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/sort/Selection.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | /** 4 | * 选择排序 5 | * 6 | * 选择出数组中的最小元素,将它与数组的第一个元素交换位置。 7 | * 再从剩下的元素中选择出最小的元素,将它与数组的第二个元素交换位置。 8 | * 不断进行这样的操作,直到将整个数组排序。 9 | * 10 | * @author 刘壮飞 11 | * https://github.com/zfman. 12 | * https://blog.csdn.net/lzhuangfei. 13 | */ 14 | public class Selection> extends Sort{ 15 | @Override 16 | public void sort(T[] nums) { 17 | int n=nums.length; 18 | for(int i=0;i sort=new Selection<>(); 32 | sort.sort(arr); 33 | ArrayUtils.printArray(arr); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/sort/Shell.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | /** 4 | * 希尔排序 5 | * 6 | * 先将整个待排记录序列分割成若干子序列,分别进行直接插入排序, 7 | * 待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序 8 | * 9 | * 对于大规模的数组,插入排序很慢,因为它只能交换相邻的元素,每次只能将逆序数量减少 1。 10 | * 希尔排序的出现就是为了改进插入排序的这种局限性,它通过交换不相邻的元素,每次可以将逆序数量减少大于 1。 11 | * 希尔排序使用插入排序对间隔 h 的序列进行排序。通过不断减小 h,最后令 h=1,就可以使得整个数组是有序的。 12 | * 13 | * 14 | * 15 | * @author 刘壮飞 16 | * https://github.com/zfman. 17 | * https://blog.csdn.net/lzhuangfei. 18 | */ 19 | public class Shell> extends Sort { 20 | @Override 21 | public void sort(T[] nums) { 22 | int n=nums.length; 23 | int step=1; 24 | while (step=1){ 27 | for(int i=step;i=step&&less(nums[j],nums[j-step]);j-=step){ 29 | swap(nums,j,j-step); 30 | } 31 | } 32 | step=step/3; 33 | } 34 | 35 | } 36 | 37 | public static void main(String[] args){ 38 | Integer[] arr={ 39 | 5,1,8,7,10,6,9,5,20,3,0 40 | }; 41 | Sort sort=new Shell<>(); 42 | sort.sort(arr); 43 | ArrayUtils.printArray(arr); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/sort/Sort.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | /** 4 | * @author 刘壮飞 5 | * https://github.com/zfman. 6 | * https://blog.csdn.net/lzhuangfei. 7 | */ 8 | public abstract class Sort> { 9 | public abstract void sort(T[] nums); 10 | 11 | public boolean less(T v,T w){ 12 | return v.compareTo(w)<0; 13 | } 14 | 15 | public void swap(T[] a,int i,int j){ 16 | T t=a[i]; 17 | a[i]=a[j]; 18 | a[j]=t; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/sort/ThreeWayQuickSort.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | /** 4 | * 三向切分快速排序 5 | * 对于有大量重复元素的数组,可以将数组切分为三部分,分别对应小于、等于和大于切分元素。 6 | * 7 | * 三向切分快速排序对于只有若干不同主键的随机数组可以在线性时间内完成排序。 8 | * 9 | * @author 刘壮飞 10 | * https://github.com/zfman. 11 | * https://blog.csdn.net/lzhuangfei. 12 | */ 13 | public class ThreeWayQuickSort> extends QuickSort { 14 | @Override 15 | public void sort(T[] nums, int l, int h) { 16 | if(l>=h) return; 17 | int lt=l,i=l+1,gt=h; 18 | T v=nums[l]; 19 | System.out.println(v); 20 | while (i<=gt){ 21 | int compare=nums[i].compareTo(v); 22 | if(compare<0){ 23 | swap(nums,lt++,i++); 24 | }else if(compare>0){ 25 | swap(nums,i,gt--); 26 | }else { 27 | i++; 28 | } 29 | } 30 | sort(nums,l,lt-1); 31 | sort(nums,gt+1,h); 32 | } 33 | 34 | public static void main(String[] args){ 35 | Integer[] arr={ 36 | 5,1,8,1,3,3,3,3,5,5,8,8,8 37 | }; 38 | ArrayUtils.printArray(arr); 39 | Sort sort=new ThreeWayQuickSort<>(); 40 | sort.sort(arr); 41 | ArrayUtils.printArray(arr); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/sort/UpToDownMergeSort.java: -------------------------------------------------------------------------------- 1 | package sort; 2 | 3 | /** 4 | * 自顶向下归并排序 5 | * 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public class UpToDownMergeSort> extends MergeSort { 11 | 12 | /** 13 | * 因为每次都将问题对半分成两个子问题, 14 | * 而这种对半分的算法复杂度一般为 O(NlogN), 15 | * 因此该归并排序方法的时间复杂度也为 O(NlogN)。 16 | * 17 | * @param nums 18 | */ 19 | @Override 20 | public void sort(T[] nums) { 21 | tmp= (T[]) new Comparable[nums.length]; 22 | sort(nums,0,nums.length-1); 23 | } 24 | 25 | public void sort(T[] nums,int l,int h) { 26 | if(l>=h) return; 27 | int mid=l+(h-l)/2; 28 | sort(nums,l,mid); 29 | sort(nums,mid+1,h); 30 | merge(nums,l,mid,h); 31 | } 32 | 33 | public static void main(String[] args){ 34 | Integer[] arr={ 35 | 5,1,8,7,10,6,9,5,20,3,0 36 | }; 37 | Sort sort=new UpToDownMergeSort<>(); 38 | sort.sort(arr); 39 | ArrayUtils.printArray(arr); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/sort2/BuddleSort.java: -------------------------------------------------------------------------------- 1 | package sort2; 2 | 3 | import utils.ArrayUtils; 4 | 5 | /** 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public class BuddleSort { 11 | public static void main(String[] args) { 12 | int[] m = { 13 | 3, 1, 5, 8, 4, 6, 9, 2, 4, 0 14 | }; 15 | 16 | int n = m.length; 17 | for (int i = 0; i < n-1; i++) { 18 | for(int j=0;jm[j+1]){ 20 | int tmp=m[j]; 21 | m[j]=m[j+1]; 22 | m[j+1]=tmp; 23 | } 24 | } 25 | } 26 | 27 | ArrayUtils.printArray(m); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/sort2/Insertion.java: -------------------------------------------------------------------------------- 1 | package sort2; 2 | 3 | import utils.ArrayUtils; 4 | 5 | /** 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public class Insertion { 11 | public static void main(String[] args) { 12 | int[] m = { 13 | 3, 1, 5, 8, 4, 6, 9, 2, 4, 0 14 | }; 15 | 16 | int n = m.length; 17 | for (int i = 1; i < n; i++) { 18 | for(int j=i;j>0&&m[j]=r) return; 15 | int j=partition(nums,l,r); 16 | sort(nums,l,j-1); 17 | sort(nums,j+1,r); 18 | } 19 | 20 | public int partition(int[] nums,int l,int r){ 21 | int i=l; 22 | int j=r+1; 23 | int val=nums[l]; 24 | while(true){ 25 | while(j!=l&&nums[--j]>val); 26 | while(i!=r&&nums[++i]=j) break; 28 | swap(nums,i,j); 29 | } 30 | swap(nums,l,j); 31 | return j; 32 | } 33 | 34 | public void swap(int[] nums,int i,int j){ 35 | int tmp=nums[i]; 36 | nums[i]=nums[j]; 37 | nums[j]=tmp; 38 | } 39 | 40 | public static void main(String[] args){ 41 | int[] arr={ 42 | 5,1,8,7,10,6,9,5,20,3,0 43 | }; 44 | new QuickSort().sort(arr); 45 | ArrayUtils.printArray(arr); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/sort2/Selection.java: -------------------------------------------------------------------------------- 1 | package sort2; 2 | 3 | import utils.ArrayUtils; 4 | 5 | /** 6 | * @author 刘壮飞 7 | * https://github.com/zfman. 8 | * https://blog.csdn.net/lzhuangfei. 9 | */ 10 | public class Selection { 11 | public static void main(String[] args) { 12 | int[] m = { 13 | 3, 1, 5, 8, 4, 6, 9, 2, 4, 0 14 | }; 15 | 16 | int n = m.length; 17 | for (int i = 0; i < n; i++) { 18 | int min=i; 19 | for(int j=i+1;j=0;i--){ 31 | if(index%2==0) v1+=a[i]; 32 | else v2+=a[i]; 33 | index++; 34 | } 35 | return v1-v2; 36 | } 37 | 38 | public static void main(String[] args){ 39 | Scanner in = new Scanner(System.in); 40 | int n=in.nextInt(); 41 | int[] a=new int[n]; 42 | for(int i=0;i=1;i--){ 29 | int other=m-i;//剩余块数 30 | int a=i;//当日吃的块数 31 | int j=n-1;//剩余天数 32 | for(;j>=1;j--){ 33 | //能够满足的话就不需要继续遍历了 34 | if(a==1&&other>=j) { 35 | j=-1; 36 | break; 37 | } 38 | //不满足的话直接停止本轮遍历 39 | if(a==1&&otherm){ 47 | return false; 48 | } 49 | if(n!=0&&m<0){ 50 | return false; 51 | }else if(n!=0&&m>=0) { 52 | return isEnough ((int)Math.ceil (mid/2.0),--n,m-mid); 53 | }else { 54 | return true; 55 | } 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /src/tencent/Main6.java: -------------------------------------------------------------------------------- 1 | package tencent; 2 | 3 | import java.util.Scanner; 4 | 5 | /** 6 | * 求解一个数是否是和谐数:n的各个位之和能够被n整除,那么这个数是和谐数 7 | * 8 | * @author 刘壮飞 9 | * https://github.com/zfman. 10 | * https://blog.csdn.net/lzhuangfei. 11 | */ 12 | public class Main6 { 13 | public static void main(String[] args){ 14 | Scanner scanner=new Scanner(System.in); 15 | int n=scanner.nextInt(); 16 | for(int i=0;i