Leetcode算法相关汇总

本文章列举了一些典型计算机算法面试题,系统地总结了如何在面试时写出高质量代码,如何优化代码效率,以及分析、解决难题的常用方法。具体实现语言有Java、Python两种。算法难度以简单和中等为主,困难为辅。其中比较经典的问题有:数组中重复的数字、二维数组中的查找、替换空格、从头到尾打印链表、重建二叉树、用两个栈实现队列、斐波那契数列、青蛙跳台阶、旋转数组的最小数字、矩阵中的路径、机器人的运动范围、剪绳子问题等等。

简介

列表所有题解均由开源社区 Doocs 贡献者提供,正在逐步完善中。

写在前面

定义一个单链表

1
2
3
4
5
6
7
8
package carzyJava;
public class ListNode {
int val;
ListNode next;
ListNode(int x){
val=x;
}
}

定义一个二叉树

1
2
3
4
5
6
7
8
9
10
package carzyJava;

public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x){
val=x;
}
}

03.数组中重复的数字

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
package carzyJava;
public class Solution03 {
/*
2022-11-03
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,
但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
*/
private void swap(int[] nums,int i, int j){
int temp;
temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
public int findRepeatNums(int[] nums){
for(int i=0;i<nums.length;i++) {
while (i!=nums[i]) {
if (nums[i] == nums[nums[i]]) {
return nums[i];
}
swap(nums, i, nums[i]);
}
}
return -1;
}
/*暴力解法
先排序再比较i和i+1位置数字是否一样
**/
public void bubbleSort(int[] nums) {
if (nums == null) {
throw new NullPointerException();
}
for (int i = 0; i < nums.length - 1; i++) {
for (int j = 0; j < nums.length - i - 1; j++) {
if (nums[j] > nums[j + 1]) {
swap(nums,j+1,j);
}
}
}
}
public int findRepeatNumsIndex(int[] nums){
for(int i=0;i<nums.length;i++){
if(nums[i]==nums[i++]) return nums[i];
}
return -1;
}

public static void main(String[] args) {
int[] nums={2,4,5,2,0,1};
System.out.print(new Solution03().findRepeatNums(nums));
}
}

04.二维数组中的查找

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 carzyJava;

public class Solution04 {
/*
2022-11-03
https://github.com/doocs/leetcode/tree/main/lcof
https://github.com/doocs
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,
每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,
输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false。
解题思路,右上角/左下角类比二叉排序树
*/
public boolean findNumIn2DArray(int[][] matrix,int target){
int m=matrix.length;
int n=matrix[0].length;
for(int i=0,j=n-1;i<m-1&&j>=0;){
if(matrix[i][j]>target){
j--;
} else if (matrix[i][j]<target) {
i++;
}else {
return true;
}
}
return false;
}
}

05.替换空格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package carzyJava;

public class Solution05 {
/*
替换空格题目描述
请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
示例 1:
输入:s = "We are happy."
输出:"We%20are%20happy."
*/
public String replaceString(String str){
return str.replaceAll(" ","%20");
}
public static void main(String[] args) {
String newStr=new Solution05().replaceString("Long time no see");
System.out.println(newStr);
}
}

06.从尾到头打印链表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package carzyJava;

public class Solution06 {
/* 2022-11-03
从尾到头打印链表
题目描述
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 1:
输入:head = [1,3,2]
输出:[2,3,1]
*/
public int[] reverLink(ListNode head){
int n=0;
for(ListNode cur=head;head!=null;cur=cur.next,n++){
}
int array[]=new int[n];

for(ListNode cur=head;cur!=null;cur=cur.next){
array[--n]=cur.val;
}

return array;
}
}

07.重建二叉树

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 carzyJava;
import java.util.Arrays;
public class Solution07 {
/*2022-11-04
https://github.com/doocs/leetcode/blob/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9807.%20%E9%87%8D%E5%BB%BA%E4%BA%8C%E5%8F%89%E6%A0%91/README.md
重建二叉树
题目描述
输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。
假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/comments/
*/
public TreeNode buildTree(int[] preOrder,int[] inOrder){
TreeNode root=new TreeNode(preOrder[0]);
if(preOrder.length==0||inOrder.length==0){
return null;
}
for(int i=0;i<inOrder.length;i++){
if(preOrder[0]==inOrder[i]){
root.left=buildTree(Arrays.copyOfRange(preOrder,1,i+1),Arrays.copyOfRange(inOrder,0,i));
root.right=buildTree(Arrays.copyOfRange(preOrder,i+1,preOrder.length),Arrays.copyOfRange(inOrder,i+1,inOrder.length));
break;
}
}
return root;
}
}

09.用两个栈实现队列

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
package carzyJava;

import java.util.Stack;

public class Solution09 {
/* 2022-11-04
用两个栈实现队列题目描述
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,
分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
示例 1:
输入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
输出:[null,null,3,-1]

示例 2:
输入:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]
两个栈,一个负责输入,一个负责输出;
执行输入时,只放入输入栈中;
执行输出时,将输入栈的所有元素依次出栈,放入输出栈中;
根据栈的特点,处于输入栈栈底的元素,在输出栈中便是栈顶;
只有输出栈中没有元素时才进行倒放,而非每一次。
*/
//输入栈
Stack<Integer> stk1=new Stack<Integer>();
//输出栈
Stack<Integer> stk2=new Stack<Integer>();
public void appendTail(int value){
stk1.push(value);
}

public int deleteHead(){
if(stk2.isEmpty()){
while (!stk1.isEmpty()){
stk2.push(stk1.pop());
}

}
return stk2.isEmpty()?-1:stk2.pop();
}
}

10- I.斐波那契数列

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
package carzyJava;

public class Solution10_1 {
/*2022-11-04
写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:

F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

*/
public static int fib(int n){
int a=0,b=1;
int i=0;
while(i<n){
int c=(a+b)%1000000007;
a=b;
b=c;
i++;
}
return a;
}

public static void main(String[] args) {
System.out.println(fib(5));
}
}

10- II.青蛙跳台阶问题

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
package carzyJava;

public class Solution10_2 {
/*2022-11-04
青蛙跳台阶问题
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

解题思路:青蛙位于f(n)级台阶时,之前可以是在f(n-1),也可以在f(n-2),即转化为为斐波那契数列问题。
*/
public int fib(int steps){
int[] array={0,1};
if(steps<2) return array[steps];
int first=0,second=1;
int sums=0;
for(int i=2;i<=steps;i++){
sums=(first+second)%1000000007;
first=sums;
second=first;
}
return sums;
}

}

11.旋转数组的最小数字

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
package carzyJava;

public class Solution11 {
/*
旋转数组的最小数字 2022-11-04
题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
给你一个可能存在 重复 元素值的数组 numbers ,它原来是一个升序排列的数组,
并按上述情形进行了一次旋转。请返回旋转数组的最小元素。
例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一次旋转,该数组的最小值为1。
示例 1:
输入:[3,4,5,1,2]
输出:1
示例 2:
输入:[2,2,2,0,1]
输出:0
https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array-ii/comments/
*/
public static int findMinNums(int[] arrays){
int low=0,high=arrays.length-1;
int mid=0;

while(low<high){
mid=low+(high-low)/2;
if(arrays[mid]<arrays[high]){
high=mid;
}else if(arrays[mid]>arrays[high]){
low=mid+1;
}else {
high--;
}
}
return arrays[low];
}
}

12.矩阵中的路径

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
package carzyJava;

import com.sun.org.apache.bcel.internal.generic.RETURN;

import java.util.Arrays;

public class Solution12 {
/*2022-11-05
矩阵中的路径 题目描述
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。
示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

https://leetcode.cn/problems/word-search/solution/shen-du-you-xian-sou-suo-yu-hui-su-xiang-jie-by-ja/
*/
char[][] charSet;
boolean[][] used; //标记是否已经被使用
int row,col;
//分别表示上、下、左、右移动
int[][] direction={ {-1,0},{1,0},{0,-1},{0,1} };
char[] strtoChar;
public boolean ifExist(char[][] charSet,String str){
this.used=new boolean[charSet.length][charSet[0].length];
for (boolean[] a:used) {
Arrays.fill(a,false);
}
this.charSet=charSet;
this.strtoChar=str.toCharArray();//目标字符转化成数组
this.row=charSet.length;
this.col=charSet[0].length;
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(charSet[i][j]==strtoChar[0]){
used[i][j]=true;
if(DFS(i,j,1)){
return true;
}else{
return false;
}

}
}
}
return false;
}

