sort=new Selection<>();
32 | sort.sort(arr);
33 | ArrayUtils.printArray(arr);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/leetcode/all/solution1_100/Solution43.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution1_100;
2 |
3 | /**
4 | * 字符串相乘.
5 | * 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
6 | *
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/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/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/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/XunleiTest2.java:
--------------------------------------------------------------------------------
1 | package other;
2 |
3 | import java.util.Scanner;
4 |
5 | /**
6 | *
7 | * 水仙花数
8 | * 输入a和b为求解的范围
9 | *
10 | * @author 刘壮飞
11 | * https://github.com/zfman.
12 | * https://blog.csdn.net/lzhuangfei.
13 | */
14 | public class XunleiTest2 {
15 | public static void main(String[] args){
16 | Scanner scanner=new Scanner(System.in);
17 | while (scanner.hasNextInt()){
18 | int a=scanner.nextInt();
19 | int b=scanner.nextInt();
20 | String ret="";
21 | for(int i=a;i<=b;i++){
22 | int m=i%10;
23 | int n=i/10;
24 | int s=0;
25 | s+=Math.pow(m,3);
26 | while (n!=0){
27 | m=n%10;
28 | n=n/10;
29 | s+=Math.pow(m,3);
30 | }
31 | if(s==i) ret+=s+" ";
32 | }
33 |
34 | if(ret.trim().equals("")) System.out.println("no");
35 | else System.out.println(ret.trim());
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/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/tencent/Main2.java:
--------------------------------------------------------------------------------
1 | package tencent;
2 |
3 | import java.util.*;
4 |
5 | /**
6 | * 翻转数列
7 | *
8 | * 小Q定义了一种数列称为翻转数列:
9 | * 给定整数n和m, 满足n能被2m整除。对于一串连续递增整数数列1, 2, 3, 4..., 每隔m个符号翻转一次, 最初符号为'-';。
10 | * 例如n = 8, m = 2, 数列就是: -1, -2, +3, +4, -5, -6, +7, +8.
11 | * 而n = 4, m = 1, 数列就是: -1, +2, -3, + 4.
12 | * 小Q现在希望你能帮他算算前n项和为多少。
13 | * 输入描述:
14 | * 输入包括两个整数n和m(2 <= n <= 109, 1 <= m), 并且满足n能被2m整除。
15 | *
16 | *
17 | * 输出描述:
18 | * 输出一个整数, 表示前n项和。
19 | *
20 | * 输入例子1:
21 | * 8 2
22 | *
23 | * 输出例子1:
24 | * 8
25 | */
26 | public class Main2{
27 | public static void main(String[] args){
28 | Scanner scan=new Scanner(System.in);
29 | int n=scan.nextInt();
30 | int m=scan.nextInt();
31 | long t=0;
32 | //全部为负数时计算和
33 | for(int i=1;i<=n;i++){
34 | t+=-i;
35 | }
36 | long a=0;
37 | //所有正数和
38 | for(int i=1+m;i<=n;i+=2*m){
39 | for(int j=i;j> 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/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/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/ShenCeInterview2.java:
--------------------------------------------------------------------------------
1 | package other;
2 |
3 | /**
4 | * 神策数据 面试手写算法题2-统计数字个数
5 | *
6 | * 有数据:[1,2,3,4,3,2,1,4,5,6] 统计每个数字出现的个数,并输出每个数字出现的个数,格式如下:
7 | * 1,2
8 | * 2,2
9 | * 3,2
10 | *
11 | * @author 刘壮飞
12 | * https://github.com/zfman.
13 | * https://blog.csdn.net/lzhuangfei.
14 | */
15 | public class ShenCeInterview2 {
16 | public void todo(int[] arr){
17 | //get max of array
18 | int max=arr[0];
19 | for(int i=1;imax) max=arr[i];
21 | }
22 |
23 | // 下标保存数字
24 | // 元素值保存的是次数
25 | // java int[] 元素默认为0
26 | int[] b=new int[max+1];
27 | for(int i=0;imax) 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/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;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/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/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> 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/tencent/Main1.java:
--------------------------------------------------------------------------------
1 | package tencent;
2 |
3 | import java.util.Arrays;
4 | import java.util.Scanner;
5 |
6 | /**
7 | * 腾讯2018秋招模拟笔试
8 | *
9 | * 有一组数字,两个人A和B依次从其中取出一个数字,每次都取出剩余数字中最大的一个,
10 | * A先B后,计算A取出的数字之和-B取出的数字之和
11 | *
12 | * @author 刘壮飞
13 | * https://github.com/zfman.
14 | * https://blog.csdn.net/lzhuangfei.
15 | */
16 | public class Main1 {
17 |
18 | /**
19 | * 先排序,再依次求得A、B各自的分数
20 | *
21 | * @param a
22 | * @return
23 | */
24 | public static int done(int[] a){
25 | int n=a.length;
26 | if(n==0) return 0;
27 | Arrays.sort(a);
28 | int v1=0,v2=0;
29 | int index=0;
30 | for(int i=n-1;i>=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;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/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/leetcode/all/solution101_200/Solution111.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution101_200;
2 |
3 | import leetcode.common.TreeNode;
4 | import leetcode.common.TreeUtils;
5 |
6 | /**
7 | * 111. 二叉树的最小深度
8 | *
9 | * 给定一个二叉树,找出其最小深度。
10 | *
11 | * 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
12 | *
13 | * 说明: 叶子节点是指没有子节点的节点。
14 | *
15 | * 示例:
16 | *
17 | * 给定二叉树 [3,9,20,null,null,15,7],
18 | *
19 | * 3
20 | * / \
21 | * 9 20
22 | * / \
23 | * 15 7
24 | * 返回它的最小深度 2.
25 | *
26 | * @author 刘壮飞
27 | * https://github.com/zfman.
28 | * https://blog.csdn.net/lzhuangfei.
29 | */
30 | public class Solution111 {
31 | public int minDepth(TreeNode root) {
32 | if(root==null) return 0;
33 | if(root.left==null&&root.right==null) return 1;
34 | if(root.left==null) return minDepth(root.right)+1;
35 | else if(root.right==null) return minDepth(root.left)+1;
36 | return Math.min(minDepth(root.left),minDepth(root.right))+1;
37 | }
38 |
39 | public static void main(String[] args){
40 | TreeNode root=TreeUtils.stringToTree("124###3#5##");
41 | int min=new Solution111().minDepth(root);
42 | System.out.println(min);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/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/solution701_800/Solution779.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution701_800;
2 |
3 | /**
4 | * 779. 第K个语法符号
5 | *
6 | * 在第一行我们写上一个 0。接下来的每一行,将前一行中的0替换为01,1替换为10。
7 | *
8 | * 给定行数 N 和序数 K,返回第 N 行中第 K个字符。(K从1开始)
9 | *
10 | *
11 | * 例子:
12 | *
13 | * 输入: N = 1, K = 1
14 | * 输出: 0
15 | *
16 | * 输入: N = 2, K = 1
17 | * 输出: 0
18 | *
19 | * 输入: N = 2, K = 2
20 | * 输出: 1
21 | *
22 | * 输入: N = 4, K = 5
23 | * 输出: 1
24 | *
25 | * 解释:
26 | * 第一行: 0
27 | * 第二行: 01
28 | * 第三行: 0110
29 | * 第四行: 01101001
30 | *
31 | * 注意:
32 | *
33 | * N 的范围 [1, 30].
34 | * K 的范围 [1, 2^(N-1)].
35 | *
36 | * @author 刘壮飞
37 | * https://github.com/zfman.
38 | * https://blog.csdn.net/lzhuangfei.
39 | */
40 | public class Solution779 {
41 | public int kthGrammar(int N, int K) {
42 | if(K==1) return 0;
43 | if(K%2==0){
44 | return kthGrammar(N-1,K/2)==0?1:0;
45 | }else{
46 | return kthGrammar(N-1,(K+1)/2)==0?0:1;
47 | }
48 | }
49 |
50 | public static void main(String[] args){
51 | int n=30;
52 | int k=434991989;
53 | int r=new Solution779().kthGrammar(n,k);
54 | System.out.println(r);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/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;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;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/offer/HasSubtreeSolution.java:
--------------------------------------------------------------------------------
1 | package offer;
2 |
3 | import leetcode.common.TreeNode;
4 | import leetcode.common.TreeUtils;
5 |
6 | /**
7 | * 树的子结构
8 | *
9 | * 输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
10 | *
11 | * @author 刘壮飞
12 | * https://github.com/zfman.
13 | * https://blog.csdn.net/lzhuangfei.
14 | */
15 | public class HasSubtreeSolution {
16 | public boolean HasSubtree(TreeNode root1, TreeNode root2) {
17 | if(root1==null||root2==null) return false;
18 | return isSubtree(root1,root2)||HasSubtree(root1.left,root2)||HasSubtree(root1.right,root2);
19 | }
20 |
21 | public boolean isSubtree(TreeNode root1,TreeNode root2){
22 | if(root2==null) return true;
23 | if(root1==null) return false;
24 | return root1.val==root2.val&&isSubtree(root1.left,root2.left)&&isSubtree(root1.right,root2.right);
25 | }
26 |
27 | public static void main(String[] args) {
28 | String treeStr1 = "889##24##7##7##";
29 | String treeStr2 = "89##2##";
30 | TreeNode root1=TreeUtils.stringToTree(treeStr1);
31 | TreeNode root2=TreeUtils.stringToTree(treeStr2);
32 | boolean r=new HasSubtreeSolution().HasSubtree(root1,root2);
33 | System.out.println(r);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/sort2/QuickSort.java:
--------------------------------------------------------------------------------
1 | package sort2;
2 | import utils.ArrayUtils;
3 |
4 | /**
5 | * @author 刘壮飞
6 | * https://github.com/zfman.
7 | * https://blog.csdn.net/lzhuangfei.
8 | */
9 | public class QuickSort {
10 | public void sort(int[] nums){
11 | sort(nums,0,nums.length-1);
12 | }
13 | public void sort(int[] nums,int l,int r){
14 | if(l>=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/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/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/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/leetcode/all/solution401_500/Solution404.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution401_500;
2 |
3 | import leetcode.common.TreeNode;
4 | import leetcode.common.TreeUtils;
5 |
6 | /**
7 | * 404. 左叶子之和
8 | *
9 | * 计算给定二叉树的所有左叶子之和。
10 | *
11 | * 示例:
12 | *
13 | * 3
14 | * / \
15 | * 9 20
16 | * / \
17 | * 15 7
18 | *
19 | * 在这个二叉树中,有两个左叶子,分别是 9 和 15,所以返回 24
20 | *
21 | * @author 刘壮飞
22 | * https://github.com/zfman.
23 | * https://blog.csdn.net/lzhuangfei.
24 | */
25 | public class Solution404 {
26 | public int sumOfLeftLeaves(TreeNode root) {
27 | if(root==null||(root.left==null&&root.right==null)) return 0;
28 | return sum(root,1);
29 | }
30 |
31 | /**
32 | * 求左叶子节点的和
33 | * @param root
34 | * @param left 1:左节点,0:右节点
35 | * @return
36 | */
37 | public int sum(TreeNode root,int left) {
38 | if(root==null) return 0;
39 | if(root.left==null&&root.right==null&&left==1) return root.val;
40 | return sum(root.left,1)+sum(root.right,0);
41 | }
42 |
43 | public static void main(String[] args){
44 | TreeNode root=TreeUtils.stringToTreeWith("3 9 # # 20 15 # # 7 # #"," ");
45 | int r=new Solution404().sumOfLeftLeaves(root);
46 | System.out.println(r);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/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(k
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/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/tencent/Main3.java:
--------------------------------------------------------------------------------
1 | package tencent;
2 |
3 | import java.util.*;
4 |
5 | /**
6 | * 贪吃的小Q
7 | *
8 | * 小Q的父母要出差N天,走之前给小Q留下了M块巧克力。小Q决定每天吃的巧克力数量不少于前一天吃的一半,但是他又不想在父母回来之前的某一天没有巧克力吃,请问他第一天最多能吃多少块巧克力
9 | * 输入描述:
10 | * 每个输入包含一个测试用例。
11 | * 每个测试用例的第一行包含两个正整数,表示父母出差的天数N(N<=50000)和巧克力的数量M(N<=M<=100000)。
12 | *
13 | *
14 | * 输出描述:
15 | * 输出一个数表示小Q第一天最多能吃多少块巧克力。
16 | *
17 | * 输入例子1:
18 | * 3 7
19 | *
20 | * 输出例子1:
21 | * 4
22 | */
23 | public class Main3{
24 | public static void main(String[] args){
25 | Scanner in=new Scanner(System.in);
26 | int n=in.nextInt();//天数
27 | int m=in.nextInt();//块数
28 | for(int i=m;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&&other=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/sort/HeapSort.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 HeapSort> 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/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/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(jm){
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/other/Wanmei1.java:
--------------------------------------------------------------------------------
1 | package other;
2 |
3 | /**
4 | * 完美世界-诱惑值
5 | * 格子n*n,每个位置都有一个诱惑值值,计算从左上到右下最小的诱惑值
6 | *
7 | * input:
8 | * 3
9 | * 1 3 7
10 | * 6 2 1
11 | * 9 8 0
12 | *
13 | * output:
14 | * 7
15 | *
16 | * 说明:第一行是n,表示矩阵为n行n列,之后的n行为每行的诱惑值
17 | *
18 | * @author 刘壮飞
19 | * https://github.com/zfman.
20 | * https://blog.csdn.net/lzhuangfei.
21 | */
22 | public class Wanmei1 {
23 | public int todo(int[][] arr) {
24 | //初始化
25 | int[][] dp = new int[arr.length][arr.length];
26 | for (int i = 0; i < dp.length; i++) {
27 | if (i == 0) dp[0][i] = arr[0][i];
28 | else dp[0][i] = dp[0][i - 1] + arr[0][i];
29 | }
30 | for (int i = 0; i < dp.length; i++) {
31 | if (i == 0) dp[i][0] = arr[i][0];
32 | else dp[i][0] = dp[i - 1][0] + arr[i][0];
33 | }
34 |
35 | //从第2行,第2列开始,该位置最小诱惑值值等于左侧和上侧的最小值加上当前位置的诱惑值
36 | for (int i = 1; i < arr.length; i++) {
37 | for (int j = 1; j < arr.length; j++) {
38 | dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1])+arr[i][j];
39 | }
40 | }
41 | return dp[dp.length-1][dp.length-1];
42 | }
43 |
44 | public static void main(String[] args) {
45 | int[][] arr = {
46 | {1, 3, 7},
47 | {6, 2, 1},
48 | {9,8,0}
49 | };
50 | int r=new Wanmei1().todo(arr);
51 | System.out.println(r);//7
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/leetcode/all/solution401_500/Solution448.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution401_500;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * 448. 找到所有数组中消失的数字
8 | *
9 | * 给定一个范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) 的 整型数组,数组中的元素一些出现了两次,另一些只出现一次。
10 | *
11 | * 找到所有在 [1, n] 范围之间没有出现在数组中的数字。
12 | *
13 | * 您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。
14 | *
15 | * 示例:
16 | *
17 | * 输入:
18 | * [4,3,2,7,8,2,3,1]
19 | *
20 | * 输出:
21 | * [5,6]
22 | *
23 | * @author 刘壮飞
24 | * https://github.com/zfman.
25 | * https://blog.csdn.net/lzhuangfei.
26 | */
27 | public class Solution448 {
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 r = new Solution448().findDuplicates(nums);
54 | for (Integer i : r) {
55 | System.out.print(i + " ");
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/offer/MergeSolution.java:
--------------------------------------------------------------------------------
1 | package offer;
2 |
3 | import leetcode.common.LinkedUtils;
4 | import leetcode.common.ListNode;
5 |
6 | /**
7 | * 合并两个排序的链表
8 | *
9 | * 输入两个单调递增的链表,输出两个链表合成后的链表,
10 | * 当然我们需要合成后的链表满足单调不减规则。
11 | *
12 | * @author 刘壮飞
13 | * https://github.com/zfman.
14 | * https://blog.csdn.net/lzhuangfei.
15 | */
16 | public class MergeSolution {
17 | public ListNode Merge(ListNode list1, ListNode list2) {
18 | ListNode list3=new ListNode(0);
19 | ListNode tmp=list3;
20 |
21 | while (list1!=null&&list2!=null){
22 | if(list2.val>list1.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/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/solution1_100/Solution35.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution1_100;
2 |
3 | /**
4 | * 35. 搜索插入位置.
5 | * 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
6 | *
7 | * 你可以假设数组中无重复元素。
8 | *
9 | * 示例 1:
10 | * 输入: [1,3,5,6], 5
11 | * 输出: 2
12 | *
13 | * 示例 2:
14 | * 输入: [1,3,5,6], 2
15 | * 输出: 1
16 | *
17 | * 示例 3:
18 | * 输入: [1,3,5,6], 7
19 | * 输出: 4
20 | *
21 | * 示例 4:
22 | * 输入: [1,3,5,6], 0
23 | * 输出: 0
24 | *
25 | * @author 刘壮飞
26 | * https://github.com/zfman.
27 | * https://blog.csdn.net/lzhuangfei.
28 | */
29 | public class Solution35 {
30 |
31 | public int searchInsert(int[] nums, int target) {
32 | return binSearch(nums,0,nums.length-1,target);
33 | }
34 |
35 | /**
36 | * 二分查找
37 | * @param nums 数组
38 | * @param low 低位
39 | * @param high 高位
40 | * @param value 待查找值
41 | * @return 位置,未找到返回low
42 | */
43 | public int binSearch(int[] nums,int low,int high,int value){
44 | int middle=low+(high-low)/2;
45 | if(low>high) return low;
46 | if(value==nums[middle]) return middle;
47 | else if(value 向右 -> 向下
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;i2->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/solution1_100/Solution66.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution1_100;
2 |
3 | /**
4 | * 66. 加一.
5 | * 给定一个非负整数组成的非空数组,在该数的基础上加一,返回一个新的数组。
6 | *
7 | * 最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。
8 | *
9 | * 你可以假设除了整数 0 之外,这个整数不会以零开头。
10 | *
11 | * 示例 1:
12 | * 输入: [1,2,3]
13 | * 输出: [1,2,4]
14 | * 解释: 输入数组表示数字 123。
15 | *
16 | * 示例 2:
17 | * 输入: [4,3,2,1]
18 | * 输出: [4,3,2,2]
19 | * 解释: 输入数组表示数字 4321。
20 | *
21 | * @author 刘壮飞
22 | * https://github.com/zfman.
23 | * https://blog.csdn.net/lzhuangfei.
24 | */
25 | public class Solution66 {
26 |
27 | /**
28 | * 从后往前计算,如果该位小于9,直接加1,停止
29 | * 如果等于9,置0,继续向前计算.
30 | * 注意边界值,如果超出,需要扩容,高位补1
31 | *
32 | * @param digits
33 | * @return
34 | */
35 | public int[] plusOne(int[] digits) {
36 | int i=digits.length-1;
37 | for(;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;mmaxVal) 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/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/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/solution701_800/Solution746.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution701_800;
2 |
3 | /**
4 | * 746. 使用最小花费爬楼梯
5 | *
6 | * 数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost[i](索引从0开始)。
7 | *
8 | * 每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或者爬两个阶梯。
9 | *
10 | * 您需要找到达到楼层顶部的最低花费。在开始时,你可以选择从索引为 0 或 1 的元素作为初始阶梯。
11 | *
12 | * 示例 1:
13 | *
14 | * 输入: cost = [10, 15, 20]
15 | * 输出: 15
16 | * 解释: 最低花费是从cost[1]开始,然后走两步即可到阶梯顶,一共花费15。
17 | * 示例 2:
18 | *
19 | * 输入: cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1]
20 | * 输出: 6
21 | * 解释: 最低花费方式是从cost[0]开始,逐个经过那些1,跳过cost[3],一共花费6。
22 | * 注意:
23 | *
24 | * cost 的长度将会在 [2, 1000]。
25 | * 每一个 cost[i] 将会是一个Integer类型,范围为 [0, 999]。
26 | *
27 | * @author 刘壮飞
28 | * https://github.com/zfman.
29 | * https://blog.csdn.net/lzhuangfei.
30 | */
31 | public class Solution746 {
32 | public int minCostClimbingStairs(int[] cost) {
33 | int[] v=new int[cost.length+1];
34 | if(cost.length==0) return 0;
35 | if(cost.length==1) return 1;
36 | if(cost.length==2) return Math.min(cost[0],cost[1]);
37 |
38 | v[0]=cost[0];
39 | v[1]=cost[1];
40 |
41 | for(int i=2;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/other/ZhaoShang2018_1.java:
--------------------------------------------------------------------------------
1 | package other;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * 招商银行2018笔试题
8 | *
9 | * 给出一个正整数n,请给出所有的包含n个'('和n个')'的字符串,使得'('和')'可以完全匹配。
10 | * 例如:
11 | * '(())()','()()()' 都是合法的;
12 | * '())()('是不合法的。
13 | * 请按照__字典序__给出所有合法的字符串。
14 | *
15 | * 输入描述:
16 | * 输入为1个正整数
17 | *
18 | *
19 | * 输出描述:
20 | * 输出为所有合法的字符串,用英文逗号隔开
21 | * 示例1
22 | * 输入
23 | * 2
24 | * 输出
25 | * (()),()()
26 | *
27 | * @author 刘壮飞
28 | * https://github.com/zfman.
29 | * https://blog.csdn.net/lzhuangfei.
30 | */
31 | public class ZhaoShang2018_1 {
32 | public List 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/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/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/Solution687.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution601_700;
2 |
3 | import leetcode.common.TreeNode;
4 | import leetcode.common.TreeUtils;
5 |
6 | /**
7 | * 687. 最长同值路径
8 | *
9 | * 给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值。 这条路径可以经过也可以不经过根节点。
10 | *
11 | * 注意:两个节点之间的路径长度由它们之间的边数表示。
12 | *
13 | * 示例 1:
14 | *
15 | * 输入:
16 | *
17 | * 5
18 | * / \
19 | * 4 5
20 | * / \ \
21 | * 1 1 5
22 | * 输出:
23 | *
24 | * 2
25 | * 示例 2:
26 | *
27 | * 输入:
28 | *
29 | * 1
30 | * / \
31 | * 4 5
32 | * / \ \
33 | * 4 4 5
34 | * 输出:
35 | *
36 | * 2
37 | *
38 | * @author 刘壮飞
39 | * https://github.com/zfman.
40 | * https://blog.csdn.net/lzhuangfei.
41 | */
42 | public class Solution687 {
43 | private int max=0;
44 | public int longestUnivaluePath(TreeNode root) {
45 | if(root!=null) dfs(root,root.val-1);
46 | return max;
47 | }
48 |
49 | public int dfs(TreeNode node,int val){
50 | if(node==null) return 0;
51 | int left=dfs(node.left,node.val);
52 | int right=dfs(node.right,node.val);
53 | int v1=left+right;
54 | int v2=Math.max(left,right);
55 | max=Math.max(Math.max(v1,v2),max);
56 | if(node.val==val) return v2+1;
57 | return 0;
58 | }
59 |
60 | public static void main(String[] args){
61 | // TreeNode root=TreeUtils.stringToTree("144##4##55###");
62 | TreeNode root=TreeUtils.stringToTree("11###");
63 | int r=new Solution687().longestUnivaluePath(root);
64 | System.out.println(r);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/other/Baidu1.java:
--------------------------------------------------------------------------------
1 | package other;
2 |
3 | import java.util.Scanner;
4 |
5 | /**
6 | * 百度2019 笔试-地外文明
7 | * 时间限制:C/C++语言 1000MS;其他语言 3000MS
8 | * 内存限制:C/C++语言 65536KB;其他语言 589824KB
9 | * 题目描述:
10 | * 地球上的宇宙科学家发现,在宇宙中的K29388G10位置有一颗酷似地球的星球,上面有一种文明,但是并不知道其文明程度。所以为了试探该星球文明是高度发达还是非常古老落后,科学家们决定发送一段英文变体,来测试它们是否能够快速识别、掌握这种文字并对地球做出反馈。
11 | *
12 | * 科学家们制定了英文字母移位变换规则:有英文大写字母表ABCDEFGHIJKLMNOPQRSTUVWXYZ,定义Z的下一个字母为A,A的上一个字母为Z(变成一个环)。令A=0,B=1,C=2,……,Z=25,每个字母对应一个数字,对于奇数字母,将其变换成它前面的第6个字母,对于偶数字母,将其变换成它后面的第8个字母。例如对于Y=24,它是偶数字母,将其变换成它后面的第八个字母(…XYZABCDEFGH…),也就是G。
13 | *
14 | * 现在,给你一段仅由大写字母组成的文字,请你按以上规则对其做一次变换。
15 | *
16 | * 输入
17 | * 仅一行,表示一段文字。(长度不超过100)
18 | *
19 | * 输出
20 | * 仅一行,表示变换后的文字。
21 | *
22 | *
23 | * 样例输入
24 | * ABCDEFGHUVWXYZ
25 | * 样例输出
26 | * IVKXMZOBCPERGT
27 | *
28 | * @author 刘壮飞
29 | * https://github.com/zfman.
30 | * https://blog.csdn.net/lzhuangfei.
31 | */
32 | public class Baidu1 {
33 | public static String todo(String s){
34 | String ret="";
35 | for(char ch:s.toCharArray()){
36 | ret+=""+getChar(s,(int)ch-65);
37 | }
38 | return ret;
39 | }
40 |
41 | public static char getChar(String s,int val){
42 | int charIndex=0;
43 | if(val%2!=0) charIndex=val-6;
44 | else charIndex=val+8;
45 | if(charIndex<0){
46 | charIndex+=26;
47 | }
48 | if(charIndex>25){
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/leetcode/all/solution801_900/Solution872.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution801_900;
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 | * 872. 叶子相似的树
11 | *
12 | * 请考虑一颗二叉树上所有的叶子,这些叶子的值按从左到右的顺序排列形成一个 叶值序列 。
13 | *
14 | * https://s3-lc-upload.s3.amazonaws.com/uploads/2018/07/16/tree.png
15 | *
16 | * 举个例子,如上图所示,给定一颗叶值序列为 (6, 7, 4, 9, 8) 的树。
17 | *
18 | * 如果有两颗二叉树的叶值序列是相同,那么我们就认为它们是 叶相似 的。
19 | *
20 | * 如果给定的两个头结点分别为 root1 和 root2 的树是叶相似的,则返回 true;否则返回 false 。
21 | *
22 | * 提示:
23 | *
24 | * 给定的两颗树可能会有 1 到 100 个结点。
25 | *
26 | * @author 刘壮飞
27 | * https://github.com/zfman.
28 | * https://blog.csdn.net/lzhuangfei.
29 | */
30 | public class Solution872 {
31 | public boolean leafSimilar(TreeNode root1, TreeNode root2) {
32 | List 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/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/other/Xunlei1.java:
--------------------------------------------------------------------------------
1 | package other;
2 |
3 | /**
4 | * 数组中消失的数字
5 | *
6 | * @author 刘壮飞
7 | * https://github.com/zfman.
8 | * https://blog.csdn.net/lzhuangfei.
9 | */
10 |
11 | import java.io.*;
12 | import java.util.*;
13 | import java.text.*;
14 | import java.math.*;
15 | import java.util.regex.*;
16 |
17 | public class Xunlei1 {
18 |
19 | /**
20 | * O(n)的算法
21 | * @param nums
22 | * @return
23 | */
24 | static int[] findDisappearedNum(int[] nums) {
25 | int[] n=new int[nums.length+1];
26 | for(int i=0;i4->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/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/Solution698.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution601_700;
2 |
3 | /**
4 | * 698. 划分为k个相等的子集
5 | *
6 | * 给定一个整数数组 nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。
7 | *
8 | * 示例 1:
9 | *
10 | * 输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4
11 | * 输出: True
12 | * 说明: 有可能将其分成 4 个子集(5),(1,4),(2,3),(2,3)等于总和。
13 | *
14 | *
15 | * 注意:
16 | *
17 | * 1 <= k <= len(nums) <= 16
18 | * 0 < nums[i] < 10000
19 | *
20 | * @author 刘壮飞
21 | * https://github.com/zfman.
22 | * https://blog.csdn.net/lzhuangfei.
23 | */
24 | public class Solution698 {
25 | public boolean canPartitionKSubsets(int[] nums, int k) {
26 | if(k==1) return true;
27 | if(k>nums.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=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/solution501_600/Solution520.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution501_600;
2 |
3 | /**
4 | * 520. 检测大写字母
5 | *
6 | * 给定一个单词,你需要判断单词的大写使用是否正确。
7 | *
8 | * 我们定义,在以下情况时,单词的大写用法是正确的:
9 | *
10 | * 全部字母都是大写,比如"USA"。
11 | * 单词中所有字母都不是大写,比如"leetcode"。
12 | * 如果单词不只含有一个字母,只有首字母大写, 比如 "Google"。
13 | * 否则,我们定义这个单词没有正确使用大写字母。
14 | *
15 | * 示例 1:
16 | *
17 | * 输入: "USA"
18 | * 输出: True
19 | * 示例 2:
20 | *
21 | * 输入: "FlaG"
22 | * 输出: False
23 | * 注意: 输入是由大写和小写拉丁字母组成的非空单词。
24 | *
25 | * @author 刘壮飞
26 | * https://github.com/zfman.
27 | * https://blog.csdn.net/lzhuangfei.
28 | */
29 | public class Solution520 {
30 | /**
31 | * 根据前两个字符判断所属的类别,由此决定后续字符应当具有的行为
32 | * 遍历后续字符,判断是否都具有所属类型的行为
33 | *
34 | * @param word
35 | * @return
36 | */
37 | public boolean detectCapitalUse(String word) {
38 | if(word.length()==1) return true;
39 |
40 | char ch1=word.charAt(0);
41 | char ch2=word.charAt(1);
42 | //1:全为大写 2:首字母大写或者全为小写
43 | int type=1;
44 | if(ch1>='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/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;itarget){
40 | v--;
41 | }else{
42 | k++;
43 | }
44 | //保存最小和、最小距离
45 | if(Math.abs(sum-target)= 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/offer/FindFirstCommonNodeSolution.java:
--------------------------------------------------------------------------------
1 | package offer;
2 |
3 | import leetcode.common.LinkedUtils;
4 | import leetcode.common.ListNode;
5 |
6 | /**
7 | * 两个链表的第一个公共结点
8 | *
9 | * 输入两个链表,找出它们的第一个公共结点。
10 | *
11 | * @author 刘壮飞
12 | * https://github.com/zfman.
13 | * https://blog.csdn.net/lzhuangfei.
14 | */
15 | public class FindFirstCommonNodeSolution {
16 | public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
17 | int m=0,n=0;
18 | ListNode p1=pHead1,p2=pHead2;
19 | while (p1!=null){
20 | p1= p1.next;
21 | m++;
22 | }
23 |
24 | while (p2!=null){
25 | p2= p2.next;
26 | n++;
27 | }
28 |
29 | p1=pHead1;
30 | p2=pHead2;
31 |
32 | int k=0;
33 | if(m>n){
34 | while(k 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/other/Xunlei2.java:
--------------------------------------------------------------------------------
1 | package other;
2 |
3 | import java.io.*;
4 | import java.util.*;
5 | import java.text.*;
6 | import java.math.*;
7 | import java.util.regex.*;
8 |
9 | /**
10 | * 【Android开发工程师】最长无重复字符子串长度
11 | * 时间限制:C/C++语言 1000MS;其他语言 3000MS
12 | * 内存限制:C/C++语言 65536KB;其他语言 589824KB
13 | * 题目描述:
14 | * 给定一个字符串,找出不含有重复字符的最长子串的长度,
15 | *
16 | * 例:给定"abcabcbb",无重复字符的最长子串是 "abc",其长度为 3
17 | *
18 | * 输入
19 | * 一个字符串
20 | *
21 | * 输出
22 | * 最长无重复字符子串的长度
23 | *
24 | *
25 | * 样例输入
26 | * abcabcbb
27 | * 样例输出
28 | * 3
29 | */
30 | public class Xunlei2 {
31 |
32 |
33 | /*请完成下面这个函数,实现题目要求的功能
34 | 当然,你也可以不按照下面这个模板来作答,完全按照自己的想法来 ^-^
35 | ******************************开始写代码******************************/
36 | static int lengthOfSubstring(String s) {
37 | int max=0;
38 | if(s==null) return 0;
39 | List 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/leetcode/all/solution101_200/Solution188.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution101_200;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | /**
7 | * 118. 杨辉三角
8 | * 给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
9 | *
10 | *
11 | *
12 | * 在杨辉三角中,每个数是它左上方和右上方的数的和。
13 | *
14 | * 示例:
15 | *
16 | * 输入: 5
17 | * 输出:
18 | * [
19 | * [1],
20 | * [1,1],
21 | * [1,2,1],
22 | * [1,3,3,1],
23 | * [1,4,6,4,1]
24 | * ]
25 | *
26 | * @author 刘壮飞
27 | * https://github.com/zfman.
28 | * https://blog.csdn.net/lzhuangfei.
29 | */
30 | public class Solution188 {
31 |
32 | /**
33 | * 第一行、二行单独处理
34 | * 其他行:
35 | * 1.第0列、第n-1列为1
36 | * 2.v[n][t]=v[n-1][t]+v[n-1][t+1]
37 | * (n:行,从0开始;t:第n行的第二个元素t=0,第三个为t=1)
38 | * @param numRows
39 | * @return
40 | */
41 | public List> 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/solution401_500/Solution437.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution401_500;
2 |
3 | import leetcode.common.TreeNode;
4 | import leetcode.common.TreeUtils;
5 |
6 | /**
7 | * 437. 路径总和 III
8 | *
9 | * 给定一个二叉树,它的每个结点都存放着一个整数值。
10 | *
11 | * 找出路径和等于给定数值的路径总数。
12 | *
13 | * 路径不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
14 | *
15 | * 二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。
16 | *
17 | * 示例:
18 | *
19 | * root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
20 | *
21 | * 10
22 | * / \
23 | * 5 -3
24 | * / \ \
25 | * 3 2 11
26 | * / \ \
27 | * 3 -2 1
28 | *
29 | * 返回 3。和等于 8 的路径有:
30 | *
31 | * 1. 5 -> 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/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/solution1_100/Solution38.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution1_100;
2 |
3 | /**
4 | * 38.报数.
5 | * 报数序列是指一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:
6 | *
7 | * 1. 1
8 | * 2. 11
9 | * 3. 21
10 | * 4. 1211
11 | * 5. 111221
12 | * 1 被读作 "one 1" ("一个一") , 即 11。
13 | * 11 被读作 "two 1s" ("两个一"), 即 21。
14 | * 21 被读作 "one 2", "one 1" ("一个二" , "一个一") , 即 1211。
15 | *
16 | * 给定一个正整数 n ,输出报数序列的第 n 项。
17 | *
18 | * 注意:整数顺序将表示为一个字符串。
19 | *
20 | * 示例 1:
21 | * 输入: 1
22 | * 输出: "1"
23 | *
24 | * 示例 2:
25 | * 输入: 4
26 | * 输出: "1211"
27 | *
28 | * @author 刘壮飞
29 | * https://github.com/zfman.
30 | * https://blog.csdn.net/lzhuangfei.
31 | */
32 | public class Solution38 {
33 |
34 | /**
35 | * 这道题重要的是要理解题意,题目有点难懂
36 | * 第一个序列为1,之后的序列都是由前一个递推出来的
37 | * 递推规则如下:
38 | * 假设上一个序列为AABCDD,那么该序列为2A1B1B2D
39 | * 统计序列中连续的字符的个数以及字符,拼接起来
40 | * AA就是2A,B就是1B,C就是1C,DD就是2D
41 | *
42 | * 接下来只要根据式子递推就可以了
43 | *
44 | * @param n
45 | * @return
46 | */
47 | public String countAndSay(int n) {
48 | int i=1;
49 | String now="1";
50 | while(i 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/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/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/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;i0,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/Solution63.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution1_100;
2 |
3 | /**
4 | * 63. 不同路径 II
5 | *
6 | * 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
7 | *
8 | * 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
9 | *
10 | * 现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
11 | *
12 | *
13 | *
14 | * 网格中的障碍物和空位置分别用 1 和 0 来表示。
15 | *
16 | * 说明:m 和 n 的值均不超过 100。
17 | *
18 | * 示例 1:
19 | *
20 | * 输入:
21 | * [
22 | * [0,0,0],
23 | * [0,1,0],
24 | * [0,0,0]
25 | * ]
26 | * 输出: 2
27 | * 解释:
28 | * 3x3 网格的正中间有一个障碍物。
29 | * 从左上角到右下角一共有 2 条不同的路径:
30 | * 1. 向右 -> 向右 -> 向下 -> 向下
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> 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/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/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/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;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(nowMlenB){
56 | while(k7->8
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/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/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/solution301_400/Solution304.java:
--------------------------------------------------------------------------------
1 | package leetcode.all.solution301_400;
2 |
3 | /**
4 | * 304. 二维区域和检索 - 矩阵不可变
5 | *
6 | * 给定一个二维矩阵,计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2)。
7 | *
8 | * Range Sum Query 2D
9 | * 上图子矩阵左上角 (row1, col1) = (2, 1) ,右下角(row2, col2) = (4, 3),该子矩形内元素的总和为 8。
10 | *
11 | * 示例:
12 | *
13 | * 给定 matrix = [
14 | * [3, 0, 1, 4, 2],
15 | * [5, 6, 3, 2, 1],
16 | * [1, 2, 0, 1, 5],
17 | * [4, 1, 0, 1, 7],
18 | * [1, 0, 3, 0, 5]
19 | * ]
20 | *
21 | * sumRegion(2, 1, 4, 3) -> 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/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;i