0%

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.demo.s704;


/**
*给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和并同样以字符串形式返回。
*
* 你不能使用任何內建的用于处理大整数的库(比如 BigInteger), 也不能直接将输入的字符串转换为整数形式。
*
*  
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/add-strings
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {
public String addStrings(String num1, String num2) {
//字符串拼接 StringBuilder
StringBuilder builder = new StringBuilder();
int m = num1.length();
int n = num2.length();
//num1 遍历 下标
int i =1;
//num2 遍历 下标
int j =1;
int carray = 0;

while(i + j <= m + n + 1) {
int numa = 0;
//补0对齐位数
if(i > m) {
numa = 0;
} else {
//字符转数字 从右向左 取值
numa = num1.charAt(m - i++) - '0';
}
int numb = 0;
//补0对齐位数
if(j > n) {
numb = 0;
} else {
//字符转数字 从右向左 取值
numb = num2.charAt(n - j++) - '0';
}
//从右向左 逐位数字相加
int sum = numa + numb + carray;
//满10 进一位
carray = sum / 10;
builder.append(sum % 10);
}
//最后一次相加后 如果有进位 则拼接到字符串
if(carray != 0) {
builder.append(carray);
}
//翻转字符串
return builder.reverse().toString();
}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.demo.s70;

/**
* 爬楼梯
* 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
*
* 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
*/
public class Solution {
public int climbStairs(int n) {
//倒推 func(n) = func(n-1) + func(n-2)
//边界 func(3) = func(2) + func(1)
// func(2) = 2
// func(1) = 1
// func(0) = 0
int p = 0;
int q = 0;
int r = 1;
for(int i =0; i< n; i++) {
p = q;
q = r;
r = p + q;
}
return r;
}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.demo.s7;

/**
* 整数反转
* 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
*
* 如果反转后整数超过 32 位的有符号整数的范围 [−231,  231 − 1] ,就返回 0。
*
* 假设环境不允许存储 64 位整数(有符号或无符号)
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/reverse-integer
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {
public int reverse(int x) {
//初始化返回值
int res = 0;
//数字拆分
while(x != 0) {
//特殊情况判断
if(res < Integer.MIN_VALUE/10 || res > Integer.MAX_VALUE/10) {
return 0;
}
int m = x % 10;
x = x / 10;
res = res * 10 + m;
}

return res;
}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.demo.s69;

/**
* x平方根
* 给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
*
* 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
*
* 注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
*
*
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/sqrtx
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {
public int mySqrt(int x) {
int l = 0;
int r = x;
int ret = 0;
//中间值 二分法
int mid = 0;
//左右移动 l r
while(l <= r) {
mid = (l + r)/ 2;
long tmp = (long)mid * mid;
if(tmp == x) {
return mid;
}
if(tmp <= x) {
ret = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
return ret;
}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package com.demo.s68;

import java.util.ArrayList;
import java.util.List;

/**
* 文本左右对齐
* 给定一个单词数组 words 和一个长度 maxWidth ,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。
*
* 你应该使用 “贪心算法” 来放置给定的单词;也就是说,尽可能多地往每行中放置单词。必要时可用空格 ' ' 填充,使得每行恰好有 maxWidth 个字符。
*
* 要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配,则左侧放置的空格数要多于右侧的空格数。
*
* 文本的最后一行应为左对齐,且单词之间不插入额外的空格。
*
* 注意:
*
* 单词是指由非空格字符组成的字符序列。
* 每个单词的长度大于 0,小于等于 maxWidth。
* 输入单词数组 words 至少包含一个单词。
*
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/text-justification
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {
public List<String> fullJustify(String[] words, int maxWidth) {
//定义0-maxWidth个空格字符串,方便之后直接调用
final String[] space = new String[maxWidth+1];
StringBuffer s = new StringBuffer();
for(int i = 0;i<maxWidth+1;i++){
space[i] = s.toString();
s.append(" ");
}
//新建List,用来存最后的结果。
List<String> pWords = new ArrayList<String>();
//遍历整个words,一行一行的排版
for(int i=0; i<words.length; i++){
int curlen = words[i].length();
//记录当前已读取单词的长度,当>=maxWidth时进行排版
int startI = i;
//记录本次读取单词的起点
while(i < words.length-1 && curlen<maxWidth){
i++;
curlen = curlen+words[i].length()+1;
// 每多读一个单词都要加一个空格
}
if(curlen>maxWidth){
//当前长度>maxWidth,说明已经多读取了一个单词
curlen = curlen-words[i].length()-1;
i--;
}
//一行一行的排版
pWords.add(processCurline(words,startI,i,curlen,maxWidth,space));
}
return pWords;
}
public String processCurline(String[] words,int si,int ei,int curlen,int maxWidth,String[] space){
StringBuffer sb = new StringBuffer(); //用来进行排版
int map = ei-si; // 记录单词之间的有几个间隙
int addSpace = maxWidth - curlen+map; //记录这一行总共有多少个空格
if(map==0){ //间隙为0,证明只有一个单词
sb.append(words[ei]);
sb.append(space[addSpace]);
return sb.toString();
}
if(ei == words.length-1){ //证明要排版最后一行了,格式特殊
for(int i =si;i<ei;i++){
sb.append(words[i]).append(" ");
}
sb.append(words[ei]); //最后一个单词不用加空格
sb.append(space[addSpace-map]); //如果还有多余空格,一起加上
return sb.toString();
}
int allAddSpace = addSpace/map; //所有的空格数 / 间隙 = 每个间隙必加的空格数
int left = addSpace % map + si; //多出来的空格要从si开始,依次加在间隙中
for(int i = si;i<ei;i++){
sb.append(words[i]).append(space[allAddSpace]);
if(i < left) sb.append(" "); // <left就要多加一个空格
}
sb.append(words[ei]);
return sb.toString();
}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.demo.s67;

/**
* x 的平方根
* 给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
*
* 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
*
* 注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
*
*
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/sqrtx
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {
public int mySqrt(int x) {
int l = 0;
int r = x;
int ret = 0;
//中间值 二分法
int mid = 0;
//左右移动 l r
while(l <= r) {
mid = (l + r)/ 2;
long tmp = (long)mid * mid;
if(tmp == x) {
return mid;
}
if(tmp <= x) {
ret = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
return ret;
}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.demo.s66;

/**
* 二进制求和
* 给你两个二进制字符串,返回它们的和(用二进制表示)。
*
* 输入为 非空 字符串且只包含数字 1 和 0。
*/
public class Solution {
public String addBinary(String a, String b) {
StringBuffer ans = new StringBuffer();

int n = Math.max(a.length(), b.length()), carry = 0;
for (int i = 0; i < n; ++i) {
carry += i < a.length() ? (a.charAt(a.length() - 1 - i) - '0') : 0;
carry += i < b.length() ? (b.charAt(b.length() - 1 - i) - '0') : 0;
ans.append((char) (carry % 2 + '0'));
carry /= 2;
}

if (carry > 0) {
ans.append('1');
}
ans.reverse();

return ans.toString();

}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package com.demo.s65;

import java.util.HashMap;
import java.util.Map;

/**
* 有效数字
* 有效数字(按顺序)可以分成以下几个部分:
*
* 一个 小数 或者 整数
* (可选)一个 'e' 或 'E' ,后面跟着一个 整数
* 小数(按顺序)可以分成以下几个部分:
*
* (可选)一个符号字符('+' 或 '-')
* 下述格式之一:
* 至少一位数字,后面跟着一个点 '.'
* 至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字
* 一个点 '.' ,后面跟着至少一位数字
* 整数(按顺序)可以分成以下几个部分:
*
* (可选)一个符号字符('+' 或 '-')
* 至少一位数字
* 部分有效数字列举如下:["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"]
*
* 部分无效数字列举如下:["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"]
*
* 给你一个字符串 s ,如果 s 是一个 有效数字 ,请返回 true 。
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/valid-number
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {

public boolean isNumber(String s) {
Map<State, Map<CharType, State>> transfer = new HashMap<State, Map<CharType, State>>();
Map<CharType, State> initialMap = new HashMap<CharType, State>() {{
put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
put(CharType.CHAR_POINT, State.STATE_POINT_WITHOUT_INT);
put(CharType.CHAR_SIGN, State.STATE_INT_SIGN);
}};
transfer.put(State.STATE_INITIAL, initialMap);
Map<CharType, State> intSignMap = new HashMap<CharType, State>() {{
put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
put(CharType.CHAR_POINT, State.STATE_POINT_WITHOUT_INT);
}};
transfer.put(State.STATE_INT_SIGN, intSignMap);
Map<CharType, State> integerMap = new HashMap<CharType, State>() {{
put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
put(CharType.CHAR_EXP, State.STATE_EXP);
put(CharType.CHAR_POINT, State.STATE_POINT);
}};
transfer.put(State.STATE_INTEGER, integerMap);
Map<CharType, State> pointMap = new HashMap<CharType, State>() {{
put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
put(CharType.CHAR_EXP, State.STATE_EXP);
}};
transfer.put(State.STATE_POINT, pointMap);
Map<CharType, State> pointWithoutIntMap = new HashMap<CharType, State>() {{
put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
}};
transfer.put(State.STATE_POINT_WITHOUT_INT, pointWithoutIntMap);
Map<CharType, State> fractionMap = new HashMap<CharType, State>() {{
put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
put(CharType.CHAR_EXP, State.STATE_EXP);
}};
transfer.put(State.STATE_FRACTION, fractionMap);
Map<CharType, State> expMap = new HashMap<CharType, State>() {{
put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
put(CharType.CHAR_SIGN, State.STATE_EXP_SIGN);
}};
transfer.put(State.STATE_EXP, expMap);
Map<CharType, State> expSignMap = new HashMap<CharType, State>() {{
put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
}};
transfer.put(State.STATE_EXP_SIGN, expSignMap);
Map<CharType, State> expNumberMap = new HashMap<CharType, State>() {{
put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
}};
transfer.put(State.STATE_EXP_NUMBER, expNumberMap);

int length = s.length();
State state = State.STATE_INITIAL;

for (int i = 0; i < length; i++) {
CharType type = toCharType(s.charAt(i));
if (!transfer.get(state).containsKey(type)) {
return false;
} else {
state = transfer.get(state).get(type);
}
}
return state == State.STATE_INTEGER || state == State.STATE_POINT || state == State.STATE_FRACTION || state == State.STATE_EXP_NUMBER || state == State.STATE_END;
}

public CharType toCharType(char ch) {
if (ch >= '0' && ch <= '9') {
return CharType.CHAR_NUMBER;
} else if (ch == 'e' || ch == 'E') {
return CharType.CHAR_EXP;
} else if (ch == '.') {
return CharType.CHAR_POINT;
} else if (ch == '+' || ch == '-') {
return CharType.CHAR_SIGN;
} else {
return CharType.CHAR_ILLEGAL;
}
}

enum State {
STATE_INITIAL,
STATE_INT_SIGN,
STATE_INTEGER,
STATE_POINT,
STATE_POINT_WITHOUT_INT,
STATE_FRACTION,
STATE_EXP,
STATE_EXP_SIGN,
STATE_EXP_NUMBER,
STATE_END
}

enum CharType {
CHAR_NUMBER,
CHAR_EXP,
CHAR_POINT,
CHAR_SIGN,
CHAR_ILLEGAL
}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.demo.s64;

/**
* 最小路径和
* 给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
*
* 说明:每次只能向下或者向右移动一步。
*
*
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/minimum-path-sum
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {
public int minPathSum(int[][] grid) {
if (grid == null || grid.length == 0 || grid[0].length == 0) {
return 0;
}
int rows = grid.length, columns = grid[0].length;
int[][] dp = new int[rows][columns];
dp[0][0] = grid[0][0];
for (int i = 1; i < rows; i++) {
dp[i][0] = dp[i - 1][0] + grid[i][0];
}
for (int j = 1; j < columns; j++) {
dp[0][j] = dp[0][j - 1] + grid[0][j];
}
for (int i = 1; i < rows; i++) {
for (int j = 1; j < columns; j++) {
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
}
}
return dp[rows - 1][columns - 1];
}
}

代码解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.demo.s63;

/**
* 不同路径 II
* 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
*
* 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。
*
* 现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
*
* 网格中的障碍物和空位置分别用 1 和 0 来表示。
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode.cn/problems/unique-paths-ii
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
*/
public class Solution {

public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int n = obstacleGrid.length, m = obstacleGrid[0].length;
int[] f = new int[m];

f[0] = obstacleGrid[0][0] == 0 ? 1 : 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (obstacleGrid[i][j] == 1) {
f[j] = 0;
continue;
}
if (j - 1 >= 0 && obstacleGrid[i][j - 1] == 0) {
f[j] += f[j - 1];
}
}
}

return f[m - 1];
}
}