public boolean DFS(int i,int j,int depth){
if(strtoChar.length==depth)
return true;
for (int[] arr:direction) {
int newX=i+arr[0]; //行坐标
int newY=j+arr[1]; //列坐标

//剪枝操作
if(!inArea(newX,newY))
continue;
if(isUsed(newX,newY))
continue;
if(charSet[newX][newY]!=strtoChar[depth])
continue;
used[newX][newY]=true;
if(DFS(newX,newY,depth+1))
return true;
else{
used[newX][newY]=false;
}
}
return false;
}

public boolean inArea(int i,int j){
if(i<0||i>=row||j<0||j>=col){
return false;
}
return true;
}
public boolean isUsed(int i,int j){
if(used[i][j]==false)
return false;
return true;
}

public static void main(String[] args) {
char[][] chars=new char[][]{
{'A','B','C','E'},
{'S','F','C','S'},
{'A','D','E','E'}
};
String target="ABFDA";
boolean isExit=new Solution12().ifExist(chars,target);
System.out.println(isExit);
}

}

13.机器人的运动范围

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
package carzyJava;

import java.util.Arrays;

public class Solution13 {
/*机器人的运动范围 2022-11-04
题目描述
地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,
它每次可以向左、右、上、下移动一格(不能移动到方格外),
也不能进入行坐标和列坐标的数位之和大于k的格子。
例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。
但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
1 <= n,m <= 100
0 <= k <= 20
示例 1:
输入:m = 2, n = 3, k = 1
输出:3

示例 2:
输入:m = 3, n = 1, k = 0
输出:1
*/
int row,col;//行数、列数

boolean[][] used;
int nums;

public int getRobotMoveNums(int row,int col,int k){
this.row=col;
this.col=col;
this.used=new boolean[row][col];
for (boolean[] b:used) {
Arrays.fill(b,false);
}
int i=0,j=0;
return DFS(i,j,k);
}

public int DFS(int i,int j,int k){
if(isMoreThanK(i,j,k)||i>=row||j>=col||used[i][j]) {
return 0;
}else{
used[i][j] = true;
return 1+DFS(i+1,j,k)+DFS(i,j+1,k);
}
}

public boolean isMoreThanK(int i,int j,int k){
if(((i%10)+(i/10)+(j%10)+(j/10))>k){
return true;
}
return false;
}


public static void main(String[] args) {
System.out.println(new Solution13().getRobotMoveNums(2,3,1));
}

}

14- I.剪绳子

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
package carzyJava;

public class Solution14_1 {
/* 剪绳子 2022-11-05
题目描述
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m-1] 。
请问 k[0]*k[1]*...*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
示例 1:
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
示例 2:
输入: n = 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。

或者 给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k >= 2 ),并使这些整数的乘积最大化。
返回 你可以获得的最大乘积 。2 <= n <= 58

*/
int power;//3的幂指数
int tempNums;
public int getMaxProduct(int nums){
this.power=0;//3的幂指数
this.tempNums=0;
if(nums>3){
while(tempNums<=nums){
if(nums-tempNums>=3) power++;
tempNums+=3;
}
if((nums-power*3)==0){
return (int) (Math.pow(3,power));
} else if ((nums-power*3)==2) {
return (int) (Math.pow(3,power)*2);
}else if((nums-power*3)==1){
return (int) (Math.pow(3,power-1)*4) ;
}
}

return nums-1;
}

public static void main(String[] args) {
System.out.println(new Solution14_1().getMaxProduct(10));
//System.out.println("Power是:"+power);
//System.out.println(Math.pow(2,3));
}

}

14- II.剪绳子 II

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 carzyJava;

public class Solution14_2 {
/*2022-11-05 剪绳子 II
题目描述
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m - 1] 。
请问 k[0]*k[1]*...*k[m - 1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
*/

public int cuttingRope(int n) {
if (n < 4) {
return n - 1;
}
int s1 = n / 3;
int m = n % 3;
if (m == 1) {
s1 -= 1;
m = 4;
}
long res = 1;
while (s1--> 0) {
res *= 3;
res %= 1000000007;
}
return (int) ((res * (m == 0 ? 1 : m)) % 1000000007);
}

}

15.二进制中 1 的个数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package carzyJava;

public class Solution15 {
/*2022-11-05 二进制中 1 的个数
编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为 汉明重量).)
https://leetcode.cn/problems/number-of-1-bits/comments/
*/
public int getHammingWeight(int n){
int nums=0;
while(n!=0){
n=n&(n-1);
nums++;
}
return nums;
}

public static void main(String[] args) {
System.out.println(new Solution15().getHammingWeight(11));
}
}

16.数值的整数次方

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 carzyJava;

public class Solution16 {
/* 数值的整数次方
题目描述
实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。
*/
public int pow(int x,int n){
int nums=1;
for(int i=1;i<=n;i++){
nums*=x;
}
return nums;
}

public double myPow1(double x, int n) {
if (n == 0) return 1;
if (n == 1) return x;
if (n == -1) return 1 / x;
double half = myPow1(x, n / 2);
return half * half * myPow1(x, n % 2);
}

public double myPow2(double x, int n) {
if (n == 0) {
return 1.0;
} else if ((n & 1) == 0) {
return myPow2(x * x, n / 2);
} else {
return (n > 0 ? x : 1.0 / x) * myPow2(x * x, n / 2);
}
}

public static void main(String[] args) {
System.out.println(new Solution16().pow(2,10));
}

}

17.打印从 1 到最大的 n 位数

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 carzyJava;

public class Solution17 {
/* 2022-11-06
打印从 1 到最大的 n 位数
题目描述
输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。

示例 1:
输入: n = 1
输出: [1,2,3,4,5,6,7,8,9]


说明:
用返回一个整数列表来代替打印
n 为正整数
*/
public void printNums(int n){
int length=(int)Math.pow(10,n)-1;
int[] arrays=new int[length];
for (int i=0;i<length;i++) {
arrays[i]=i+1;
}
for (int index:arrays) {
System.out.print(index+" ");
}
}

public static void main(String[] args) {
new Solution17().printNums(2);
}
}

18.删除链表的节点

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
package carzyJava;

public class Solution18 {
/* 删除链表的节点 2022-11-06
题目描述:给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
返回删除后的链表的头节点。
说明:
题目保证链表中节点的值互不相同

示例 1:
输入: head = [4,5,1,9], val = 5
输出: [4,1,9]
解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
*/
public ListNode deleteListNode(ListNode root, int nums){
ListNode front=null;
ListNode cur=null;
if(root.val==nums){
root=root.next;
return root;
}
for (cur=root,front=root;cur!=null;cur=cur.next) {
if (cur.val != nums) {
front = cur;
} else {
break;
}

}

return front;
}
public ListNode creatListNode(int[] nums){
int length=nums.length;
ListNode root=new ListNode(nums[0]);
ListNode cur=null;
cur=root;
for (int i=1;i<length;i++) {
cur.next.val = nums[i];
cur=cur.next;
}
return root;
}

public static void main(String[] args) {
int[] arrays={12,34,43,54,645,45};
}
}

20.表示数值的字符串

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
package carzyJava;

public class Solution20 {
/*
提示:
1 <= s.length <= 20
s 仅含英文字母(大写和小写),数字(0-9),加号 '+' ,减号 '-' ,空格 ' ' 或者点 '.' 。
https://github.com/doocs/leetcode/blob/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9820.%20%E8%A1%A8%E7%A4%BA%E6%95%B0%E5%80%BC%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2/README.md
解法
遍历字符串:
出现 +/- 时,位置必须是在第 0 位,或者 e/E 的后面一位
出现 . 时,在此之前不能出现 . 或者 e/E
出现 e/E 时,前面不能出现 e/E,并且必须出现过数字
*/
public boolean isNumbers(String string){
String str=string.trim();//删除前后空格
char[] chars=str.toCharArray();
boolean findE=false;
boolean findDot=false;
boolean findNums=false;
for (int i=0;i<chars.length;i++) {
//判断是否遇到了+-符号
if (chars[i]=='+'||chars[i]=='-') {
//如果在字符串中间非开头位置遇到+-符号,并且前面没有E/e符号,则该字符串不是数字
if (chars[i]!=0&&chars[i-1]!='E'&&chars[i-1]!='e') {
return false;
}
} else if (chars[i]>='0'&&chars[i]<='0') { //匹配到数字
findNums=true;
} else if (chars[i]=='.') { //匹配到小数点
if (findDot||findE) { //如果之前发现过小数点或者有E/e
return false;
}
findDot=true;
} else if (chars[i]=='E'||chars[i]=='e') { //匹配到十进制E或者e
if (findE||!findNums) {
return false;
}
findE=true;
findNums=false;//E或者e后面需要数字重新出现,刷新状态
}
}
return findNums;
}

}

21.调整数组顺序使奇数位于偶数前面

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
package carzyJava;

public class Solution20 {
/*
提示:
1 <= s.length <= 20
s 仅含英文字母(大写和小写),数字(0-9),加号 '+' ,减号 '-' ,空格 ' ' 或者点 '.' 。
https://github.com/doocs/leetcode/blob/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9820.%20%E8%A1%A8%E7%A4%BA%E6%95%B0%E5%80%BC%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2/README.md
解法
遍历字符串:
出现 +/- 时,位置必须是在第 0 位,或者 e/E 的后面一位
出现 . 时,在此之前不能出现 . 或者 e/E
出现 e/E 时,前面不能出现 e/E,并且必须出现过数字
*/
public boolean isNumbers(String string){
String str=string.trim();//删除前后空格
char[] chars=str.toCharArray();
boolean findE=false;
boolean findDot=false;
boolean findNums=false;
for (int i=0;i<chars.length;i++) {
//判断是否遇到了+-符号
if (chars[i]=='+'||chars[i]=='-') {
//如果在字符串中间非开头位置遇到+-符号,并且前面没有E/e符号,则该字符串不是数字
if (chars[i]!=0&&chars[i-1]!='E'&&chars[i-1]!='e') {
return false;
}
} else if (chars[i]>='0'&&chars[i]<='0') { //匹配到数字
findNums=true;
} else if (chars[i]=='.') { //匹配到小数点
if (findDot||findE) { //如果之前发现过小数点或者有E/e
return false;
}
findDot=true;
} else if (chars[i]=='E'||chars[i]=='e') { //匹配到十进制E或者e
if (findE||!findNums) {
return false;
}
findE=true;
findNums=false;//E或者e后面需要数字重新出现,刷新状态
}
}
return findNums;
}
}

22.链表中倒数第 k 个节点

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
package carzyJava;

public class Solution22 {
/*链表中倒数第 k 个节点 2022-11-06
题目描述
输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。
例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。

示例:
给定一个链表: 1->2->3->4->5, 和 k = 2.
返回链表 4->5.
解法
定义快慢指针 slow、fast,初始指向 head。
fast 先向前走 k 步,接着 slow、fast 同时向前走,当 fast 指向 null 时,slow 指向的节点即为链表的倒数第 k 个节点。
*/
public ListNode getReverseK(ListNode root, int k){
ListNode fast=root;
ListNode slow=root;
int step=0;
while(step!=k){
fast=fast.next;
step++;
}
while(fast!=null){
fast=fast.next;
slow=slow.next;
}

return slow;
}
}

24.反转链表

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 carzyJava;

public class Solution24 {
/*2022-11-06
反转链表 题目描述
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

解法
定义指针 pre,cur 分别指向 null 和头节点。
遍历链表,将 cur.next 临时保存到 t 中,然后改变指针 cur 指向的节点的指向,将其指向 pre 指针指向的节点,即 cur.next = pre。然后 pre 指针指向 cur,cur 指针往前走。
当遍历结束后,返回 pre 指针即可。
*/
public ListNode reverseList(ListNode root){
ListNode pre=null;
ListNode cur=root;
ListNode temp=null;
while (cur!=null){
temp=cur.next;
cur.next=pre;
pre=cur;
cur=temp;

}
return pre;
}
}

相关文档

1
2
3
https://github.com/doocs/leetcode
https://github.com/doocs/leetcode/blob/main/lcof/README.md
https://github.com/juliali/ProgrammingFirstStep