修改LeetCode目录结构,不分类

This commit is contained in:
whaifree 2024-10-28 14:49:49 +08:00
parent aee514923d
commit 7ea67e280f
229 changed files with 20403 additions and 5 deletions

View File

@ -0,0 +1,69 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/26 13:30
* @注释
*/
public class AbsoluteBeiBao {
@Test
public void test() {
int[] weight = {1, 3, 4};
int[] value = {15, 20, 30};
int capacity = 4;
System.out.println(absoluteBeiBaoOneD(weight, value, capacity));
}
/**
* 使用动态规划解决背包问题求解在给定背包容量下能够获得的最大价值
* @param weight 物品的重量数组
* @param value 物品的价值数组
* @param capacity 背包的容量
*/
public int absoluteBeiBao(int[] weight, int[] value,int capacity) {
int length = weight.length;
int[][] dp = new int[length + 1][capacity + 1];
// 初始化动态规划数组
// dp[i][j] 表示在前 i 个物品0-(i-1)背包容量为 j 的情况下的最大价值
for (int i = 1; i <= length; i++) { //
for (int j = 1; j <= capacity; j++) {
if (j >= weight[i-1]) {
// 当前物品重量小于等于背包容量时考虑放入当前物品
// 完全背包二维数组的代码跟一维只有下面一个下标不同
// 那就是放i这个选择因为是可以重复放的所以是dp[i]
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - weight[i-1]] + value[i-1]);
}else {
// 当前物品重量大于背包容量无法放入维持前一个状态
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[length][capacity];
}
public int absoluteBeiBaoOneD(int[] weight, int[] value,int capacity) {
int length = weight.length;
int[] dp = new int[capacity + 1];
// 初始化动态规划数组
// dp[i][j] 表示在前 i 个物品0-(i-1)背包容量为 j 的情况下的最大价值
// dp[j] 表示前i个物品中背包容量为j的最大价值
for (int i = 1; i <= length; i++) { //
for (int j = weight[i - 1]; j <= capacity; j++) {
dp[j] = Math.max(dp[j], dp[j - weight[i - 1]] + value[i - 1]);
}
}
return dp[capacity];
}
}

View File

@ -0,0 +1,205 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/12 16:53
* @注释
*/
public class BeiBao {
@Test
public void main() {
//
// new Thread(() -> {
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
// }).start();
//
// new Thread(() -> {
//
// }).start();
//
//
// String a = "a";
//
// String b = new String("a");
//
// System.out.println(a == b);
int[] weight = {1,3,4};
int[] value = {15,20,30};
int bagSize = 4;
new Solution2().packageProblem(weight, value, bagSize);
}
class Solution{
/**
*
*
* <br/>
* <img src='https://code-thinking-1253855093.file.myqcloud.com/pics/2021011010314055.png' />
*
* @param weights 每个物品的重量
* @param values 每个物品的价值
* @param carryNumber 允许携带的数量
* @return 价值
*/
public int packageProblem(int[] weights, int[] values, int carryNumber) {
/**
* 重量 价值
* 物品0 1 15
* 物品1 3 20
* 物品2 4 30
*/
// dp[i][j] i表示携带的产品j表示容量为j的背包 dp[i][j]为从0-i个产品里取最大的价值
// 1. 不放物品i的最大价值dp[i][j] = dp[i-1][j] 不放物品i所以i不占重量所以不用-weight[i]
// 2. 放物品i的最大价值 dp[i-1][j-weight[i]] + value[i] 如果放了物品i那最大价值就 不放物品i的最大价值+物品i的价值j-weight[i] 表示放i需要腾出来空间
// dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最大价值注意是不放物品i所以要减去weight[i]
// dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 不放物品的价值 加上i物品的价值
// 初始化如果容量为0最大价值都为0如果容量为123只能放物品0的时候最大价值都是15
int goodsNumber = weights.length;
int[][] dp = new int[goodsNumber][carryNumber + 1];
// 把第0个物品进行初始化前提是能够放入第0个物品
for (int i = weights[0]; i < carryNumber + 1; i++) {
dp[0][i] = values[0];
}
/**
* 先遍历物品再遍历背包
*/
for (int i = 1; i < goodsNumber; i++) {
for (int j = 1; j < carryNumber + 1; j++) {
if (weights[i] > j) {
// 物品i放不进背包容量为j的背包
dp[i][j] = dp[i - 1][j];
}else {
// 能放进去
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weights[i]] + values[i]);
}
}
}
// 打印dp数组
for (int i = 0; i < goodsNumber; i++) {
for (int j = 0; j <= carryNumber; j++) {
System.out.print(dp[i][j] + "\t");
}
System.out.println("\n");
}
return dp[weights.length - 1][carryNumber];
}
}
class Solution1{
/**
* dp[i][j] i表示商品j表示空间 dp[i][j]表示 容量为j为包裹从0-i个商品中取得最大值
*
* 初始化
* 0 1 2 3 4 5 包容量
* 物品0 0 0 2 2 2 2
* 物品1 0
* 物品2 0
*
* dp[i][j] 表示从下标为[0-i]的物品里任意取放进容量为j的背包价值总和最大是多少
*
* @param weights 物品的重量
* @param values 物品的价值
* @param carryNumber 可以携带的数量
* @return
*/
public int packageProblem(int[] weights, int[] values, int carryNumber) {
int length = weights.length;
int[][] dp = new int[length][carryNumber + 1];
for (int i = 0; i < length; i++) {
dp[i][0] = 0;
}
for (int i = weights[0]; i <= carryNumber; i++) {
dp[0][i] = values[0];
}
// 如果i 不放东西 dp[i][j] = dp[i-1][j]
// 如果i 放东西 dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i]]-value[i])
// i为商品j为容量
for (int i = 1; i < length; i++) {
for (int j = 1; j <= carryNumber; j++) {
if (weights[i] > j) {
// 重量太大放不进去
dp[i][j] = dp[i - 1][j];
}else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weights[i]] + values[i]);
}
}
}
return dp[length - 1][carryNumber];
}
}
class Solution2{
/**
*
* dp[i][j] 表示从下标为[0-i]的物品里任意取放进容量为j的背包价值总和最大是多少
* dp[j] 表示容量为j的背包的最大价值总和
*
* 初始化
* 0 1 2 3 4 5 包容量
* 物品0 0 0 2 2 2 2
* 物品1 0
* 物品2 0
*
* 不放这个商品 那价值不变还是dp[j]
* dp[j] = max(dp[j] , dp[j-weight[i]]+value[i]])
*
* @param weights 物品的重量
* @param values 物品的价值
* @param carryNumber 可以携带的数量
* @return
*/
public int packageProblem(int[] weights, int[] values, int carryNumber) {
int length = weights.length;
int[] dp = new int[carryNumber + 1];
// 不放这个商品 那价值不变还是dp[j]
// dp[j] = max(dp[j] , dp[j-weight[i]]+value[i]])
// i为商品j为容量
for(int i = 0; i < length; i++) { // 遍历物品
for(int j = carryNumber ;j >= weights[i]; j--) { // 遍历背包容量
dp[j] = Math.max(dp[j], dp[j - weights[i]] + values[i]);
}
/**
* 倒序遍历是为了保证物品i只被放入一次但如果一旦正序遍历了那么物品0就会被重复加入多次
*
* 举一个例子物品0的重量weight[0] = 1价值value[0] = 15
* 如果正序遍历
* dp[1] = dp[1 - weight[0]] + value[0] = 15
* dp[2] = dp[2 - weight[0]] + value[0] = 30
*
* 此时dp[2]就已经是30了意味着物品0被放入了两次所以不能正序遍历
*/
}
return dp[carryNumber];
}
}
}

View File

@ -0,0 +1,56 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
import java.util.Scanner;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/27 12:45
* @注释
*/
public class KaMa47 {
@Test
public void test()
{
int i = new Solution().plt(3, 2);
System.out.println(i);
}
/* https://kamacoder.com/problempage.php?pid=1067
*/
class Solution{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int capacity = scanner.nextInt();
int m = scanner.nextInt();
System.out.println(plt(capacity, m));
}
/**
* @param capacity 需要n阶
* @param m 每一步可以走几个
* @return
*/
public static int plt(int capacity, int m) {
// 排列
int[] dp = new int[capacity + 1];
dp[0] = 1;
for (int j = 0; j <= capacity; j++) {
for (int i = 1; i <= m; i++) {
if (j >= i) {
dp[j] += dp[j - i];
}
}
}
return dp[capacity];
}
}
}

View File

@ -0,0 +1,67 @@
package cn.whaifree.leetCode.Graph;
import java.util.Scanner;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/23 11:29
* @注释
*/
public class Kama100 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
int b = scanner.nextInt();
int[][] input = new int[a][b];
boolean[][] visited = new boolean[a][b];
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
input[i][j] = scanner.nextInt();
}
}
int max = 0;
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
if (!visited[i][j] && input[i][j] == 1) {
visited[i][j] = true;
int in = in(input, visited, i, j) + 1; // 注意这里也是一小块陆地
max = Math.max(max, in);
}
}
}
System.out.println(max);
}
static int[][] direct = new int[][]{{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
/**
* 广度有限 用队列
* - 深入搜索 用地柜
* @param input
* @param visited
* @param x
* @param y
*/
public static int in(int[][] input, boolean[][] visited, int x, int y) {
int res = 0;
for (int i = 0; i < direct.length; i++) {
int nx = x + direct[i][0];
int ny = y + direct[i][1];
if (nx >= 0 && nx < input.length && ny >= 0 && ny < input[0].length
&& !visited[nx][ny]) {
if (input[nx][ny] == 1) {
visited[nx][ny] = true;
res += 1;
res += in(input, visited, nx, ny);
}
}
}
return res;
}
}

View File

@ -0,0 +1,85 @@
package cn.whaifree.leetCode.Graph;
import java.util.Scanner;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/23 12:00
* @注释
*/
public class Kama101 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
int b = scanner.nextInt();
int[][] input = new int[a][b];
boolean[][] visited = new boolean[a][b];
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
input[i][j] = scanner.nextInt();
}
}
// 在边缘处进入一旦为1才进入边缘陆地全部进入
for (int i = 0; i < a; i++) {
if (input[i][0] == 1) {
in(input, i, 0);
}
if (input[i][b - 1] == 1) {
in(input, i, b - 1);
}
}
for (int j = 0; j < b; j++) {
if (input[0][j] == 1) {
in(input, 0, j);
}
if (input[a - 1][j] == 1) {
in(input, a - 1, j);
}
}
res = 0;// 重新开始计数
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
if (input[i][j] == 1) {
in(input, i, j);
}
}
}
System.out.println(res);
}
static int res = 0;
static int[][] direct = new int[][]{{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
/**
* 广度有限 用队列
* - 深入搜索 用地柜
*
*
* 孤岛 所有单元格都不接触边缘的岛屿
*
* 从周边找到陆地然后 通过 dfs或者bfs
* 将周边靠陆地且相邻的陆地都变成海洋
* 然后再去重新遍历地图 统计此时还剩下的陆地就可以了
* @param input
* @param x
* @param y
*/
public static void in(int[][] input, int x, int y) {
input[x][y] = 0;
res++;
for (int i = 0; i < direct.length; i++) {
int nx = x + direct[i][0];
int ny = y + direct[i][1];
if (nx >= 0 && nx < input.length && ny >= 0 && ny < input[0].length) {
if (input[nx][ny] == 1) {
in(input, nx, ny);
}
}
}
}
}

View File

@ -0,0 +1,99 @@
package cn.whaifree.leetCode.Graph;
import java.util.Scanner;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/23 12:52
* @注释
*/
public class Kama102 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
int b = scanner.nextInt();
int[][] input = new int[a][b];
boolean[][] visited = new boolean[a][b];
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
input[i][j] = scanner.nextInt();
}
}
// 在边缘处进入一旦为1才进入边缘陆地全部进入
for (int i = 0; i < a; i++) {
if (input[i][0] == 1) {
in(input, i, 0);
}
if (input[i][b - 1] == 1) {
in(input, i, b - 1);
}
}
for (int j = 0; j < b; j++) {
if (input[0][j] == 1) {
in(input, 0, j);
}
if (input[a - 1][j] == 1) {
in(input, a - 1, j);
}
}
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
if (input[i][j] == 1) {
input[i][j] = 0; // 孤岛沉没
} else if (input[i][j] == 2) {
input[i][j] = 1;
}
}
}
for (int i = 0; i < input.length; i++) {
for (int j = 0; j < input[0].length; j++) {
System.out.print(input[i][j] + " ");
}
System.out.println();
}
}
/**
* 步骤一深搜或者广搜将地图周边的 1 陆地全部改成 2 特殊标记
*
* 步骤二将水域中间 1 陆地全部改成 水域0
*
* 步骤三将之前标记的 2 改为 1 陆地
*/
static int res = 0;
static int[][] direct = new int[][]{{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
/**
* 广度有限 用队列
* - 深入搜索 用地柜
*
*
* 孤岛 所有单元格都不接触边缘的岛屿
*
* 从周边找到陆地然后 通过 dfs或者bfs
* 将周边靠陆地且相邻的陆地都变成海洋
* 然后再去重新遍历地图 统计此时还剩下的陆地就可以了
* @param input
* @param x
* @param y
*/
public static void in(int[][] input, int x, int y) {
input[x][y] = 2;
res++;
for (int i = 0; i < direct.length; i++) {
int nx = x + direct[i][0];
int ny = y + direct[i][1];
if (nx >= 0 && nx < input.length && ny >= 0 && ny < input[0].length) {
if (input[nx][ny] == 1) {
in(input, nx, ny);
}
}
}
}
}

View File

@ -0,0 +1,57 @@
package cn.whaifree.leetCode.String;
import org.junit.Test;
/**
* 字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面给定一个字符串 s 和一个正整数 k请编写一个函数将字符串中的后面 k 个字符移到字符串的前面实现字符串的右旋转操作
*
* 例如对于输入字符串 "abcdefg" 和整数 2函数应该将其转换为 "fgabcde"
*
* 输入输入共包含两行第一行为一个正整数 k代表右旋转的位数第二行为字符串 s代表需要旋转的字符串
*
* 输出输出共一行为进行了右旋转操作后的字符串
*/
public class Kama55 {
@Test
public void test() {
String s = "abcdefg";
int k = 2;
String result = new Solution().reverse(s, k);
System.out.println(result);
}
public static void main(String[] args) {
}
class Solution{
/**
* 逆转
* abcde 2
* cbaed 两个区间分别逆转
* deabc 整体逆转
* @param s
* @param target
* @return
*/
public String reverse(String s, int target) {
StringBuilder stringBuilder = new StringBuilder(s);
reverseString(stringBuilder, 0, target - 1);
reverseString(stringBuilder, target, stringBuilder.length() - 1);
reverseString(stringBuilder, 0, stringBuilder.length() - 1);
return stringBuilder.toString();
}
public void reverseString(StringBuilder stringBuilder,int start, int end) {
while (start < end) {
char tmp = stringBuilder.charAt(start);
stringBuilder.setCharAt(start, stringBuilder.charAt(end));
stringBuilder.setCharAt(end, tmp);
start++;
end--;
}
}
}
}

View File

@ -0,0 +1,65 @@
package cn.whaifree.leetCode.Graph;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/17 16:26
* @注释
*/
public class Kama99 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int a = scanner.nextInt();
int b = scanner.nextInt();
int[][] input = new int[a][b];
boolean[][] visited = new boolean[a][b];
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
input[i][j] = scanner.nextInt();
}
}
int res = 0;
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
if (!visited[i][j] && input[i][j] == 1) {
// 没有走过的节点+为陆地1
res++;
method(input, visited, i, j);
}
}
}
System.out.println(res);
}
public static int method(int[][] input, boolean[][] looking, int x, int y) {
int[][] dir = {{0, 1}, {1, 0}, {-1, 0}, {0, -1}}; // 表示四个方向
int res = 0;
int[] item = new int[]{x, y};
looking[x][y] = true;
Deque<int[]> queue = new LinkedList<>();
queue.add(item);
while (!queue.isEmpty()) {
int[] pop = queue.pop();
int x1 = pop[0];
int y1 = pop[1];
for (int i = 0; i < 4; i++) {
int nextX = x1 + dir[i][0];
int nextY = y1 + dir[i][1];
if (nextX >= 0 && nextX < input.length && nextY >= 0 && nextY < input[0].length) {
if (!looking[nextX][nextY] && input[nextX][nextY] == 1) { // 只有1才遍历这样就可以保证只在小岛屿内
// 下一次的节点没有遍历过并且为1
queue.add(new int[]{nextX, nextY});
looking[nextX][nextY] = true; // 进入队列就标志看过了
}
}
}
}
return res;
}
}

View File

@ -0,0 +1,62 @@
package cn.whaifree.leetCode.Graph;
import java.util.Scanner;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/19 16:44
* @注释
*/
public class Kama99_2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int[][] grid = new int[m][n];
boolean[][] visited = new boolean[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
grid[i][j] = sc.nextInt();
}
}
int res = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (!visited[i][j] && grid[i][j] == 1) {
res++;
visited[i][j] = true;
depth(grid, visited, i, j);
}
}
}
System.out.println(res);
}
static int[][] direct = new int[][]{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
public static void depth(int[][] map, boolean[][] visited, int x, int y) {
// 深度优先
for (int i = 0; i < 4; i++) {
int[] ints = direct[i];
int nextX = x + ints[0];
int nextY = y + ints[1];
if (nextX < 0 || nextX >= map.length || nextY < 0 || nextY >= map[0].length) {
continue;
}
if (visited[nextX][nextY]) { // 访问过的不再访问
continue;
}
if (map[nextX][nextY] == 1) {
visited[nextX][nextY] = true;
depth(map, visited, nextX, nextY);
}
}
}
}

View File

@ -0,0 +1,49 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
import java.util.HashSet;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/15 16:37
* @注释
*/
public class LCR119 {
@Test
public void test() {
int[] nums = {100, 4, 200, 1, 3, 2};
System.out.println(new Solution().longestConsecutive(nums));
}
class Solution {
public int longestConsecutive(int[] nums) {
HashSet<Integer> set = new HashSet<>();
for (int num : nums) {
set.add(num);
}
int max = 0;
for (int num : nums) {
if (set.contains(num- 1)) { // 1 2 3 4 只要保证set里没有0
continue;
}
// int base = num;
// int tmp = 0;
// while (set.contains(base++)) {
// tmp++;
// }
// max = Math.max(max, tmp);
int maxnum = num;
while (set.contains(maxnum + 1)) {
maxnum++;
}
max = Math.max(max, maxnum - num + 1);
}
return max;
}
}
}

View File

@ -0,0 +1,46 @@
package cn.whaifree.leetCode.String;
import org.junit.Test;
public class LCR181 {
@Test
public void main()
{
Solution solution = new Solution();
String s = solution.reverseMessage(" abx ");
System.out.println(s);
}
class Solution {
public String reverseMessage(String message) {
String trim = message.trim();
String[] split = trim.split("\s+");
reverse(split);
StringBuilder stringBuilder = new StringBuilder();
for (String s : split) {
if (s.isEmpty()) {
continue;
}
stringBuilder.append(s).append(" ");
}
if (!stringBuilder.isEmpty()) stringBuilder.deleteCharAt(stringBuilder.length() - 1);
return stringBuilder.toString();
}
public void reverse(String[] strings) {
int start = 0;
int end = strings.length - 1;
while (start < end) {
swap(strings, start++, end--);
}
}
public void swap(String[] strings, int start, int end) {
String temp = strings[start];
strings[start] = strings[end];
strings[end] = temp;
}
}
}

View File

@ -0,0 +1,39 @@
package cn.whaifree.leetCode.String;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/5 11:36
* @注释
*/
public class LeetCode10 {
class Solution {
public boolean isMatch(String s, String p) {
char[] sChar = s.toCharArray();
char[] pChar = p.toCharArray();
/**
* dp[sIndex][pIndex]表示s字符串的前sIndex个字符是否和p字符串的前pIndex个字符完成正则表达式的匹配
*
* 当p字符串的第pIndex个字符不为*
* if p第pIndex个字符与s的第sIndex个字符匹配
* dp[sIndex][pIndex] =
* f[sIndex - 1][pIndex - 1](s的前sIndex - 1个字符和p的前pIndex-1个字符的匹配结果)
* 如果p第pIndex个字符与s的第sIndex个字符不匹配
* 则结果为false
* 当p字符串的第pIndex个字符为*
* 此时*前面的符号可以出现0次或任意次
* - x出现0次
* 此时结果为f[sIndex][pIndex - 2]此时相当于删除了*以及x
* - x出现非0的任意次 此时的结果为f[sIndex - 1][pIndex] && (p.charAt(pIndex - 2) == '.' || p.charAt(pIndex - 2) == s.charAt(sIndex - 1));
*
*/
return false;
}
}
}

View File

@ -0,0 +1,81 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.LinkedList;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/23 19:56
* @注释
*/
public class LeetCode100 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTree(new Integer[]{1,2,1});
TreeNode treeNode1 = TreeNode.constructTree(new Integer[]{1,1,2});
treeNode1.printTree();
treeNode.printTree();
System.out.println(new Solution1().isSameTree(treeNode, treeNode1));
}
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
} else if (p == null || q == null) {
return false;
}
// LinkedList能存null
Deque<TreeNode> deque = new LinkedList<>();
deque.add(p);
deque.add(q);
while (!deque.isEmpty()) {
// 防止只剩下一个元素如果只剩下一个元素那么一定是false
TreeNode BPop = deque.pop();
TreeNode APop = deque.pop();
if (BPop == null && APop == null) {
// 叶子节点不需要加入左右子节点
continue;
} else if (BPop != null && APop == null) {
return false;
} else if (BPop == null && APop != null) {
return false;
} else if (BPop.val != APop.val) {
return false;
}
deque.add(BPop.right);
deque.add(APop.right);
deque.add(BPop.left);
deque.add(APop.left);
}
return true;
}
}
class Solution1 {
public boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
} else if (p == null && q != null) {
return false;
} else if (p != null && q == null) {
return false;
} else if (p.val != q.val) {
return false;
}
boolean sameTreeRight = isSameTree(p.right, q.right);
boolean sameTreeLeft = isSameTree(p.left, q.left);
return sameTreeLeft && sameTreeRight;
}
}
}

View File

@ -0,0 +1,113 @@
package cn.whaifree.leetCode.Greedy;
import org.junit.Test;
import java.util.Arrays;
import java.util.Comparator;
import java.util.stream.IntStream;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/2/27 11:42
* @注释
*/
public class LeetCode1005 {
@Test
public void test() {
System.out.println(new Solution().largestSumAfterKNegations(new int[]{-2,5,0,2,-2}, 3));
System.out.println(new Solution().largestSumAfterKNegations(new int[]{4,2,3}, 1))
;
System.out.println(new Solution1().largestSumAfterKNegations(new int[]{-2,5,0,2,-2}, 3));
System.out.println(new Solution1().largestSumAfterKNegations(new int[]{4,2,3}, 1));
}
class Solution {
/**
* 注意几个例子
* 1. nums = [3,-1,0,2], k = 3 选择下标 (1, 2, 2) nums 变为 [3,1,0,2]
*
* -2,5,1,2,-2
* 按绝对值逆转 5 -2 2 -2 1
* 每次遇到负数变为相反数
* // 剩下的k如果是奇数就把最后一个逆转
*
* @param nums
* @param k
* @return
*/
public int largestSumAfterKNegations(int[] nums, int k) {
// 按绝对值从大到小排序对前k个负数进行相反数
nums = IntStream.of(nums)
.boxed()
.sorted((o1, o2) -> Math.abs(o2) - Math.abs(o1))
.mapToInt(Integer::intValue).toArray();
for (int i = 0; i < nums.length; i++) {
if (k > 0 && nums[i] < 0) {
nums[i] = -nums[i];
k--;
}
}
// 此时还有k个没减去,k为偶数则不管k为奇数就把最小那个变为正数
if (k % 2 == 1) {
nums[nums.length-1] = -nums[nums.length-1];
}
return Arrays.stream(nums).sum();
}
}
class Solution1 {
/**
* 注意几个例子
* 1. nums = [3,-1,0,2], k = 3 选择下标 (1, 2, 2) nums 变为 [3,1,0,2]
*
* -2,5,1,2,-2
* 排序
* -2 -2 1 2 5
* 逆转
* 2 2 1 2 5
* 将最下的数逆转,sum-min-min
* 2 2 -1 2 5
*
* @param nums
* @param k
* @return
*/
public int largestSumAfterKNegations(int[] nums, int k) {
// 按绝对值从大到小排序对前k个负数进行相反数
Arrays.sort(nums);
int sum = 0;
int minValue = Integer.MAX_VALUE;
for (int i = 0; i < nums.length; i++) {
if (k > 0 && nums[i] < 0) {
nums[i] = -nums[i];
k--;
}
sum += nums[i];
minValue = Math.min(minValue, nums[i]);
}
// 此时还有k个没减去,k为偶数则不管k为奇数就把最小那个变为正数
if (k % 2 == 1) {
// 减去在遍历过程中加的minValue部分和通过变换负数的部分
return sum - minValue - minValue;
}else {
return sum;
}
}
}
}

View File

@ -0,0 +1,91 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
/**
* @version 1.0
* @Author whai文海104
* @Date 2024/1/21 19:19
* @注释
*/
public class LeetCode101 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTree(new Integer[]{1, 2, 2, 3, null,null, 3});
treeNode.printTree();
System.out.println(new Solution1().isSymmetric(treeNode));
}
class Solution {
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
return compare(root.left, root.right);
}
public boolean compare(TreeNode left, TreeNode right) {
// left.left right.right递归
// left.right right.left递归
if (left == null && right == null) {
return true;
} else if (left != null && right == null) {
return false;
} else if (left == null && right != null) {
return false;
} else if (left.val != right.val) {
return false;
}
boolean outSite = compare(left.left, right.right);
boolean inSite = compare(left.right, right.left);
return outSite && inSite;
}
}
class Solution1 {
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
Deque<TreeNode> deque = new LinkedList<>();
deque.add(root.left);
deque.add(root.right);
while (!deque.isEmpty()) {
TreeNode left = deque.pop();
TreeNode right = deque.pop();
if (left == null && right == null) {
continue;
}
// else if (left == null && right != null) {
// return false;
// } else if (left != null && right == null) {
// return false;
// } else if (left.val != right.val) {
// return false;
// }
if (left == null || right == null || left.val != right.val) {
return false;
}
deque.add(left.left);
deque.add(right.right);
deque.add(left.right);
deque.add(right.left);
}
return true;
}
}
}

View File

@ -0,0 +1,90 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/16 20:37
* @注释
*/
public class LeetCode102 {
@Test
public void test() {
TreeNode root = TreeNode.constructTree(new Integer[]{3, 9, 20, null, null, 15, 7});
root.printTree();
System.out.println(new Solution1().levelOrder(root));
}
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new LinkedList<>();
if (root == null) {
return res;
}
Deque<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
// 遍历本层的个数
List<Integer> e = new ArrayList<>();
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode pop = queue.pop();
e.add(pop.val);
if(pop.left!=null) queue.add(pop.left);
if(pop.right!=null) queue.add(pop.right);
}
res.add(e);
}
return res;
}
}
class Solution1 {
List<List<Integer>> res = new LinkedList<>();
/**
* 二叉树递归层次遍历
* @param root
* @return
*/
public List<List<Integer>> levelOrder(TreeNode root) {
if (root == null) {
return res;
}
level(root, 0);
return res;
}
public void level(TreeNode root, int level) {
if (root == null) {
return;
}
List<Integer> i = null;
if (res.size() <= level) {
i = new ArrayList<>();
res.add(level, i);
} else {
i = res.get(level);
}
i.add(root.val);
level(root.left, level + 1);
level(root.right, level + 1);
}
}
}

View File

@ -0,0 +1,54 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/27 23:06
* @注释
*/
public class LeetCode103 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTreeByArray(new Integer[]{3, 9, 20, 88, 99, 15, 7, 10, 5, 1});
List<List<Integer>> lists =
new Solution().zigzagLevelOrder(treeNode);
for (List<Integer> list : lists) {
System.out.println(list);
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
if (root == null) {
return res;
}
level(root, 0, true);
return res;
}
public void level(TreeNode root, int level, boolean leftIn) {
if (root == null) {
return;
}
if (level == res.size()) {
res.add(level, new ArrayList<>());
}
if (leftIn) {
res.get(level).add(root.val);
} else {
res.get(level).add(0, root.val);
}
level(root.left, level + 1, !leftIn);
level(root.right, level + 1, !leftIn);
}
}
}

View File

@ -0,0 +1,61 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/25 11:28
* @注释
*/
public class LeetCode1035 {
@Test
public void test()
{
int[] nums1 = new int[]{1,3,7,1,7,5};
int[] nums2 = new int[]{1,9,2,5,1};
System.out.println(new Solution().maxUncrossedLines(nums1, nums2));
}
class Solution {
/**
* 不相交就是挨个求nums1的子序列在nums中出现的次数
* - 不用连续
* - 子序列
*
* dp[i][j] 表示 nums1从0-i-1nums2从0-j-1有几个相同的子序列
*
* if nums1[i] == nums2[j]
* dp[i][j] = dp[i-1][j-1]+1
* else
* dp[i][j] = dp[i-1][j-1]
*
*
* @param nums1 短的
* @param nums2 长的
* @return
*/
public int maxUncrossedLines(int[] nums1, int[] nums2) {
if (nums1.length > nums2.length) {
return maxUncrossedLines(nums2, nums1);
}
int[][] dp = new int[nums1.length + 1][nums2.length + 1];
for (int i = 1; i <= nums1.length; i++) {
for (int j = 1; j <= nums2.length; j++) {
if (nums1[i - 1] == nums2[j - 1]) {
// 对应位置相等则从i-1 j-1的值+1
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
// 对应的值不相等则获取前面已经匹配的最大值
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[nums1.length][nums2.length];
}
}
}

View File

@ -0,0 +1,99 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/21 20:05
* @注释
*/
public class LeetCode104 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTree(new Integer[]{1, 2, 2, 3, null,null,null});
treeNode.printTree();
System.out.println(new Solution2().maxDepth(treeNode));
}
class Solution {
int depth = 0;
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
level(root, 1);
return depth;
}
public void level(TreeNode treeNode, int level) {
if (treeNode == null) {
return;
}
if (level > depth) {
depth = level;
}
if (treeNode.right != null) {
level(treeNode.right, level + 1);
}
if (treeNode.left != null) {
level(treeNode.left, level + 1);
}
}
}
class Solution2{
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
return level(root);
}
public int level(TreeNode treeNode) {
if (treeNode == null) {
return 0;
}
int left = level(treeNode.left) + 1;
int right = level(treeNode.right) + 1;
return Math.max(left, right);
}
}
class Solution1 {
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
int depth = 0;
// 右视图
Deque<TreeNode> deque = new ArrayDeque<>();
deque.add(root);
while (!deque.isEmpty()) {
int size = deque.size();
for (int i = 0; i < size; i++) {
TreeNode pop = deque.pop();
if (pop.left != null) {
deque.add(pop.left);
}
if (pop.right != null) {
deque.add(pop.right);
}
}
depth++;
}
return depth;
}
}
}

View File

@ -0,0 +1,64 @@
package cn.whaifree.leetCode.Stack;
import org.junit.Test;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.LinkedList;
import java.util.function.Consumer;
public class LeetCode1047 {
@Test
public void test() {
System.out.println(new Solution1().removeDuplicates("adff"));
}
class Solution {
public String removeDuplicates(String s) {
Deque<Character> stack = new ArrayDeque<>();
char[] chars = s.toCharArray();
for (char aChar : chars) {
// 入栈前判断第一个是不是相同的
if (!stack.isEmpty() && stack.peek() == aChar) {
stack.pop();
}else {
stack.push(aChar);
}
}
char[] ans = new char[stack.size()];
for (int i = stack.size() - 1; i >=0; i--) {
ans[i] = stack.pop();
}
return new String(ans);
}
}
class Solution1 {
/**
* stringBuilder也能作为栈使用
*/
public String removeDuplicates(String s) {
// 将StringBuilder作为栈 abbacd
StringBuilder res = new StringBuilder();
int top = -1;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (res.length() != 0 && c == res.charAt(top)) {
res.deleteCharAt(top);
top--;
} else {
res.append(c);
top++;
}
}
return res.toString();
}
}
}

View File

@ -0,0 +1,114 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/18 14:31
* @注释
*/
public class LeetCode1049 {
@Test
public void test() {
int[] stones = {1,2};
int result = new Solution1().lastStoneWeightII(stones);
System.out.println(result);
}
class Solution {
/**
* 背包容量为half让其尽可能装满除非装不下了到装不下了这一部分已经装入的就是拿来碰撞的剩下就是sum-dp[half]-dp[half]
*
* 目标就是让石头的总价值分为两部分
*
* 转换为背包问题
*
* dp[j] 表示 容量为j的背包最多能够容纳多少价值的物品
* - 物品i的价值 stones[i]
* - 物品i的重量 stones[i]
*
* 1 <= stones.length <= 30
* 1 <= stones[i] <= 100
* 初始化为store[half]
*
*
* 递推公式 dp[j] = Math.max(dp[j],dp[j-weight[i]]+value[i])
* 分成两堆石头一堆石头的总重量是dp[half]另一堆就是sum - dp[half]
*
* @param stones
* @return
*/
public int lastStoneWeightII(int[] stones) {
int sum = 0;
for (int stone : stones) {
sum += stone;
}
int half = sum / 2;
int[] dp = new int[half + 1];
for (int i = 0; i < stones.length; i++) {
for (int j = half; j >= stones[i]; j--) { // 确保背包能够放下
dp[j] = Math.max(dp[j], dp[j - stones[i]] + stones[i]);
}
}
// dp[half] 是要被消灭的那两个部分的消灭就*2
return sum - dp[half] * 2;
}
}
class Solution1 {
/**
* half = sum/2
*
*
* dp[i][j] 表示 放入i后容量为j的背包的最大价值
*
* 1. 放入i dp[i][j] = dp[i-1][j-weight[i]]+value[i]
* 2. 不放入i dp[i][j] = dp[i-1][j]
*
* 2 4 1 1 target=4
*
* 0 1 2 3 4
* 0 0 0 2 2 2
* 1 0 0 2 2 2
* 2 0 1 3 3 3
* 3 0 1 4 4 4
*
* @param stones
* @return
*/
public int lastStoneWeightII(int[] stones) {
int sum = 0;
for (int stone : stones) {
sum += stone;
}
// 计算所有石头的总重量并将其的一半作为目标重量
int half = sum / 2;
int length = stones.length;
int[][] dp = new int[length][half + 1];
for (int i = stones[0]; i <= half; i++) {
dp[0][i] = stones[0];
}
for (int i = 1; i < length; i++) {
for (int j = 1; j <= half ; j++) {
if (j < stones[i]) {
// 放不下 就不放了价值为i-1物品的最大价值
// 当前石头重量大于目标重量无法放入价值等于前i-1个石头的最大价值
dp[i][j] = dp[i - 1][j];
}else {
// 取放入和不放入当前石头两种情况中的最大价值
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - stones[i]] + stones[i]);
}
}
}
// 返回石头总重量减去最接近目标重量的那堆石头的两倍重量
return sum - dp[length - 1][half] * 2;
}
}
}

View File

@ -0,0 +1,87 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/27 13:34
* @注释
*/
public class LeetCode105 {
@Test
public void test() {
TreeNode.constructTree(new Integer[]{3,9,20,1,null,15,7});
// 9 3 20 7 15
// 20 3 7 9 15
// 20 7 3 15 9
new Solution().buildTree(new int[]{3,9,1,20,15,7}, new int[]{1,9,3,15,20,7}).printTree();
}
class Solution {
Map<Integer, Integer> map = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
for (int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
return build(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
}
public TreeNode build(
int[] preorder,
int preorderStart,
int preorderEnd,
int[] inorder,
int inorderStart,
int inorderEnd
) {
if (preorderStart > preorderEnd || inorderStart > inorderEnd) {
return null;
}
int value = preorder[preorderStart];
Integer indexInInorder = map.get(value);
TreeNode node = new TreeNode(value);
// 左边的个数就是index的InInorderNumber
//只要有左边节点数量其他都好算
int leftChildNumber = indexInInorder - inorderStart;
// 前序 start的下一个 ~ start+左边的数量
// 中序 start ~ start+左边的数量-1(不包含index)
node.left = build(
preorder,
preorderStart + 1,
preorderStart + leftChildNumber,
inorder,
inorderStart,
inorderStart + leftChildNumber - 1
);
//3 9 1 20 15 7
//1 9 3 15 20 7
// 前序 start+左边的数量+1index ~ end
// 中序 左边的数量+1index ~ end
node.right = build(
preorder,
preorderStart + leftChildNumber + 1,
preorderEnd,
inorder,
indexInInorder + 1,
inorderEnd);
return node;
}
}
}

View File

@ -0,0 +1,90 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/25 21:29
* @注释
*/
public class LeetCode106 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTree(new Integer[]{3,9,20,null,null,15,7});
// 9 3 20 7 15
// 20 3 7 9 15
// 20 7 3 15 9
//9,3,15,20,7
//9,15,7,20,3
new Solution().buildTree(new int[]{9,3,15,20,7}, new int[]{9,15,7,20,3}).printTree();
}
class Solution {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
public TreeNode buildTree(int[] inorder, int[] postorder) {
if (inorder.length == 0) {
return null;
}
for (int i = 0; i < inorder.length; i++) {
map.put(inorder[i], i);
}
return circle(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1);
}
public TreeNode circle(
int[] inorder,
int inorderStart,
int inorderEnd,
int[] postorder,
int posterStart,
int posterEnd
) {
if (posterEnd < posterStart || inorderStart > inorderEnd) {
return null;
}
int lastValue = postorder[posterEnd];
TreeNode root = new TreeNode(lastValue);
// 中序中的下标
Integer index = map.get(lastValue);
// 左字树的个数
int leftChileNumber = index - inorderStart;
// 中序 start ~ start+leftnumber(即index)
// 后序 start ~ start+左边的树
root.left = circle(
inorder,
inorderStart,
index - 1,
postorder,
posterStart,
posterStart + leftChileNumber - 1);
// 中序 index+1 ~ end
// 后序 start+left ~ end-1(中序节点)
root.right = circle(
inorder,
index + 1,
inorderEnd, postorder,
posterStart + leftChileNumber,
posterEnd - 1);
return root;
}
}
}

View File

@ -0,0 +1,86 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/17 14:50
* @注释
*/
public class LeetCode107 {
@Test
public void test() {
TreeNode root = TreeNode.constructTree(new Integer[]{3,9,20,null,null,15,7});
root.printTree();
System.out.println(new Solution1().levelOrderBottom(root));
}
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> res = new LinkedList<>();
if (root == null) {
return res;
}
Deque<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
int size = queue.size();
List<Integer> e = new LinkedList<>();
for (int i = 0; i < size; i++) {
TreeNode pop = queue.pop();
e.add(pop.val);
if (pop.left != null) {
queue.add(pop.left);
}
if (pop.right != null) {
queue.add(pop.right);
}
}
// 每次都采用头插法
res.add(0,e);
}
return res;
}
}
class Solution1 {
List<List<Integer>> res = new LinkedList<>();
/**
* 二叉树递归层次遍历
* @param root
* @return
*/
public List<List<Integer>> levelOrderBottom(TreeNode root) {
if (root == null) {
return res;
}
level(root, 0);
Collections.reverse(res);
return res;
}
public void level(TreeNode root, int level) {
if (root == null) {
return;
}
int size = res.size();
if (size <= level) {
res.add(new ArrayList<>());
}
res.get(level).add(root.val);
level(root.left, level + 1);
level(root.right, level + 1);
}
}
}

View File

@ -0,0 +1,40 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/31 18:56
* @注释
*/
public class LeetCode108 {
@Test
public void test() {
new Solution().sortedArrayToBST(new int[]{1, 2, 3, 4, 5, 6, 7, 8}).printTree();
}
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
return construct(nums, 0, nums.length - 1);
}
public TreeNode construct(int[] nums, int start, int end) {
if (start > end) {
return null;
}
int middle = (end + start) / 2;
int num = nums[middle];
TreeNode root = new TreeNode(num);
root.left = construct(nums, start, middle - 1);
root.right = construct(nums, middle + 1, end);
return root;
}
}
}

View File

@ -0,0 +1,48 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/21 20:36
* @注释
*/
public class LeetCode110 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTree(new Integer[]{1,2,2,3,null,null,3,4,null,null,4});
treeNode.printTree();
System.out.println(new Solution().isBalanced(treeNode));
}
class Solution {
public boolean isBalanced(TreeNode root) {
return level(root)!=-1;
}
public int level(TreeNode root) {
if (root == null) {
return 0;
}
int leftHeight = level(root.left);
if (leftHeight == -1) {
return -1;
}
int rightDepth = level(root.right);
if (rightDepth == -1) {
return -1;
}
if (Math.abs(leftHeight - rightDepth) > 1) {
return -1;
}
return Math.max(leftHeight, rightDepth) + 1;
// return Math.abs(leftHeight - rightDepth) > 1 ? -1 : Math.max(leftHeight, rightDepth) + 1;
}
}
}

View File

@ -0,0 +1,107 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/21 20:36
* @注释
*/
public class LeetCode111 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTree(new Integer[]{1, 2, 2, 3, null,null,null,3});
treeNode.printTree();
System.out.println(new Solution2().minDepth(treeNode));
}
class Solution {
int minDepth = Integer.MAX_VALUE;
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
getDepth(root, 1);
return minDepth;
}
void getDepth(TreeNode root, int level) {
if (root == null) {
return;
}
if (root.left != null) {
getDepth(root.left, level + 1);
}
if (root.right != null) {
getDepth(root.right, level + 1);
}
// 左右子树都为空才表明已经到底部了
if (root.left == null && root.right == null && level < minDepth) {
minDepth = level;
}
}
}
class Solution1 {
public int minDepth(TreeNode root) {
return getDepth(root);
}
int getDepth(TreeNode root) {
if (root == null) {
return 0;
}
int right = getDepth(root.right) ;
int left = getDepth(root.left) ;
if (root.left == null && root.right != null) {
return right + 1;
}
if (root.right == null && root.left != null) {
return left + 1;
}
return 1 + Math.min(right, left);
}
}
class Solution2 {
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
int depth = 0;
// 右视图
Deque<TreeNode> deque = new ArrayDeque<>();
deque.add(root);
while (!deque.isEmpty()) {
int size = deque.size();
depth++;
for (int i = 0; i < size; i++) {
TreeNode pop = deque.pop();
if (pop.left != null) {
deque.add(pop.left);
}
if (pop.right != null) {
deque.add(pop.right);
}
if (pop.right == null && pop.left == null) {
// 从上到下第一个双节点非空就是输出
return depth;
}
}
}
return 0;
}
}
}

View File

@ -0,0 +1,79 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.Deque;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/24 20:59
* @注释
*/
public class LeetCode112 {
@Test
public void test(
) {
TreeNode treeNode = TreeNode.constructTree(new Integer[]{5,4,8,11,null,13,4,7,2,null,null,null,1});
treeNode.printTree();
System.out.println(new Solution1().hasPathSum(treeNode, 22));
}
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
return level(root, 0, targetSum);
}
public boolean level(TreeNode treeNode,int sum,int targetSum) {
if (treeNode == null) {
return false;
}
sum += treeNode.val;
// 最后一个必须是叶子节点
if (treeNode.left == null && treeNode.right == null && sum == targetSum) {
return true;
}
boolean left = level(treeNode.left, sum, targetSum);
boolean right = level(treeNode.right, sum, targetSum);
return left || right;
}
}
class Solution1 {
/**
* 使用队列
* @param root
* @param targetSum
* @return
*/
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) {
return false;
}
Deque<Object> queue = new java.util.ArrayDeque<>();
queue.add(root);
queue.add(root.val);
while (!queue.isEmpty()) {
TreeNode pop = (TreeNode) queue.pop();
Integer value = (Integer) queue.pop();
if (pop.right == null && pop.left == null && value == targetSum) {
return true;
}
if (pop.right != null) {
queue.add(pop.right);
queue.add(value + pop.right.val);
}
if (pop.left != null) {
queue.add(pop.left);
queue.add(value + pop.left.val);
}
}
return false;
}
}
}

View File

@ -0,0 +1,62 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/24 21:30
* @注释
*/
public class LeetCode113 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTree(new Integer[]{5,4,8,null,4});
treeNode.printTree();
System.out.println(new Solution().pathSum(treeNode, 13));
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
if (root == null) {
return res;
}
level(root, targetSum, new ArrayList<>());
return res;
}
/**
*
* @param root 节点
* @param needSum 还需要的数
* @param nowHasPath 记录已经走过的路也用于回退
*/
public void level(TreeNode root, int needSum,ArrayList<Integer> nowHasPath) {
if (root == null) {
return;
}
nowHasPath.add(root.val);
if (root.left == null && root.right == null && root.val == needSum) {
res.add(new ArrayList<>(nowHasPath));
// 回退全部交给上一次递归
}
if (root.left != null) {
level(root.left, needSum - root.val, nowHasPath);
nowHasPath.remove(nowHasPath.size() - 1);
}
if (root.right != null) {
level(root.right, needSum - root.val, nowHasPath);
nowHasPath.remove(nowHasPath.size() - 1);
}
}
}
}

View File

@ -0,0 +1,92 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/23 17:31
* @注释
*/
public class LeetCode114 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTreeByArray(new Integer[]{0, 1, 2, 3, 4, 5, 6});
new Solution().flatten(treeNode);
treeNode.printTree();
}
class Solution {
public void flatten(TreeNode root) {
if (root == null) {
return;
}
Deque<TreeNode> deque = new LinkedList<>();
deque.push(root);
TreeNode tmp = root;
while (!deque.isEmpty()) {
TreeNode pop = deque.pop();
if (pop != null) {
if (pop.right != null) {
deque.push(pop.right);
}
if (pop.left != null) {
deque.push(pop.left);
}
deque.push(pop);
deque.push(null);
}else {
TreeNode nextPop = deque.pop();
if (nextPop != tmp) {
tmp.right = nextPop;
tmp.left = null;
tmp = tmp.right;
}
}
}
}
}
@Test
public void test2() {
TreeNode treeNode = TreeNode.constructTreeByArray(new Integer[]{0, 1, 2, 3, 4, 5, 6});
new Solution2().flatten(treeNode);
treeNode.printTree();
}
class Solution2 {
public void flatten(TreeNode root) {
if (root == null) {
return;
}
subFlatten(root);
}
public TreeNode subFlatten(TreeNode root) {
TreeNode left = root.left;
TreeNode right = root.right;
TreeNode tmp = root;
root.left = null;
if (left != null) {
root.right = left;
tmp = subFlatten(left); // tmp会返回一节的最后一个尾巴节点
}
if (right != null) {
tmp.right = right; // 把前面的right拿过来再往下
tmp = subFlatten(right);
}
return tmp;
}
}
}

View File

@ -0,0 +1,52 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/24 12:00
* @注释
*/
public class LeetCode1143 {
@Test
public void test() {
Solution solution = new Solution();
int res = solution.longestCommonSubsequence("bsbininm","jmjkbkjkv" );
System.out.println(res);
}
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
// 公共子序列 dp[len1+1][len2+1]
// dp[i][j] 表示 text1的前i-1与text2的前j-1中有多长的公共子序列长度
// dp[i][j]长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j]
// if text1[i]==text2[i]
//
//
int len1 = text1.length();
int len2 = text2.length();
int[][] dp = new int[len1 + 1][len2 + 1];
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
// 如果相等
if (text1.charAt(i - 1) == text2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1] + 1;
//dp[i][j] = Math.max(dp[i][j - 1] + 1, dp[i][j]);
} else {
dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]);
// dp[i][j] = Math.max(dp[i - 1][j - 1], Math.max(dp[i - 1][j], dp[i][j - 1]));
}
}
}
return dp[len1][len2];
}
}
}

View File

@ -0,0 +1,67 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/26 11:44
* @注释
*/
public class LeetCode115 {
@Test
public void test()
{
Solution solution = new Solution();
System.out.println(solution.numDistinct("babgbag", "bag"));
}
class Solution {
public int numDistinct(String s, String t) {
/**
* dp[i][j] 以i-1为 结尾的 s子序列 中出现以j-1为 结尾的 t的个数为dp[i][j]
*
* '' b a g
* '' 1 0 0 0
* b 1 1 0 0
* a 1 1 1 0
* e 1 1 1 0
* g 1 1 1 1
* g 1 1 1 2
*
* if s[i]==t[j]
* 1. 用s[i - 1]来匹配 dp[i - 1][j - 1] bagg和bag t匹配到s的第二个g时使用第一个g
* 2. 不用第s[i - 1]来匹配 dp[i - 1][j] bagg和bag t匹配到s的第二个g时不使用第一个g
* dp[i][j] = dp[i-1][j-1]+dp[i - 1][j];
* else
* 不用s[i - 1]来匹配模拟s中删除了这个元素
* dp[i][j] = dp[i - 1][j];
*
*/
char[] sChar = s.toCharArray();
char[] tChar = t.toCharArray();
int[][] dp = new int[sChar.length + 1][tChar.length + 1];
for (int i = 0; i < sChar.length; i++) {
dp[i][0] = 1;
}
for (int i = 1; i <= sChar.length; i++) {
for (int j = 1; j <= tChar.length; j++) {
if (sChar[i - 1] == tChar[j - 1]) {
// 如果相同
// 使用i-1进行匹配 dp[i - 1][j - 1] bagg和bag t匹配到s的第二个g时使用第一个g
// 不用第s[i - 1]来匹配 dp[i - 1][j] bagg和bag t匹配到s的第二个g时不使用第一个g
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
} else {
// 不用s[i - 1]来匹配
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[sChar.length][tChar.length];
}
}
}

View File

@ -0,0 +1,115 @@
package cn.whaifree.leetCode.Tree;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/18 16:11
* @注释
*/
public class LeetCode116 {
class Node {
public int val;
public Node left;
public Node right;
public Node next;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, Node _left, Node _right, Node _next) {
val = _val;
left = _left;
right = _right;
next = _next;
}
public void setLeft(Node left) {
this.left = left;
}
public void setRight(Node right) {
this.right = right;
}
};
@Test
public void test() {
Node node = new Node(1);
node.left = new Node(2);
node.right = new Node(3);
node.left.left = new Node(4);
node.left.right = new Node(5);
node.right.left = new Node(6);
node.right.right = new Node(7);
System.out.println(new Solution1().connect(node));
}
class Solution {
public Node connect(Node root) {
if (root == null) {
return null;
}
Deque<Node> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
Node pop = queue.pop();
// 防止把下一层的节点赋值为next
if (i < size - 1) {
pop.next = queue.peek();
}
if (pop.left != null) {
queue.add(pop.left);
}
if (pop.right != null) {
queue.add(pop.right);
}
}
}
return root;
}
}
class Solution1 {
/**
* 递归方法
* @param root
* @return
*/
public Node connect(Node root) {
if (root == null) {
return null;
}
circle(root);
return root;
}
void circle(Node root) {
if (root == null) {
return;
}
if (root.left!=null) root.left.next = root.right == null ? null : root.right;
if (root.right!=null) root.right.next = root.next == null ? null : root.next.left;
circle(root.left);
circle(root.right);
}
}
}

View File

@ -0,0 +1,103 @@
package cn.whaifree.leetCode.Tree;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/15 11:16
* @注释
*/
public class LeetCode117 {
class Node {
public int val;
public Node left;
public Node right;
public Node next;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, Node _left, Node _right, Node _next) {
val = _val;
left = _left;
right = _right;
next = _next;
}
}
@Test
public void test() {
Node root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.right.right = new Node(7);
root = new Solution1().connect(root);
System.out.println(root);
}
class Solution {
List<Node> levelHead = new ArrayList<>();
public Node connect(Node root) {
level(root, 0);
return root;
}
public void level(Node root, int level) {
if (root == null) {
return;
}
if (levelHead.size() > level) {
root.next = levelHead.get(level);
levelHead.set(level, root);
}else {
levelHead.add(level, root);
}
level(root.right, level + 1);
level(root.left, level + 1);
}
}
class Solution1 {
public Node connect(Node root) {
if (root == null) {
return null;
}
Deque<Node> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
int size = queue.size();
Node nodeIndex = null;
// 遍历这一层
for (int i = 0; i < size; i++) {
Node pop = queue.pop();
pop.next = nodeIndex;
nodeIndex = pop;
if (pop.right != null) {
queue.add(pop.right);
}
if (pop.left != null) {
queue.add(pop.left);
}
}
}
return root;
}
}
}

View File

@ -0,0 +1,92 @@
package cn.whaifree.leetCode.String;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/18 21:43
* @注释
*/
public class LeetCode12 {
class Solution1 {
int[] nums = new int[]{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
String[] romans = new String[]{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
public String intToRoman(int num) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < nums.length; i++) {
int v = nums[i];
String c = romans[i];
while (num >= v) {
num -= v;
stringBuilder.append(c);
}
if (num == 0) { // 效率
break;
}
}
return stringBuilder.toString();
}
}
class Solution {
static Map<Integer,String> map = new HashMap<>();
static {
map.put(1,"I");
map.put(2,"II");
map.put(3,"III");
map.put(4,"IV");
map.put(5,"V");
map.put(6,"VI");
map.put(7,"VII");
map.put(8,"VIII");
map.put(9,"IX");
map.put(10,"X");
map.put(20,"XX");
map.put(30,"XXX");
map.put(40,"XL");
map.put(50,"L");
map.put(60,"LX");
map.put(70,"LXX");
map.put(80,"LXXX");
map.put(90,"XC");
map.put(100,"C");
map.put(200,"CC");
map.put(300,"CCC");
map.put(400,"CD");
map.put(500,"D");
map.put(600,"DC");
map.put(700,"DCC");
map.put(800,"DCCC");
map.put(900,"CM");
map.put(1000,"M");
map.put(2000,"MM");
map.put(3000,"MMM");
}
public String intToRoman(int num) {
StringBuilder sb = new StringBuilder();
String x = String.valueOf(num);
for (int i = 0; i < x.length(); i++) {
char c = x.charAt(i);
if (c == '0') {
continue;
}
int v = (int) ((c - '0') * Math.pow(10, x.length() - i - 1));
sb.append(map.get(v));
}
return sb.toString();
}
}
@Test
public void test() {
Solution solution = new Solution();
System.out.println(solution.intToRoman(1994));
}
}

View File

@ -0,0 +1,88 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/3 14:38
* @注释
*/
public class LeetCode121 {
@Test
public void test()
{
int[] prices = {7,1,5,3,6,4};
System.out.println(new Solution1().maxProfit(prices));
}
class Solution {
/**
*
* 只能选择 某一天 买入这只股票并选择在 未来的某一个不同的日子 卖出该股票
*
* dp[i][1]表示i天不持有股票的持有现金
* dp[i][0]表示i天持有股票所有的现金
* 第i天买入股票现金就是 -prices[i]
*
* 第i天有股票 1. 刚刚买入2. 第i-1天就有
* 第i天没有股票 2. 第i天卖出 2. 第i-1天就没有股票
*
* dp[i][0] 持有股票
* - i-1就持有股票今天不卖 dp[i-1][0]
* - 买入股票 -今天的股价 -prices[i]
* - max
* dp[i][1] 无持有
* - i-1 保持现状dp[i-1][1]
* - 卖出 prices[i] + dp[i-1][0] 价格+[i-1]天加持有的现金
* - max
* dp[0][0] = -price[0]
* dp[0][1] = 0
*
* @param prices
* @return
*/
public int maxProfit(int[] prices) {
if (prices.length == 1) {
return 0;
}
int[] dp = new int[2];
dp[0] = -prices[0];
dp[1] = 0;
for (int i = 0; i < prices.length; i++) {
// 持有股票 1. i-1就有 2. 刚刚买入
dp[0] = Math.max(dp[0], -prices[i]);
// 无股票 2. i-1就无2 刚刚卖出
dp[1] = Math.max(dp[1], dp[0] + prices[i]);
}
return dp[1]; // 最后一天一定没有股票才能有最大利润
}
}
class Solution1 {
/**
* 贪心
* @param prices
* @return
*/
public int maxProfit(int[] prices) {
int min = Integer.MAX_VALUE;
int res = 0;
for (int i = 0; i < prices.length; i++) {
min = Math.min(min, prices[i]);
res = Math.max(res, prices[i] - min);
}
return res;
}
}
}

View File

@ -0,0 +1,70 @@
package cn.whaifree.leetCode.Greedy;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/2/25 22:21
* @注释
*/
public class LeetCode122 {
@Test
public void test() {
System.out.println(new Solution1().maxProfit(new int[]{7, 1, 5, 3, 6, 4}));
System.out.println(new Solution1().maxProfit(new int[]{1}));
}
class Solution {
/**
* 随时可以买卖那么只要有跌的我都不要
* 上帝视角只要涨我就全要
*
* 7跌 1涨5 4涨6 跌4
*
* @param prices
* @return
*/
public int maxProfit(int[] prices) {
int maxProfit = 0;
for (int i = 0; i < prices.length; i++) {
if (i > 0 && prices[i] - prices[i - 1] > 0) {
maxProfit += prices[i] - prices[i - 1];
}
}
return maxProfit;
}
}
class Solution1 {
/**
* dp[i] 表示当天可获得的收益
* dp[i] = dp[i-1] + if(prices[i-1] < price[i]){prices[i] - price[i-1]}
*
* @param prices
* @return
*/
public int maxProfit(int[] prices) {
int[] dp = new int[prices.length];
for (int i = 1; i < prices.length; i++) {
dp[i] = dp[i - 1];
if (prices[i - 1] < prices[i]) {
// 挣钱
dp[i] += prices[i] - prices[i - 1];
}
}
return dp[prices.length - 1];
}
}
}

View File

@ -0,0 +1,56 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/16 15:05
* @注释
*/
public class LeetCode124 {
@Test
public void test()
{
TreeNode treeNode = TreeNode.constructTreeByArray(1, 2, 3);
System.out.println(new Solution().maxPathSum(treeNode));
}
class Solution {
/**
* f
* a
* b c
* <p>
* a有可能的路径
* 1. f a c
* 2. f a b
* 3. b a c 不包含父亲节点 用b+a+c与max判断
*
* @param root
* @return
*/
int max = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
maxPath(root);
return max;
}
public int maxPath(TreeNode root) {
if (root == null) {
return 0;
}
int left = maxPath(root.left);
int right = maxPath(root.right);
if (left < 0) {
left = 0;
}
if (right < 0) {
right = 0;
}
max = Math.max(max, left + right + root.val); // 如果是 b a c 既没有用父亲节点
return Math.max(left, right) + root.val;
}
}
}

View File

@ -0,0 +1,49 @@
package cn.whaifree.leetCode.String;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/18 23:28
* @注释
*/
public class LeetCode125 {
public static void main(String[] args) {
System.out.println((int) 'A');
System.out.println((int) 'Z');
System.out.println((int) 'a');
System.out.println((int) 'z');
System.out.println(new Solution().isPalindrome("A man, a plan, a canal: Panama"));
}
static class Solution {
public boolean isPalindrome(String s) {
StringBuilder sb = new StringBuilder();
for (char c : s.toCharArray()) {
// 大写字符转换为小写字符并移除所有非字母数字字符
// if (c >= 'A' && c <= 'Z') {
// sb.append((char) (c + 32));
// } else if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) {
// sb.append(c);
// }
if (Character.isLetterOrDigit(c)) {
sb.append(Character.toLowerCase(c));
}
}
return isHuiWen(sb.toString());
}
public boolean isHuiWen(String s) {
int left = 0;
int right = s.length() - 1;
while (left < right) {
if (s.charAt(left) != s.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
}
}

View File

@ -0,0 +1,38 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/27 22:27
* @注释
*/
public class LeetCode129 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTreeByArray(new Integer[]{4, 9, 0, 5, 1});
int sum = new Solution().sumNumbers(treeNode);
System.out.println(sum);
}
class Solution {
public int sumNumbers(TreeNode root) {
return sumNumbers(root, 0);
}
public int sumNumbers(TreeNode root,int pre) {
if (root == null) {
return 0;
}
if (root.left == null && root.right == null) {
return pre * 10 + root.val;
}
int now = pre * 10 + root.val;
int left = sumNumbers(root.left, now);
int right = sumNumbers(root.right, now);
return left + right;
}
}
}

View File

@ -0,0 +1,38 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/15 12:34
* @注释
*/
public class LeetCode129_2 {
/**
* 向下遍历从前往后获取值
*/
class Solution {
public int sumNumbers(TreeNode root) {
return level(root, 0);
}
public int level(TreeNode root,int preV) {
if (root == null) {
return 0;
}
int sum = root.val + preV * 10;
if (root.left == null && root.right == null) {
return sum;
}
int right = level(root.right,sum);
int left = level(root.left, sum);
return right + left;
}
}
}

View File

@ -0,0 +1,123 @@
package cn.whaifree.leetCode.String;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/18 0:11
* @注释
*/
public class LeetCode13 {
@Test
public void test()
{
Solution1 solution = new Solution1();
int i = solution.romanToInt("MCMXCIV");
System.out.println(i);
}
class Solution {
public int romanToInt(String s) {
char[] charArray = s.toCharArray();
int res = 0;
for (int i = 0; i < charArray.length; i++) {
if (i < charArray.length - 1 && charArray[i] == 'I' && charArray[i + 1] == 'V') {
res += 4;
i++;
}
else if (i < charArray.length - 1 && charArray[i] == 'I' && charArray[i + 1] == 'X') {
res += 9;
i++;
}
else if (i < charArray.length - 1 && charArray[i] == 'X' && charArray[i + 1] == 'L') {
res += 40;
i++;
}
else if (i < charArray.length - 1 && charArray[i] == 'X' && charArray[i + 1] == 'C') {
res += 90;
i++;
}
else if (i < charArray.length - 1 && charArray[i] == 'C' && charArray[i + 1] == 'D') {
res += 400;
i++;
}
else if (i < charArray.length - 1 && charArray[i] == 'C' && charArray[i + 1] == 'M') {
res += 900;
i++;
}
else if (charArray[i] == 'I') {
res += 1;
}
else if (charArray[i] == 'V') {
res += 5;
}
else if (charArray[i] == 'X') {
res += 10;
}
else if (charArray[i] == 'L') {
res += 50;
}
else if (charArray[i] == 'C') {
res += 100;
}
else if (charArray[i] == 'D') {
res += 500;
}
else if (charArray[i] == 'M') {
res += 1000;
}
}
return res;
}
}
class Solution1 {
/**
* 当前位置的元素比下个位置的元素小就减去当前值否则加上当前值
* 输入: s = "MCMXCIV"
* 输出: 1994
* 解释: M = 1000, CM = 900, XC = 90, IV = 4.
* @param s
* @return
*/
public int romanToInt(String s) {
int res = 0;
int preV = getV(s.charAt(0));
for (int i = 1; i < s.length(); i++) {
int nums = getV(s.charAt(i));
if (preV < nums) {
res -= preV;
}else {
res += preV;
}
preV = nums;
}
res += preV;
return res;
}
public int getV(char c) {
switch (c) {
case 'I':
return 1;
case 'V':
return 5;
case 'X':
return 10;
case 'L':
return 50;
case 'C':
return 100;
case 'D':
return 500;
case 'M':
return 1000;
}
return 0;
}
}
}

View File

@ -0,0 +1,71 @@
package cn.whaifree.leetCode.BackTracking;
import org.junit.Test;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/2/10 15:12
* @注释
*/
public class LeetCode131 {
@Test
public void test() {
String abbc = "aaab";
new Solution().partition(abbc).forEach(
list -> {
System.out.println(list);
}
);
}
class Solution {
List<List<String>> res = new ArrayList<>();
List<String> path = new ArrayList<>();
public List<List<String>> partition(String s) {
backTracking(s, 0);
return res;
}
/**
* 1. 判断回文字符串函数 <br>
* 2. 从start开始切割到i i++<br>
* 递归
* <img src="https://code-thinking.cdn.bcebos.com/pics/131.%E5%88%86%E5%89%B2%E5%9B%9E%E6%96%87%E4%B8%B2.jpg">
*
* @param s
* @param start
*/
public void backTracking(String s, int start) {
if (start >= s.length()) {
res.add(new ArrayList<>(path));
return;
}
for (int i = start; i < s.length(); i++) {
if (isPalindrome(s, start, i)) {
String substring = s.substring(start, i + 1);
path.add(substring);
backTracking(s, i + 1);
path.remove(path.size() - 1);
}
}
}
//判断是否是回文串
private boolean isPalindrome(String s, int startIndex, int end) {
for (int i = startIndex, j = end; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
return false;
}
}
return true;
}
}
}

View File

@ -0,0 +1,120 @@
package cn.whaifree.leetCode.Greedy;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/2/27 20:02
* @注释
*/
public class LeetCode134 {
@Test
public void test() throws InterruptedException {
System.out.println("初始化内存 -Xms");
System.out.println(Runtime.getRuntime().totalMemory() / 1024 / 1024 + "m");
System.out.println("最大可使用内存 ");
System.out.println(Runtime.getRuntime().freeMemory() / 1024 / 1024 + "m");
System.out.println("最大堆内存:-Xmx");
System.out.println(Runtime.getRuntime().maxMemory() / 1024 / 1024 + "m");
// -XX+PrintGCDetails
int[] ints = new int[10000];
// Thread.sleep(1000000);
// System.out.println(new Solution().canCompleteCircuit(
// new int[]{5,1,2,3,4},
// new int[]{4,4,1,5,1}
// ));
}
class Solution {
/**
*
* @param gas 加油站有的油
* @param cost 行驶代价
* @return
*/
public int canCompleteCircuit(int[] gas, int[] cost) {
int[] rent = new int[gas.length];
int total = 0;
for (int i = 0; i < gas.length; i++) {
rent[i] = gas[i] - cost[i];
total += rent[i];
}
// 如果全部剩余<0 则必然跑不了一圈
if (total < 0) {
return -1;
}
// 以下为必然可以跑一圈的
// 如果当前剩余不够用则让指针指向i+1
int curSum = 0;
int index = 0;
for (int i = 0; i < rent.length; i++) {
curSum += rent[i];
if (curSum < 0) {
index = (i + 1) % gas.length ;
curSum = 0;
}
}
// 1. 前提必然能跑一圈
// 2. 没有进入某个i之后都没有curSum<0 那么就是正确的i
return index;
}
}
// class Solution {
// /**
// *
// * @param gas 加油站有的油
// * @param cost 行驶代价
// * @return
// */
// public int canCompleteCircuit(int[] gas, int[] cost) {
// int needSum = 0;
// for (int i : cost) {
// needSum += i;
// }
//
// int iHave = 0;
// int sumAdd = 0;
// int start = 0;
// for (int i = 0; i < gas.length; i++) {
// iHave += gas[i];
// sumAdd += gas[i];
// if (iHave < cost[i]) {
// iHave = 0;
// i = start;
// start = start + 1;
// sumAdd = 0;
// continue;
// }
// iHave -= cost[i];
// if (sumAdd >= needSum) {
// return start;
// }
//
// if (i == gas.length - 1) {
// i = -1;
// }
//
// if (start == gas.length - 1 && start != i) {
// break;
// }
// }
//
// return -1;
// }
//
// }
}

View File

@ -0,0 +1,63 @@
package cn.whaifree.leetCode.Greedy;
import org.junit.Test;
import java.util.Arrays;
import java.util.Vector;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/2/28 12:44
* @注释
*/
public class LeetCode135 {
@Test
public void tesr() {
System.out.println(new Solution().candy(new int[]{1, 2, 2, 5, 4, 3, 2}));
}
class Solution {
public int candy(int[] ratings) {
// 从前往后遍历遇到ratings[i]>ratings[i-1] score[i]+1
int length = ratings.length;
int[] scores = new int[length];
scores[0] = 1;
for (int i = 1; i < length; i++) {
if (ratings[i] > ratings[i - 1]) {
scores[i] = scores[i - 1] + 1;
}else {
scores[i] = 1;
}
}
// 从后往前
for (int i = length -1; i > 0; i--) {
/**
* 如果 ratings[i] < ratings[i - 1]此时candyVec[i-1]第i-1个小孩的糖果数量就有两个选择了
* - 一个是candyVec[i] + 1从右边这个加1得到的糖果数量
* - 一个是candyVec[i-1]之前比较右孩子大于左孩子得到的糖果数量
* 5 3
* 从右边向左边i-1可选择为 3+1 或者原来的 5从左往右已经处理过的
* 同时要满足同时保证i小孩既大于左也大于右边那么取最大值
* 同时保证i小孩既大于左也大于右边
*/
if (ratings[i] < ratings[i - 1]) {
scores[i - 1] = Math.max(scores[i] + 1, scores[i - 1]);
}
}
int scoreSum = 0;
for (int score : scores) {
scoreSum += score;
}
return scoreSum;
}
}
}

View File

@ -0,0 +1,86 @@
package cn.whaifree.leetCode.LinkedList;
import org.junit.Test;
public class LeetCode138 {
static class Node {
int val;
Node next;
Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
}
@Test
public void test() {
// 1 2 3
// 1 3
// 2 1
// Node node1 = new Node(1);
// Node node2 = new Node(2);
// Node node3 = new Node(3);
// node1.next = node2;
// node2.next = node3;
// node1.random = node3;
// node2.random = node1;
// Node node = copyRandomList(node1);
// System.out.println(node);
// [[7,null],[13,0],[11,4],[10,2],[1,0]]
Node node1 = new Node(7);
Node node2 = new Node(13);
Node node3 = new Node(11);
Node node4 = new Node(10);
Node node5 = new Node(1);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
node2.random = node1;
node3.random = node5;
node4.random = node3;
node5.random = node1;
Node node = copyRandomList(node1);
System.out.println(node);
}
public Node copyRandomList(Node head) {
Node index = head;
while (index != null) {
Node tmp = index.next;
index.next = new Node(index.val);
index.next.next = tmp;
index = index.next.next;
}
index = head;
while (index != null) {
if (index.random != null) {
index.next.random = index.random.next;
}
index = index.next.next;
}
Node newHead = head.next;
index = newHead;
Node tmpPreIndex = head;
while (index.next != null) {
tmpPreIndex.next = tmpPreIndex.next.next;
tmpPreIndex = tmpPreIndex.next;
index.next = index.next.next;
index = index.next;
}
tmpPreIndex.next = null;
return newHead;
}
}

View File

@ -0,0 +1,84 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/28 13:15
* @注释
*/
public class LeetCode139 {
@Test
public void test() {
// System.out.println(new Solution().wordBreak("leetcode", List.of("leet", "code")));
// System.out.println(new Solution().wordBreak("leetcode", List.of("leet", "cod", "e")));
// ["apple","pen"]
System.out.println(new Solution().wordBreak("applepenapple", List.of("apple", "pen")));
}
class Solution {
/**
*
* dp[i][j] 表示s中前j个字母能否被0-i中任意元素组合出来
*
* 定义 dp[i] 表示字符串 s i 个字符组成的字符串 s[0..i1] 是否能被空格拆分成若干个字典中出现的单词
*
* c a t s a n d o g
* cats 0 0 0 1 0
* dog
* sand
* and
* cat
* '' l e e t c o d e
* '' 1 0 0 0 0 0 0 0 0
* leet 1 0 0 0 1 0 0 0 0
* code 1 0 0 0 0 0 0 0 1
*
* a p p l e p e n a p p l e
* apple 1 0 0 0 0 1 0 0 0 0 0 0 0 1
* pen 1 0 0 0 0 1 0 0 1 0 0 0 0 0
*
* @param s
* @param wordDict
* @return
*/
public boolean wordBreak(String s, List<String> wordDict) {
// 完全背包先便利字符串再遍历背包确保重会重复选择背包
int len = s.length();
boolean[] dp = new boolean[len + 1];
dp[0] = true;
for (int j = 1; j <= len; j++) {
for (int i = 0; i < wordDict.size(); i++) {
String str = wordDict.get(i);
int index = j - str.length();
if (index >= 0 && dp[index] && check(s, j - 1, str)) {
dp[j] = true;
}
}
}
return dp[len];
}
public boolean check(String s, int start, String word) {
for (int i = word.length() - 1; i >= 0; i--) {
if (word.charAt(i) != s.charAt(start)) {
return false;
}
start--;
}
return true;
}
}
@Test
public void main() {
System.out.println(new Solution().check("leetcode", 7, "code"));
}
}

View File

@ -0,0 +1,73 @@
package cn.whaifree.leetCode.String;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/18 22:09
* @注释
*/
public class LeetCode14 {
@Test
public void test() {
Solution solution = new Solution();
String[] strs = {"d", "c"};
String s = solution.longestCommonPrefix(strs);
System.out.println(s);
}
class Solution {
public String longestCommonPrefix(String[] strs) {
String min = strs[0];
for (String s : strs) {
if (s.length() < min.length()) {
min = s;
}
}
int index = 0;
while (index < min.length()) {
char c = strs[0].charAt(index);
for (int i = 1; i < strs.length; i++) {
if (strs[i].charAt(index) != c) {
return strs[0].substring(0, index);
}
}
index++;
}
return min;
}
}
@Test
public void test2() {
Solution2 solution = new Solution2();
String[] strs = {"flower","flow","flight"};
String s = solution.longestCommonPrefix(strs);
System.out.println(s);
}
class Solution2 {
public String longestCommonPrefix(String[] strs) {
String str = strs[0];
for (int i = 1; i < strs.length; i++) {
str = common(str, strs[i]);
}
return str;
}
public String common(String a, String b) {
int len = Math.min(a.length(), b.length());
for (int i = 0; i < len; i++) {
if (a.charAt(i) != b.charAt(i)) {
return a.substring(0, i);
}
}
return a.substring(0, len);
}
}
}

View File

@ -0,0 +1,42 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/23 12:54
* @注释
*/
public class LeetCode141 {
@Test
public void test() {
ListNode listNode = ListNode.listNodeFromArray(new int[]{1});
// listNode.next.next.next = listNode;
System.out.println(new Solution().hasCycle(listNode));
}
public class Solution {
public boolean hasCycle(ListNode head) {
if (head == null) {
return false;
}
if (head.next == null) {
return false; // 只有一个节点
}
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast) {
if (fast == null || fast.next == null) {
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
}
}

View File

@ -0,0 +1,104 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Objects;
import java.util.Stack;
public class LeetCode142 {
@Test
public void test() {
Solution solution = new Solution();
ListNode listNode1= new ListNode(1);
ListNode listNode2= new ListNode(2,listNode1);
ListNode listNode3= new ListNode(3,listNode2);
ListNode listNode4= new ListNode(4,listNode3);
listNode1.next = listNode3;
// ListNode.printList(listNode4);
ListNode listNode = solution.detectCycle(listNode4);
if (listNode == null) {
System.out.println("null");
} else {
System.out.println(listNode.val);
}
}
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
/**
* 快慢指针
* 时间复杂度O(N)其中 N 为链表中节点的数目我们恰好需要访问链表中的每一个节点
* 空间复杂度O(1)
*
* @param head
* @return
*/
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
// 相遇了有环
if (slow == fast) {
break;
}
}
if (Objects.isNull(fast) || Objects.isNull(fast.next)) {
return null;
}
// 此时相遇 fast,slow
// x = (n-1)(y-z)+z
slow = head;
while (slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
/**
* 时间复杂度O(N)其中 N 为链表中节点的数目我们恰好需要访问链表中的每一个节点
* 空间复杂度O(N)其中 N 为链表中节点的数目我们需要将链表中的每个节点都保存在哈希表当中
*/
public class Solution1 {
/**
* 快慢指针
* @param head
* @return
*/
public ListNode detectCycle(ListNode head) {
HashSet<ListNode> listNodes = new HashSet<>();
ListNode index = head;
while (index != null && !listNodes.contains(index)) {
listNodes.add(index);
index = index.next;
}
return index;
}
}
}

View File

@ -0,0 +1,81 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
/**
* 前序遍历
* @version 1.0
* @Author whai文海
* @Date 2024/1/14 15:12
* @注释
*/
public class LeetCode144 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTree(new Integer[]{});
TreeNode.printTree(treeNode);
new Solution1().preorderTraversal(treeNode).forEach(
integer -> System.out.println(integer)
);
}
class Solution {
List<Integer> res = new LinkedList<Integer>();
public List<Integer> preorderTraversal(TreeNode root) {
if (root == null) {
return res;
}
return pre(root);
}
public List<Integer> pre(TreeNode root) {
if (root == null) {
return null;
}
res.add(root.val);
pre(root.left);
pre(root.right);
return res;
}
}
class Solution1 {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new LinkedList<Integer>();
if (root == null) {
return res;
}
// 基于指针
Deque<TreeNode> queue = new LinkedList<>();
// 加入根节点
TreeNode index = root;
queue.push(index);
while (!queue.isEmpty()) {
index = queue.pop();
res.add(index.val);
// 先加入右子树因为是栈后出右边
if (index.right != null) {
queue.push(index.right);
}
// 后加入左子树
if (index.left != null) {
queue.push(index.left);
}
}
return res;
}
}
}

View File

@ -0,0 +1,77 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/15 20:11
* @注释
*/
public class LeetCode145 {
@Test
public void test() {
TreeNode root = TreeNode.constructTree(new Integer[]{1, 2, 3, 4, 5});
root.printTree();
new Solution1().postorderTraversal(root).forEach(
System.out::println
);
}
class Solution {
List<Integer> res = new LinkedList<>();
public List<Integer> postorderTraversal(TreeNode root) {
if (root == null) {
return res;
}
postorder(root);
return res;
}
public void postorder(TreeNode root) {
if (root==null) return;
postorder(root.left);
postorder(root.right);
res.add(root.val);
}
}
class Solution1 {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new LinkedList<Integer>();
if (root == null) {
return res;
}
Deque<TreeNode> stack = new ArrayDeque<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode pop = stack.pop();
res.add(pop.val);
if (pop.left != null) {
stack.push(pop.left);
}
if (pop.right != null) {
stack.push(pop.right);
}
}
Collections.reverse(res);
return res;
}
}
}

View File

@ -0,0 +1,90 @@
package cn.whaifree.leetCode.Stack;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
/**
* 逆转波兰表达式
*/
public class LeetCode150 {
@Test
public void test() {
System.out.println(new Solution1().evalRPN(new String[]{"2", "1", "+", "3", "*"}));
System.out.println(new Solution1().evalRPN(new String[]{"4", "13", "5", "/", "+"}));
}
class Solution {
public int evalRPN(String[] tokens) {
Deque<String> stack = new LinkedList<>();
int index = 0;
while (index < tokens.length) {
String token = tokens[index];
if (token.equals("+")) {
Integer pop1 = Integer.parseInt(stack.pop());
Integer pop2 = Integer.parseInt(stack.pop());
stack.push(String.valueOf(pop1 + pop2));
} else if (token.equals("-")) { //避免多次判断
Integer pop1 = Integer.parseInt(stack.pop());
Integer pop2 = Integer.parseInt(stack.pop());
stack.push(String.valueOf(pop2 - pop1));
} else if (token.equals("*")) {
Integer pop1 = Integer.parseInt(stack.pop());
Integer pop2 = Integer.parseInt(stack.pop());
stack.push(String.valueOf(pop2 * pop1));
} else if (token.equals("/")) {
Integer pop1 = Integer.parseInt(stack.pop());
Integer pop2 = Integer.parseInt(stack.pop());
stack.push(String.valueOf(pop2 / pop1));
} else {
stack.push(token);
}
index++;
}
return Integer.parseInt(stack.pop());
}
}
class Solution1 {
public int evalRPN(String[] tokens) {
Deque<String> stack = new LinkedList<>();
for (String token : tokens) {
switch (token) {
case "+":
int i = Integer.parseInt(stack.pop());
int j = Integer.parseInt(stack.pop());
stack.push(String.valueOf(i + j));
break;
case "-":
int k = Integer.parseInt(stack.pop());
int l = Integer.parseInt(stack.pop());
stack.push(String.valueOf(l - k));
break;
case "*":
int m = Integer.parseInt(stack.pop());
int n = Integer.parseInt(stack.pop());
stack.push(String.valueOf(n * m));
break;
case "/":
int o = Integer.parseInt(stack.pop());
int p = Integer.parseInt(stack.pop());
stack.push(String.valueOf(p / o));
break;
default:
stack.push(token);
break;
}
}
return Integer.parseInt(stack.pop());
}
}
}

View File

@ -0,0 +1,123 @@
package cn.whaifree.leetCode.String;
import org.junit.Test;
import java.util.*;
public class LeetCode151 {
// todo
@Test
public void test() {
String s = " a b cd ef g ";
System.out.println(new Solution2().reverseWords(s));
}
class Solution {
public String reverseWords(String s) {
List<String> list = new LinkedList<>();
String[] split = s.split(" ");
for (String s1 : split) {
if (!(s1.equals("") || s1.equals(" "))) {
list.add(s1);
}
}
StringBuilder buffer = new StringBuilder();
int index = list.size() - 1;
while (index > 0) {
buffer.append(list.get(index--)+" ");
}
buffer.append(list.get(0));
return buffer.toString();
}
}
// 不要使用辅助空间空间复杂度要求为O(1)
class Solution1 {
public String reverseWords(String s) {
StringBuilder stringBuilder = deleteSpace(s, ' ');
reverse(stringBuilder, 0, stringBuilder.length() - 1);
reverseWord(stringBuilder);
// 移除多余空格
// 反转char
// 反转每个字符
return stringBuilder.toString();
}
public void reverseWord(StringBuilder stringBuilder) {
int start = 0;
int index = 0;
while (index < stringBuilder.length() + 1) {
if (index == stringBuilder.length() || stringBuilder.charAt(index) == ' ') {
reverse(stringBuilder, start, index - 1);
start = index + 1;
}
index++;
}
}
public void reverse(StringBuilder str, int start, int end) {
while (start < end) {
char tmp = str.charAt(start);
str.setCharAt(start, str.charAt(end));
str.setCharAt(end, tmp);
end--;
start++;
}
}
/**
* 双指针移动元素移除target
* - 参考LeetCode 27
* @param target
* @return
*/
public StringBuilder deleteSpace(String s,char target) {
// 前后指针
int start = 0;
int end = s.length() - 1;
while (s.charAt(start) == target) start++;
while (s.charAt(end) == target) end--;
// 1. 删除首尾空格
StringBuilder stringBuilder = new StringBuilder();
while (start <= end) {
if (s.charAt(start) !=target){
stringBuilder.append(s.charAt(start) );
}else if (s.charAt(start) == target && stringBuilder.charAt(stringBuilder.length() - 1) != target) {
stringBuilder.append(s.charAt(start) );
}
start++;
}
// 2. 如果遇到空格判断上一个是不是空格
// - 不是入String
// - 跳过
return stringBuilder;
}
}
class Solution2{
public String reverseWords(String s) {
// 删除前后空白
String trim = s.trim();
String[] split = trim.split("\\s+");
List<String> list = Arrays.asList(split);
Collections.reverse(list);
return String.join(" ", list);
}
}
}

View File

@ -0,0 +1,104 @@
package cn.whaifree.leetCode.Stack;
import org.junit.Test;
import java.util.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/1 0:52
* @注释
*/
public class LeetCode155 {
@Test
public void test2() {
MinStack minStack = new MinStack();
// ["MinStack","push","push","push","getMin","pop","top","getMin"]
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
System.out.println(minStack.getMin());
minStack.pop();
System.out.println(minStack.top());
System.out.println(minStack.getMin());
}
class MinStack {
static class Item{
Integer item;
Integer minV;
public Item(Integer item, Integer minV) {
this.item = item;
this.minV = minV;
}
}
Deque<Item> itemStack = null;
public MinStack() {
itemStack = new ArrayDeque<>();
}
public void push(int val) {
// 找到当前最小值
Integer minNow = Math.min(getMin(), val);
Item item = new Item(val, minNow);
itemStack.push(item);
}
public void pop() {
itemStack.pop();
}
public int top() {
if (itemStack.isEmpty()) {
return Integer.MAX_VALUE;
}
return itemStack.peek().item;
}
public int getMin() {
if (itemStack.isEmpty()) {
return Integer.MAX_VALUE;
}
return itemStack.peek().minV;
}
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/
@Test
public void test() {
MinStack minStack = new MinStack();
// ["MinStack","push","push","push","getMin","pop","top","getMin"]
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
System.out.println(minStack.getMin());
minStack.pop();
System.out.println(minStack.top());
System.out.println(minStack.getMin());
}
/**
* Your MinStack object will be instantiated and called as such:
* MinStack obj = new MinStack();
* obj.push(val);
* obj.pop();
* int param_3 = obj.top();
* int param_4 = obj.getMin();
*/
}

View File

@ -0,0 +1,30 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/13 11:06
* @注释
*/
public class LeetCode160 {
@Test
public void test()
{
}
class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode A = headA, B = headB;
while (A != B) {
A = A == null ? headB : A.next;
B = B == null ? headA : B.next;
}
return A;
}
}
}

View File

@ -0,0 +1,103 @@
package cn.whaifree.leetCode.String;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/8/31 14:57
* @注释
*/
public class LeetCode165 {
@Test
public void test() {
Solution2 solution = new Solution2();
int result = solution.compareVersion("1.01.2", "1.001");
System.out.println(result);
}
class Solution2 {
/**
* 双指针不断计算有效长度
* @param version1
* @param version2
* @return
*/
public int compareVersion(String version1, String version2) {
int v1Index = 0;
int v2Index = 0;
while (v1Index < version1.length() || v2Index < version2.length()) {
int tmpV1Sum = 0;
while (v1Index < version1.length() && version1.charAt(v1Index) != '.') {
tmpV1Sum += tmpV1Sum * 10 + version1.charAt(v1Index) - '0';
v1Index++;
}
v1Index++; // 跳过.
int tmpV2Sum = 0;
while (v2Index < version2.length() && version2.charAt(v2Index) != '.') {
tmpV2Sum += tmpV2Sum * 10 + version2.charAt(v2Index) - '0';
v2Index++;
}
v2Index++; // 跳过.
if (tmpV1Sum < tmpV2Sum) {
return -1;
} else if (tmpV1Sum > tmpV2Sum) {
return 1;
}
}
return 0;
}
}
class Solution {
/**
* 1.2 1.10
* 1.01 1.001
* 1.0.0.0
*
*
* @param version1
* @param version2
* @return
*/
public int compareVersion(String version1, String version2) {
String[] splitV1 = version1.split("\\.");
String[] splitV2 = version2.split("\\.");
if (splitV1.length < splitV2.length) {
splitV1 = fill(splitV1, splitV2.length);
}else {
splitV2 = fill(splitV2, splitV1.length);
}
// 现在两边一样长了
for (int i = 0; i < splitV1.length; i++) {
Integer v1 = Integer.valueOf(splitV1[i]);
Integer v2 = Integer.valueOf(splitV2[i]);
if (v1 > v2) {
return 1;
} else if (v1 < v2) {
return -1;
}
}
return 0;
}
public String[] fill(String[] split, int newLen) {
String[] tmp = new String[newLen];
int i = 0;
for (; i < split.length; i++) {
tmp[i] = split[i];
}
for (; i < tmp.length; i++) {
tmp[i] = "0";
}
return tmp;
}
}
}

View File

@ -0,0 +1,68 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/19 23:02
* @注释
*/
public class LeetCode167 {
@Test
public void test() {
Solution1 solution = new Solution1();
int[] ints = solution.twoSum(new int[]{2,7,11,15}, 9);
System.out.println(ints[0] + " " + ints[1]);
}
class Solution {
public int[] twoSum(int[] numbers, int target) {
for (int i = 0; i < numbers.length; i++) {
int tar = target - numbers[i];
int j = binarySearch(numbers, tar);
if (j != -1 && i != j) {
return i < j ? new int[]{i + 1, j + 1} : new int[]{j + 1, i + 1};
}
}
return null;
}
public int binarySearch(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
}
class Solution1 {
public int[] twoSum(int[] numbers, int target) {
int left = 0;
int right = numbers.length - 1;
while (left < right) {
int sum = numbers[left] + numbers[right];
if (sum == target) {
return new int[]{left + 1, right + 1};
} else if (sum < target) {
left++;
}else {
right--;
}
}
return null;
}
}
}

View File

@ -0,0 +1,57 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/1 2:21
* @注释
*/
public class LeetCode169
{
@Test
public void test()
{
int[] nums = {2,2,1,1,1,2,2};
Solution solution = new Solution();
int i = solution.majorityElement(nums);
System.out.println(i);
}
class Solution {
/**
* 遍历每个元素
* count 为现在出现最多的数
* - 如果count = 0 (表示发生了是和不是的变化)
* - 这个元素出现的次数>=之前元素出现的个数
* 所以基准变为这个元素
* count = item == base : 1:-1
*
* 如果是这个元素+1,不是这个元素-1
*
* cge5 cge5 cge7
* 1 2 1 2 1 0 1 0 1 2 1 0 1 2 3 4
* [7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
* 在遍历到数组中的第一个元素以及每个在 | 之后的元素时candidate 都会因为 count 的值变为 0 而发生改变最后一次 candidate 的值从 5 变为 7也就是这个数组中的众数
*
*
* @param nums
* @return
*/
public int majorityElement(int[] nums) {
int count = 0;
Integer candidate = null;
for (int num : nums) {
if (count == 0) {
candidate = num;
System.out.println("基准元素:" + candidate);
}
count += (num == candidate) ? 1 : -1;
}
return candidate;
}
}
}

View File

@ -0,0 +1,119 @@
package cn.whaifree.leetCode.BackTracking;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/2/2 10:31
* @注释
*/
public class LeetCode17 {
@Test
public void test() {
String digits = "23";
new Solution().letterCombinations(digits).forEach(s -> System.out.println(s));
}
class Solution {
List<String> map = new ArrayList<>();
List<String> result = new ArrayList<>();
// 记录 路径
StringBuilder s = new StringBuilder();
public List<String> letterCombinations(String digits) {
if (digits.length() == 0) {
return result;
}
map.add(0, null);
map.add(1, null);
map.add(2, "abc");
map.add(3, "def");
map.add(4, "ghi");
map.add(5, "jkl");
map.add(6, "mno");
map.add(7, "pqrs");
map.add(8, "tuv");
map.add(9, "wxyz");
backTracking(digits, 0, digits.length());
return result;
}
/**
*
* @param digits 原始字符 23
* @param number 使用到第几个字符
* @param needLength 需要几个字符等价于digits.length
*/
void backTracking(String digits, int number,int needLength) {
if (s.length() == needLength) {
result.add(new String(s.toString()));
return;
}
int c = digits.charAt(number) - 48;
String sValue = map.get(c);
int length = sValue.length();
// 对每个字符处理
for (int i = 0; i < length; i++) {
char c1 = sValue.charAt(i);
s.append(c1);
backTracking(digits, number + 1, needLength);
s.deleteCharAt(s.length() - 1);
}
}
}
class Solution1 {
List<String> map = new ArrayList<>();
List<String> result = new ArrayList<>();
// 记录 路径
StringBuilder s = new StringBuilder();
public List<String> letterCombinations(String digits) {
if (digits.length() == 0) {
return result;
}
map.add(0, null);
map.add(1, null);
map.add(2, "abc");
map.add(3, "def");
map.add(4, "ghi");
map.add(5, "jkl");
map.add(6, "mno");
map.add(7, "pqrs");
map.add(8, "tuv");
map.add(9, "wxyz");
backTracking(digits, 0);
return result;
}
/**
*
* @param digits 原始字符 23
* @param number 使用到第几个字符
*/
void backTracking(String digits, int number) {
if (s.length() == digits.length()) {
result.add(new String(s.toString()));
return;
}
int c = digits.charAt(number) - 48;
String sValue = map.get(c);
int length = sValue.length();
// 对每个字符处理
for (int i = 0; i < length; i++) {
char c1 = sValue.charAt(i);
s.append(c1);
backTracking(digits, number + 1);
s.deleteCharAt(s.length() - 1);
}
}
}
}

View File

@ -0,0 +1,128 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/27 22:42
* @注释
*/
public class LeetCode173 {
class BSTIterator1 {
List<Integer> list;
Integer index = -1;
public BSTIterator1(TreeNode root) {
list = new ArrayList<>();
inOrderTraversal(root);
}
public int next() {
index++;
return list.get(index);
}
public boolean hasNext() {
return index < list.size() - 1;
}
public void inOrderTraversal(TreeNode root) {
if (root == null) {
return;
}
inOrderTraversal(root.left);
list.add(root.val);
inOrderTraversal(root.right);
}
}
@Test
public void test1() {
TreeNode root = TreeNode.constructTree(new Integer[]{7, 3, 15, null, null, 9, 20});
BSTIterator bstIterator = new BSTIterator(root);
while (bstIterator.hasNext()) {
System.out.println(bstIterator.next());
}
}
class BSTIterator {
/**
* next访问到某个节点就让他右边入栈
*/
Deque<TreeNode> stack;
public BSTIterator(TreeNode root) {
// 每层放左边第一个
stack = new LinkedList<>();
TreeNode index = root;
while (index != null) {
stack.push(index);
index = index.left;
}
}
public int next() {
TreeNode pop = stack.pop(); // 当前指针位置
if (pop.right != null) { // 如果有边有就把右边和右边的左子树都放入栈中
TreeNode index = pop.right;
while (index != null) {
stack.push(index);
index = index.left;
}
}
return pop.val;
}
public boolean hasNext() {
return !stack.isEmpty();
}
}
class BSTIterator2 {
/**
* next访问到某个节点就让他右边入栈
*/
Deque<TreeNode> stack;
TreeNode now;
public BSTIterator2(TreeNode root) {
// 每层放左边第一个
stack = new LinkedList<>();
now = root;
}
public int next() {
while (now != null) {
stack.push(now);
now = now.left;
}
now = stack.pop();
int val = now.val;
now = now.right;
return val;
}
public boolean hasNext() {
return now != null ||!stack.isEmpty();
}
}
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator obj = new BSTIterator(root);
* int param_1 = obj.next();
* boolean param_2 = obj.hasNext();
*/
}

View File

@ -0,0 +1,68 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/28 19:41
* @注释
*/
public class LeetCode17_12BiNode {
@Test
public void test() {
TreeNode root = TreeNode.constructTreeByArray(4, 2, 5, 1, 3, null, 6, 0);
TreeNode treeNode = new Solution().convertBiNode(root);
TreeNode.treeToArray(treeNode).forEach(i -> System.out.println(i));
}
class Solution {
TreeNode res = new TreeNode();
TreeNode index = res;
public TreeNode convertBiNode(TreeNode root) {
circle(root);
return res.right;
}
private void circle(TreeNode root) {
if (root == null) {
return;
}
circle(root.left);
index.right = new TreeNode(root.val);
index = index.right;
circle(root.right);
}
}
class Solution1 {
TreeNode res = new TreeNode();
TreeNode index = res;
public TreeNode convertBiNode(TreeNode root) {
circle(root);
return res.right;
}
private void circle(TreeNode root) {
if (root == null) {
return;
}
circle(root.left);
// 直接使用不创建新对象能提升很多效率
index.right = root;
root.left = null;
index = index.right;
circle(root.right);
}
}
}

View File

@ -0,0 +1,58 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
import java.util.Arrays;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/16 12:15
* @注释
*/
public class LeetCode189 {
@Test
public void test()
{
int[] nums = new int[]{-1};
new Solution1().rotate(nums, 3);
System.out.println(Arrays.toString(nums));
}
class Solution {
public void rotate(int[] nums, int k) {
int[] newNums = new int[nums.length];
for (int i = 0; i < newNums.length; i++) {
newNums[(i + k) % nums.length] = nums[i];
}
System.arraycopy(newNums, 0, nums, 0, nums.length);
}
}
class Solution1 {
public void rotate(int[] nums, int k) {
k %= nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
}
public void reverse(int[] nums, int start, int end) {
while (start < end) {
swap(nums, start, end);
start++;
end--;
}
}
public void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
}

View File

@ -0,0 +1,144 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
public class LeetCode19 {
@Test
public void test() {
Solution2 solution = new Solution2();
ListNode listNode = solution.removeNthFromEnd(ListNode.listNodeFromArray(new int[]{1,2,3,4}), 3);
ListNode.printList(listNode);
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
/**
* 链表中结点的数目为 sz
* 1 <= sz <= 30
* 0 <= Node.val <= 100
* 1 <= n <= sz
*
* 时间复杂度O(Length)
* 空间复杂度O(1)
*
* @param head
* @param n
* @return
*/
public ListNode removeNthFromEnd(ListNode head, int n) {
// 空链表
if (head == null) {
return head;
}
int length = getLength(head);
// 删除头
if (n == length) {
head = head.next;
return head;
}
int find = length - n;
ListNode index = head;
for (int i = 0; i < find - 1; i++) {
index = index.next;
}
index.next = index.next.next;
return head;
}
int getLength(ListNode head) {
int length = 0;
ListNode index = head;
while (index != null) {
index = index.next;
length++;
}
return length;
}
}
class Solution1 {
/**
*
* 时间复杂度O(Length)
* 空间复杂度O(Length)
*
* 修改多使用这个栈会更快
* LinkedList比Stack快的原因如下1
* 基于数组实现Stack基于数组实现随机访问查找效率更高增删改效率较低
* 基于链表实现LinkedList基于链表实现增删改效率更高随机访问查找效率较低
* 对于频繁的插入删除操作利用LinkedList实现栈自然比Stack快很多
* @param head
* @param n
* @return
*/
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
Deque<ListNode> stack = new LinkedList<ListNode>();
// 双端队列
ListNode index = dummy;
while (index != null) {
stack.push(index);
index = index.next;
}
for (int i = 0; i < n; i++) {
stack.pop();
}
ListNode peek = stack.peek();
peek.next = peek.next.next;
return dummy.next;
}
}
class Solution2 {
/**
* 双指针 快慢节点追逐
* 两个节点的差值为n快指针走完了慢指针就是了
*
* @param head
* @param n
* @return
*/
public ListNode removeNthFromEnd(ListNode head, int n) {
ListNode dummy = new ListNode(0, head);
ListNode fast = dummy;
ListNode slow = dummy;
for (int i = 0; i <= n; i++) {
fast = fast.next;
}
while (fast!= null) {
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return dummy.next;
}
}
}

View File

@ -0,0 +1,40 @@
package cn.whaifree.leetCode.Dynamic;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/3 13:50
* @注释
*/
public class LeetCode198 {
@Test
public void test()
{
Solution solution = new Solution();
int[] nums = new int[]{2,7};
int rob = solution.rob(nums);
System.out.println(rob);
}
class Solution {
public int rob(int[] nums) {
if (nums.length == 1) {
return nums[0];
}
// dp[i] 表示 从0-i偷窃都最大价值
// dp[i] = max(dp[i-1],dp[i-2]+nums[i]])
int[] dp = new int[nums.length];
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
for (int i = 2; i < nums.length; i++) {
dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);
}
return dp[nums.length - 1];
}
}
}

View File

@ -0,0 +1,87 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.*;
import java.util.function.Consumer;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/17 15:07
* @注释
*/
public class LeetCode199 {
@Test
public void test() {
TreeNode root = TreeNode.constructTree(new Integer[]{1, 2, 3, 4});
root.printTree();
System.out.println(new Solution1().rightSideView(root));
}
class Solution {
/**
* 层次遍历每层最右边就是结果
* @param root
* @return
*/
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
}
Deque<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode pop = queue.pop();
// 只加入每层最后一个元素
if(i==size-1) res.add(pop.val);
if (pop.left != null) {
queue.add(pop.left);
}
if (pop.right != null) {
queue.add(pop.right);
}
}
}
return res;
}
}
class Solution1 {
List<Integer> res = new ArrayList<>();
public List<Integer> rightSideView(TreeNode root) {
if (root == null) {
return res;
}
level(root, 0);
return res;
}
public void level(TreeNode root, int level) {
if (root == null) {
return;
}
// 每层只有一个输出就是每层最右边的那个
// 每层都是让右边先进入递归就能保证获取到最右的数据
if (res.size() == level) {
res.add(root.val);
}
level(root.right, level + 1);
level(root.left, level + 1);
}
}
}

View File

@ -0,0 +1,121 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/20 11:42
* @注释
*/
public class LeetCode2 {
@Test
public void test() {
new Solution1().addTwoNumbers(
/*[9,9,9,9,9,9,9], l2 = [9,9,9,9]*/
ListNode.listNodeFromArray(new int[]{9, 9, 9, 9, 9, 9, 9})
, ListNode.listNodeFromArray(new int[]{9, 9, 9, 9})
).printList();
}
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
return circle(l1, l2, false);
}
/**
*
* @param l1
* @param l2
* @param in 是否进1
* @return
*/
public ListNode circle(ListNode l1, ListNode l2, boolean in) {
if (l1 == null && l2 == null && in) {
return new ListNode(1);
}
if (l1 == null) {
// l2 调用另一个递归方法不断去判断是否需要在当前节点进1
return judgeIn(l2, in);
} else if (l2 == null) {
return judgeIn(l1, in);
}
int val = 0;
int sum = l1.val + l2.val;
if (in) {
val = sum + 1;
}else {
val = sum;
}
ListNode res = new ListNode(val % 10);
res.next = circle(l1.next, l2.next, val >= 10);
return res;
}
public ListNode judgeIn(ListNode node, boolean in) {
if (node == null) {
if (in) {
return new ListNode(1);
}
return null;
}
int val = 0;
if (in) {
val = node.val + 1;
}else {
val = node.val;
}
ListNode res = new ListNode(val % 10);
res.next = judgeIn(node.next, val >= 10);
return res;
}
}
class Solution1 {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode indexA = l1;
ListNode indexB = l2;
boolean flagIn = false;
while (indexA != null && indexB != null) {
int sum = indexA.val + indexB.val;
if (flagIn) {
sum += 1;
}
indexA.val = sum % 10;
if (sum >= 10) {
flagIn = true;
}else {
flagIn = false;
}
if (indexA.next == null && indexB.next == null && flagIn) {
indexA.next = new ListNode(1);
break;
}
if (indexA.next == null && indexB.next != null) {
indexA.next = new ListNode(0);
}
if (indexB.next == null && indexA.next != null) {
indexB.next = new ListNode(0);
}
indexB = indexB.next;
indexA = indexA.next;
}
return l1;
}
}
}

View File

@ -0,0 +1,46 @@
package cn.whaifree.leetCode.Stack;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
/**
* 括号匹配
*/
public class LeetCode20 {
@Test
public void test() {
System.out.println(new Solution().isValid("()[]{}"));
System.out.println(new Solution().isValid("}"));
}
class Solution {
public boolean isValid(String s) {
Deque<Character> stack = new LinkedList<>();
char[] chars = s.toCharArray();
for (char aChar : chars) {
if (aChar == '{' || aChar == '[' || aChar == '(') {
stack.push(aChar);
}else if (aChar == ']'){
if (stack.isEmpty() || stack.pop() != '[') {
return false;
}
}else if (aChar == '}'){
if (stack.isEmpty() ||stack.pop()!= '{') {
return false;
}
}else if (aChar == ')'){
if (stack.isEmpty() || stack.pop() != '(') {
return false;
}
}
}
return stack.isEmpty();
}
}
}

View File

@ -0,0 +1,211 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
/**
* 链表
*
* 203. 移除链表元素
* 示例 1
* 输入head = [1,2,6,3,4,5,6], val = 6
* 输出[1,2,3,4,5]
* 示例 2
*
* 输入head = [], val = 1
* 输出[]
* 示例 3
*
* 输入head = [7,7,7,7], val = 7
* 输出[]
*
*/
public class LeetCode203 {
// /**
// * [6] 6
// * [] 6
// * [2] 6
// *
// *
// * @param head
// * @param val
// * @return
// */
// public ListNode removeElements(ListNode head, int val) {
//
// // 如果链表只有一个节点或者没有要删除的元素则直接返回原链表
// if (head == null) {
// return head;
// }
// if (head.next == null && head.val == val) {
// head = null;
// return head;
// } else if (head.next == null) {
// return head;
// }
//
// // 定义一个指针pre指向head节点
// // 定义一个指针index指向head.next节点
// ListNode pre = head;
// ListNode index = head.next;
//
// // 遍历链表直到index.next为null
// while (index.next != null) {
//
// // 如果index节点的值等于要删除的元素val
// if (index.val == val) {
//
// // 删除该节点
// pre.next = index.next;
//
// // 将指针index移动到下一个节点
// index = pre.next;
//
// // 将指针pre移动到下一个节点
// pre = pre.next;
//
// // 继续遍历链表
// continue;
// }
//
// // 如果index节点的值不等于要删除的元素val
// index = index.next;
// pre = pre.next;
// }
// // 尾巴节点为val那就删除尾巴节点
// if (index.val == val) {
// pre.next = null;
// }
// // 如果头节点的值等于要删除的元素val
// if (head.val == val) {
// head = head.next;
// }
//
//
// // 返回删除元素后的链表
// return head;
// }
public ListNode removeElements1(ListNode head, int val) {
// 找到第一个head不删除的点 删除头结点时另做考虑
while (head != null && head.val == val) {
head = head.next;
}
// 保证删完后不为空
if(head==null)
return head;
//
ListNode index = head;
while (index.next != null) {
if (index.next.val == val) {
index.next = index.next.next;
} else {
index = index.next;
}
}
return head;
}
// /**
// * 递归
// * @param head
// * @param val
// * @return
// */
// public ListNode removeElements(ListNode head, int val) {
// if (head == null) {
// return null;
// }
// head.next = removeElements(head.next, val);
// if (head.next.val == val) {
// return head.next.next;
// } else {
// return head.next;
// }
// }
/**
* 递归
* 1. 停止条件
* 2. 循环返回值
* @param head
* @param val
* @return
*/
public ListNode removeElements(ListNode head, int val) {
if (head == null) {
return null;
}
// h
// 6 6
// 让head 之后的元素交给下个递归
head.next = removeElements(head.next, val);
if (head.val == val) {
return head.next;
} else {
return head;
}
// 递归的返回值为head.next,即传入的下一结点
// 如果匹配就返回当前结点不匹配返回的head就是前一结点了
// 压栈时的head.next为后一个结点弹栈时的head.next就位后前一个结点
}
public ListNode removeElements3(ListNode head, int val) {
if (head == null) {
return head;
}
// 1. 获取当前节点
// 2. 递归next 6 6
head.next = removeElements3(head.next, val);
if (head.val == val) {
return head.next;
} else {
return head;
}
}
/**
* 0 1 2 3
* 加上虚拟表头节点
* @param head
* @param val
* @return
*/
public ListNode removeElements7(ListNode head, int val) {
ListNode virtualHead = new ListNode(0, head);
ListNode pre = virtualHead;
ListNode index = head;
head = virtualHead;
while (index != null) {
if (index.val == val) {
pre.next = index.next;
index = pre.next;
}else {
pre = pre.next;
index = index.next;
}
}
return head.next;
}
@Test
public void Test() {
ListNode listNode = ListNode.listNodeFromArray(new int[]{7,7,7,7});
// ListNode.printList(listNode);
ListNode listNode1 = removeElements7(listNode, 7);
ListNode.printList(listNode1);
}
}

View File

@ -0,0 +1,127 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
import java.util.List;
import java.util.Queue;
import java.util.Stack;
/**
* 206. 反转链表
* 给你单链表的头节点 head 请你反转链表并返回反转后的链表
*
* 示例 1
* 输入head = [1,2,3,4,5]
* 输出[5,4,3,2,1]
*
* 示例 2
* 输入head = [1,2]
* 输出[2,1]
* 示例 3
* 输入head = []
* 输出[]
* 提示
*
* 链表中节点的数目范围是 [0, 5000]
* -5000 <= Node.val <= 5000
*/
public class LeetCode206 {
@Test
public void test() {
ListNode listNode = ListNode.listNodeFromArray(new int[]{1,2,3,4,5});
ListNode listNode1 = reverseList2(listNode);
ListNode.printList(listNode1);
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
/**
* 使用栈
* @param head
* @return
*/
public ListNode reverseList(ListNode head) {
Stack<Integer> integerStack = new Stack<>();
ListNode index = head;
while (index!= null) {
integerStack.add(index.val);
index = index.next;
}
ListNode ansHead = new ListNode();
index = ansHead;
while (!integerStack.empty()) {
index.next = new ListNode(integerStack.pop());
index = index.next;
}
return ansHead.next;
}
/**
* <img src='https://code-thinking.cdn.bcebos.com/gifs/206.%E7%BF%BB%E8%BD%AC%E9%93%BE%E8%A1%A8.gif' />
*
* 使用三个指针 pre index tmp <br/>
* - 存储tmp为index的下一个节点让index指向pre <br/>
* pre index tmp <br/>
* 1 <-- 2 3 --> 4 <br/>
* pre index tmp<br/>
* 1 <-- 2 3 --> 4<br/>
* pre index tmp<br/>
* 1 <-- 2 <-- 3 4<br/>
*
* <b>移动指针不一定要index.next, 在指针固定顺序的时候 <br/>
* 可以让tmp=index.next;pre=index;index=tmp</b>
*
* @param head
* @return
*/
public ListNode reverseList1(ListNode head) {
ListNode pre = null;
ListNode tmp = null;
ListNode index = head;
while (index != null) {
tmp = index.next;
index.next = pre;
pre = index;
index = tmp;
}
return pre;
}
/**
* 递归
* - 递归 只考虑当前这个部分<b>把其他的部分扔给下一次递归</b>
* @param head
* @return
*/
public ListNode reverseList2(ListNode head) {
// 两个逆转
return reverse(null, head);
}
public ListNode reverse(ListNode pre, ListNode cur) {
if (cur == null) {
return pre;
}
// 只考虑三个点1 2逆转3tmp 2.next为下次递归的输入
ListNode tmp = cur.next;
cur.next = pre;
return reverse(cur, tmp);
}
}

View File

@ -0,0 +1,100 @@
package cn.whaifree.leetCode.Graph;
import org.junit.Test;
import java.util.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/16 0:02
* @注释
*/
public class LeetCode207 {
@Test
public void test() {
int numCourses = 4;
int[][] prerequisites = {{1, 0},{0,2},{1,3}};
System.out.println(new Solution().canFinish(numCourses, prerequisites));
}
class Solution {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i < numCourses; i++) {
graph.add(new ArrayList<>());
}
// 统计入度个数
int[] inGre = new int[numCourses];
for (int i = 0; i < prerequisites.length; i++) {
int course = prerequisites[i][0];
int preCourse = prerequisites[i][1];
graph.get(preCourse).add(course);
inGre[course]++;
}
// 对所有入度为0的进入队列
Deque<Integer> queue = new ArrayDeque<>();
for (int i = 0; i < numCourses; i++) {
if (inGre[i] == 0) {
queue.add(i);
}
}
// 出对并去边
int exeCount = 0;
while (!queue.isEmpty()) {
Integer pop = queue.pop();
exeCount++;
// 遍历这个pop点的出边
List<Integer> popOut = graph.get(pop);
for (int i = 0; i < popOut.size(); i++) {
int deleteSideNode = popOut.get(i);
inGre[deleteSideNode]--;
if (inGre[deleteSideNode] == 0) {
queue.add(deleteSideNode);
}
}
}
// 如果队列中没有元素了但还有边返回false
return exeCount == numCourses;
}
}
class Solution1 {
public boolean canFinish(int numCourses, int[][] prerequisites) {
// 统计入度个数
int[] map = new int[2000];
for (int i = 0; i < prerequisites.length; i++) {
map[prerequisites[i][0]]++;
}
// 对所有入度为0的进入队列
Deque<Integer> queue = new ArrayDeque<>();
for (int i = 0; i < numCourses; i++) {
if (map[i] == 0) {
queue.add(i);
}
}
// 出对并去边
int exeCount = 0;
while (!queue.isEmpty()) {
Integer pop = queue.pop();
exeCount++;
// 遍历所有的边
for (int i = 0; i < prerequisites.length; i++) {
if (prerequisites[i][1] == pop) {
int deleteSideNode = prerequisites[i][0];
map[deleteSideNode]--;
if (map[deleteSideNode] == 0) {
queue.add(deleteSideNode);
}
}
}
}
// 如果队列中没有元素了但还有边返回false
return exeCount == numCourses;
}
}
}

View File

@ -0,0 +1,128 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
import java.util.Arrays;
/**
* 209. 长度最小的子数组
* 给定一个含有 n 个正整数的数组和一个正整数 target
*
* 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] 并返回其长度如果不存在符合条件的子数组返回 0
*
* 示例 1
*
* 输入target = 7, nums = [2,3,1,2,4,3]
* 输出2
* 解释子数组 [4,3] 是该条件下的长度最小的子数组
* 示例 2
*
* 输入target = 4, nums = [1,4,4]
* 输出1
* 示例 3
*
* 输入target = 11, nums = [1,1,1,1,1,1,1,1]
* 输出0
*
* 提示
*
* 1 <= target <= 109
* 1 <= nums.length <= 105
* 1 <= nums[i] <= 105
*
* 进阶
*
* 如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法
*/
public class LeetCode209_2 {
/**
* 暴力求解会超时
* @param target
* @param nums
* @return
*/
public int minSubArrayLen(int target, int[] nums) {
int minLength = Integer.MAX_VALUE;
for (int i = 0; i < nums.length; i++) {
int sum = 0;
for (int j = i; j < nums.length; j++) {
sum += nums[j];
if (sum >= target) {
minLength = Math.min(minLength, j - i + 1);
break;
}
/**
* if (sum >= target && j - i +1 < minLength) {
* minLength = j - i + 1;
* break;
* }
*/
}
}
return minLength == Integer.MAX_VALUE ? 0 : minLength;
}
public int minSubArrayLen1(int target, int[] nums) {
int left = 0;
int right = 0;
int sum = 0;
int ans = Integer.MAX_VALUE;
while (right < nums.length ) {
sum += nums[right];
// 窗口内找到最小子串
while (sum >= target) {
ans = Math.min(ans, right - left + 1);
sum -= nums[left++];
}
right++;
}
return ans == Integer.MAX_VALUE ? 0 : ans;
}
class Solution {
/**
* 前缀和做法
* @param target
* @param nums
* @return
*/
public int minSubArrayLen(int target, int[] nums) {
// 求前缀和
int length = nums.length;
int[] preSum = new int[length + 1];
for (int i = 1; i < preSum.length; i++) {
preSum[i] = preSum[i - 1] + nums[i - 1];
}
// 2,3,1,2,4,3
// 因为每个元素都是正数所以preSum是递增的可以用二分查找
int minLengthFillSolution = Integer.MAX_VALUE;
for (int i = 1; i < preSum.length; i++) {
// 从0开始查找
int fill = target + preSum[i - 1];
int intervalEnd = Arrays.binarySearch(preSum, fill); // 没找到就会返回负数
if (intervalEnd < 0) {
intervalEnd = -intervalEnd - 1; // 防止查出来的是负数
}
// 这个区间如果合理就可能是正常的区间
if (intervalEnd <= length)
minLengthFillSolution = Math.min(minLengthFillSolution, intervalEnd - (i - 1));
// 注意区分下标 intervalEnd和i-1 前缀和为fill和target
}
return minLengthFillSolution == Integer.MAX_VALUE ? 0 : minLengthFillSolution;
}
}
@Test
public void list() {
System.out.println(new Solution().minSubArrayLen(7, new int[]{2, 3, 1, 2, 4, 3}));
// System.out.println(minSubArrayLen1(5, new int[]{2,3,6}));
}
}

View File

@ -0,0 +1,79 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/4 13:05
* @注释
*/
public class LeetCode21 {
@Test
public void test() {
new Solution1().mergeTwoLists(
ListNode.listNodeFromArray(new int[]{5}),
ListNode.listNodeFromArray(new int[]{1, 2, 4})
).printList();
}
class Solution {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if (list2 == null) {
return list1;
}
if (list1 == null) {
return list2;
}
ListNode pre = new ListNode(-1); // 标记结果头部
ListNode preIndex = pre; // 标记需要添加的位置
// 合并有序链表
ListNode indexA = list1;
ListNode indexB = list2;
while (indexA != null && indexB != null) {
if (indexA.val <= indexB.val) {
preIndex.next = indexA;
indexA = indexA.next;
}else {
preIndex.next = indexB;
indexB = indexB.next;
}
preIndex = preIndex.next;
}
if (indexA == null) {
preIndex.next = indexB;
}else {
preIndex.next = indexA;
}
return pre.next;
}
}
class Solution1 {
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if (list1 == null) {
return list2;
}
if (list2 == null) {
return list1;
}
if (list1.val < list2.val) {
list1.next = mergeTwoLists(list1.next, list2);
return list1;
}else {
list2.next = mergeTwoLists(list1, list2.next);
return list2;
}
}
}
}

View File

@ -0,0 +1,98 @@
package cn.whaifree.leetCode.Graph;
import org.junit.Test;
import java.util.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/16 0:44
* @注释
*/
public class LeetCode210 {
@Test
public void test() {
int[][] prerequisites = {{1,0},{2,0},{3,1},{3,2}};
int[] res = new Solution().findOrder(4, prerequisites);
System.out.println(Arrays.toString(res));
}
public int[] findOrder(int numCourses, int[][] prerequisites) {
if (numCourses == 0) return new int[0];
int[] inDegrees = new int[numCourses];
// 建立入度表
for (int[] p : prerequisites) {
inDegrees[p[0]]++; // 记录每个节点的入度
}
// 入度为0的节点队列
Queue<Integer> queue = new LinkedList<>();
for (int i = 0; i < inDegrees.length; i++) {
if (inDegrees[i] == 0) queue.offer(i); // 入度为 0 的节点可以进行执行
}
int count = 0; // 记录可以执行的任务数
int[] res = new int[numCourses]; // 完整拓扑排序的执行过程
// 根据提供的可以执行的任务入度为 0删除入度为 0 的节点
while (!queue.isEmpty()){
int curr = queue.poll(); // 拿到一个可以执行的任务
res[count++] = curr; // 这个任务可以执行作为下一次执行的节点
for (int[] p : prerequisites) {
if (p[1] == curr){ // {a,b} 表示 a 依赖 b b-->a
inDegrees[p[0]]--;
if (inDegrees[p[0]] == 0) queue.offer(p[0]);
}
}
}
if (count == numCourses) return res;
return new int[0];
}
class Solution {
public int[] findOrder(int numCourses, int[][] prerequisites) {
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i < numCourses; i++) {
graph.add(new ArrayList<>());
}
int[] inGre = new int[numCourses];
Deque<Integer> deque = new LinkedList<>();
for (int[] prerequisite : prerequisites) {
int course = prerequisite[0];
int pre = prerequisite[1];
inGre[course]++;
graph.get(pre).add(course);
}
for (int i = 0; i < inGre.length; i++) {
if (inGre[i] == 0) {
deque.add(i);
}
}
int exec = 0;
int[] res = new int[numCourses];
while (!deque.isEmpty()) {
Integer exe = deque.pop();
res[exec] = exe;
exec++;
List<Integer> in = graph.get(exe);
for (int into = 0; into < in.size(); into++) {
Integer intoNode = in.get(into);
inGre[intoNode]--;
if (inGre[intoNode] == 0) {
deque.add(intoNode);
}
}
}
if (numCourses == exec) {
return res;
}
return new int[0];
}
}
}

View File

@ -0,0 +1,518 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
import java.io.*;
import java.util.*;
import java.util.function.BiConsumer;
import static org.junit.Assert.assertArrayEquals;
public class LeetCode215 {
public static void main(String[] args) throws FileNotFoundException {
String name = "/Users/kyriewhluo/IdeaProjects/tsf/tsf-dispatch/src/main/resources/tsf-dispatch.yml";
// 读取每一行
HashMap<String, List<String>> map = new HashMap<>();
try (BufferedReader reader = new BufferedReader(new FileReader(name))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.contains("tsf-resource")) {
String[] split = line.split("/");
String key = "/" + split[1] + "/" + split[2];
List<String> orDefault = map.getOrDefault(key, new ArrayList<>());
orDefault.add(line);
map.put(key, orDefault);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
map.forEach(new BiConsumer<String, List<String>>() {
@Override
public void accept(String s, List<String> strings) {
System.out.println("# key:" + s);
System.out.println("# size:" + strings.size());
for (String string : strings) {
System.out.println(string);
}
for (int i = 0; i < 3; i++) {
System.out.println();
}
}
});
}
@Test
public void sort_EmptyArray_ShouldHandleGracefull3y() {
int[] nums = {3,2,1,5,6,4};
System.out.println(new Solution5().findKthLargest(nums, 2));
System.out.println(Arrays.toString(nums));
}
class Solution5 {
/**
* 快速排序某次base放对位置后左边刚刚好有k-1个就找到了
* @param nums
* @param k
* @return
*/
public int findKthLargest(int[] nums, int k) {
return sort(nums, 0, nums.length - 1, k);
}
/**
* 快速排序思路对前n-1个进行不断交换最后把基准替换到交接点
* @param nums
* @param start
* @param end
* @param k
* @return
*/
public int sort(int[] nums, int start, int end, int k) {
if (start > end) {
return nums[end];
}
int q = new Random().nextInt(end - start + 1) + start;
swap(nums, q, end);
int base = nums[end];
int left = start;
int right = end;
while (left < right) {
//从左往右遍历当左指针指向的元素小于等于基数时i++左指针持续向右移动
while (nums[left] >= base && left < right) {
left++;
}
//从右往左遍历当右指针指向的元素大于等于基数时j--右指针持续向左移动
while (nums[right] <= base && left < right) {
right--;
}
if (left < right) {
//当左右两个指针停下来时交换两个元素
swap(nums, left, right);
}
}
swap(nums, left, end);
// 从大到小排序如果左边k-1个则left就是第k个左边k-1个比他大
if (left == k - 1) {
return nums[left];
}
// 左边的数量太少了往右边找
if (left < k - 1) {
return sort(nums, left + 1, end, k);
}
return sort(nums, start, left - 1, k);
}
public void swap(int[] heap, int start, int end) {
int temp = heap[start];
heap[start] = heap[end];
heap[end] = temp;
}
}
@Test
public void sort_EmptyArray_ShouldHandleGracefully8() {
// [3,2,3,1,2,4,5,5,6], k = 4
int[] nums = {5,4,3,2,1};
System.out.println(new Solution4().findKthLargest(nums, 2));
}
class Solution4 {
public int findKthLargest(int[] nums, int k) {
for (int i = nums.length - 1; i > 0; i--) {
shiftUp(nums, i);
}
System.out.println(Arrays.toString(nums));
return nums[nums.length - k];
}
public void shiftUp(int[] heap, int end) {
int parent = (end - 1) / 2;
while (parent >= 0) {
int left = parent * 2 + 1;
int right = parent * 2 + 2;
int k = parent;
if (left <= end &&heap[left] > heap[k]) {
k = left;
}
if (right <= end && heap[right] > heap[k]) {
k = right;
}
swap(heap, parent, k);
parent--;
}
swap(heap, 0, end);
}
public void swap(int[] heap, int start, int end) {
int temp = heap[start];
heap[start] = heap[end];
heap[end] = temp;
}
}
@Test
public void main()
{
int i = 0;
while (true) {
i++;
}
//
// int[] nums = {3,2,1,5,6,4};
// int k = 2;
// Solution solution = new Solution();
// int i = solution.findKthLargest(nums, k);
// System.out.println(i);
}
// @Test
// public void test188()
// {
// new sol().findKthLargest(new int[]{3, 2, 1, 5, 6, 4}, 3);
//
//
// }
// class sol{
// /**
// * 3
// * / \
// * / \
// * 5 -2147483648
// * /
// * 2 右边那个有问题所以不行
// * @param nums
// * @param k
// * @return
// */
// public int findKthLargest(int[] nums, int k) {
// Heap heap = new Heap(k);
// for (int num : nums) {
// heap.add(num);
// }
// return 1;
// }
// }
// class Heap{
//
//
// int[] heap = null;
//
// public Heap(int k) {
// this.heap = new int[k + 1];
// Arrays.fill(this.heap, Integer.MIN_VALUE);
// }
//
// public void add(int num) {
// heap[heap.length - 1] = num;
// shiftUp(heap, heap.length - 1);
// }
//
//
// /**
// * 固定长度的让其 shiftUp
// * @param nums
// * @param numIndex numsIndex 位置上移
// */
// public void shiftUp(int[] nums, int numIndex) {
// int k = numIndex;
// while (k > 0) {
// int parent = (k - 1) / 2;
//// if (nums[numIndex] < nums[parent]) { // 小顶堆
// if (nums[k] > nums[parent]) { // 大顶堆
// // 小顶堆小的上移
// swap(nums, parent, k);
// k = parent;
// }else {
// break;
// }
// TreeNode.constructTreeByArrayWithInteger(nums);
// }
//
// }
//
// public void swap(int[] nums, int start, int end) {
// int temp = nums[start];
// nums[start] = nums[end];
// nums[end] = temp;
// }
//
// }
class Solution {
public int findKthLargest(int[] nums, int k) {
// 小顶堆
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
for (int num : nums) {
priorityQueue.offer(num);
if (priorityQueue.size() > k) {
priorityQueue.poll();
}
}
return priorityQueue.poll();
}
}
@Test
public void test1()
{
int[] nums = {3,2,1,5,6,4};
int k = 2;
Solution1 solution = new Solution1();
int i = solution.findKthLargest(nums, k);
System.out.println(i);
}
class Solution1 {
public int findKthLargest(int[] nums, int k) {
sort(nums, nums.length - 1);
return nums[k - 1];
}
/**
* 堆排序思路
* 1. 依次遍历非叶节点 nonLeaf = (end - 1) / 2; --
* 选取左右两边比他大的替换上来不断替换直到最上面是最大的
* 2. 把最大的堆顶移动到最后确定一个最大值
* @param nums
* @param end
*/
public void sort(int[] nums, int end) {
if (end <= 0) {
return;
}
int heapSize = nums.length;
for (int i = heapSize / 2; i >= 0; --i) {
int l = i * 2 + 1, r = i * 2 + 2, largest = i;
if (l < heapSize && nums[l] > nums[largest]) {
largest = l;
}
if (r < heapSize && nums[r] > nums[largest]) {
largest = r;
}
if (largest != i) {
swap(nums, i, largest);
sort(nums, heapSize - 1);
}
}
swap(nums, 0, end);
}
public void swap(int[] nums, int start, int end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
}
}
@Test
public void sort_EmptyArray_ShouldHandleGracefully() {
int[] nums = {};
sort(nums);
assertArrayEquals(new int[0], nums);
}
@Test
public void sort_NaturalNumberArray_ShouldSortInAscendingOrder() {
int[] nums = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
sort(nums);
assertArrayEquals(new int[]{1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9}, nums);
}
@Test
public void sort_IntegerArray_ShouldSortInAscendingOrder() {
int[] nums = {10, -1, 2, 5, 0, 6, -3, 4};
sort(nums);
assertArrayEquals(new int[]{-3, -1, 0, 2, 4, 5, 6, 10}, nums);
}
@Test
public void sort_SingleElementArray_ShouldRemainUnchanged() {
int[] nums = {5};
sort(nums);
assertArrayEquals(new int[]{5}, nums);
}
@Test
public void sort_DuplicateElementsArray_ShouldSortInAscendingOrder() {
int[] nums = {4, 2, 2, 8, 3, 3, 1};
sort(nums);
assertArrayEquals(new int[]{1, 2, 2, 3, 3, 4, 8}, nums);
}
@Test
public void sort_NegativeNumberArray_ShouldSortInAscendingOrder() {
int[] nums = {-1, -2, -3, -4, -5};
System.out.println(Arrays.toString(new Solution3().sortArray(nums)));
}
class Solution3 {
public int[] sortArray(int[] nums) {
sort(nums, nums.length - 1);
return nums;
}
/**
* 堆排序思路
* 1. 依次遍历非叶节点 nonLeaf = (end - 1) / 2; --
* 选取左右两边比他大的替换上来不断替换直到最上面是最大的
* 2. 把最大的堆顶移动到最后确定一个最大值
* @param nums
* @param end
*/
public void sort(int[] nums, int end) {
if (end <= 0) {
return;
}
int nonLeaf = (end - 1) / 2;
while (nonLeaf >= 0) {
int left = 2 * nonLeaf + 1;
int right = 2 * nonLeaf + 2;
int maxIn = nonLeaf; // 父子三个节点的最大值
if (left <= end && nums[maxIn] < nums[left]) {
maxIn = left;
}
if (right <= end && nums[maxIn] < nums[right]) {
maxIn = right;
}
swap(nums, nonLeaf, maxIn);
// // noleaf至少有一个子节点
// if (left <= end &&right <= end) {
// if (nums[left] < nums[right]) {
// if (nums[right] > nums[nonLeaf]) {
// swap(nums, nonLeaf, right);
// }
// }else {
// if (nums[left] > nums[nonLeaf]) {
// swap(nums, nonLeaf, left);
// }
// }
// } else {
// // 只有左边一个节点
// if (nums[left] > nums[nonLeaf]) {
// swap(nums, nonLeaf, left);
// }
// }
nonLeaf--;
}
swap(nums, 0, end );
sort(nums, end - 1);
}
public void swap(int[] nums, int start, int end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
}
}
/**
* 所有非叶子节点x n/2 开始表示下面都是叶子节点找到子节点中的最大值如果比x 还大swap再排序下一个非叶子节点
*/
public void sort(int[] nums) {
sort(nums, nums.length - 1);
System.out.println(Arrays.toString(nums));
}
/**
* 堆排序思路
* 1. 依次遍历非叶节点 nonLeaf = (end - 1) / 2; --
* 选取左右两边比他大的替换上来不断替换直到最上面是最大的
* 2. 把最大的堆顶移动到最后确定一个最大值
* @param nums
* @param end
*/
public void sort(int[] nums, int end) {
if (end <= 0) {
return;
}
int nonLeaf = (end - 1) / 2;
while (nonLeaf >= 0) {
int left = 2 * nonLeaf + 1;
int right = 2 * nonLeaf + 2;
int maxIn = nonLeaf; // 父子三个节点的最大值
if (left <= end && nums[maxIn] < nums[left]) {
maxIn = left;
}
if (right <= end && nums[maxIn] < nums[right]) {
maxIn = right;
}
swap(nums, nonLeaf, maxIn);
// // noleaf至少有一个子节点
// if (left <= end &&right <= end) {
// if (nums[left] < nums[right]) {
// if (nums[right] > nums[nonLeaf]) {
// swap(nums, nonLeaf, right);
// }
// }else {
// if (nums[left] > nums[nonLeaf]) {
// swap(nums, nonLeaf, left);
// }
// }
// } else {
// // 只有左边一个节点
// if (nums[left] > nums[nonLeaf]) {
// swap(nums, nonLeaf, left);
// }
// }
nonLeaf--;
}
swap(nums, 0, end );
sort(nums, end - 1);
}
public void swap(int[] nums, int start, int end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
}
}

View File

@ -0,0 +1,81 @@
package cn.whaifree.leetCode.BackTracking;
import org.junit.Test;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/2/2 8:22
* @注释
*/
public class LeetCode216 {
@Test
public void test() {
Solution solution = new Solution();
solution.combinationSum3(9, 45).forEach(
list -> {
System.out.println(list);
}
);
}
class Solution {
List<List<Integer>> res = new LinkedList<>();
List<Integer> path = new ArrayList<>();
int sum = 0;
/**
* 相加之和为n的k个数的组合
* @param k
* @param n
* @return
*/
public List<List<Integer>> combinationSum3(int k, int n) {
circle(1, 9, n, k);
return res;
}
public void circle(int start, int end, int n, int k) {
if (path.size() == k && sum == n) {
res.add(new ArrayList<>(path));
return;
}
// 1. 如果sum>n了证明往后加只会更大因为都是正数就不再继续了
// sum>n
//
// 2. 如果 9个数要9个数
// 已经选择size
// 还需选择k-size
// 可以选择的数end-start
// 可以选择的数<还需选择的数 end-start<k-size
for (int i = start; i <= end ; i++) {
// 可以选择的数<还需选择的数
if (end - i + 1 < k - path.size()) {
return;
}
path.add(i);
sum += i;
// 如果 加上某个数已经超过了n那么剩下的正数都没必要再加了如1234后面只能选5678如果去了4加了5678必然会超过n
if (sum > n) {
path.remove(path.size() - 1);
sum -= i;
return;
}
circle(i + 1, end, n, k);
path.remove(path.size() - 1);
sum -= i;
}
}
}
}

View File

@ -0,0 +1,73 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/22 19:05
* @注释
*/
public class LeetCode222 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTree(new Integer[]{1, 2, 3, 4, 5, 6});
treeNode.printTree();
System.out.println(new Solution1().countNodes(treeNode));
}
class Solution {
public int countNodes(TreeNode root) {
return inLevel(root);
}
public int inLevel(TreeNode node) {
if (node==null) return 0;
int left = inLevel(node.left) + 1;
int right = inLevel(node.right) ;
return left + right;
}
}
class Solution1 {
public int countNodes(TreeNode root) {
return inLevel(root);
}
public int inLevel(TreeNode node) {
if (node == null) {
return 0;
}
// 计算左边深度
int leftDepth = 0;
TreeNode leftNode = node.left;
while (leftNode != null) {
leftNode = leftNode.left;
leftDepth++;
}
// 计算右边深度
int rightDepth = 0;
TreeNode rightNode = node.right;
while (rightNode != null) {
rightNode = rightNode.right;
rightDepth++;
}
// 如果两变深度一样那么该树是完全二叉树
if (leftDepth == rightDepth) {
return (2 << leftDepth) - 1;
}
// 如果两边深度不一样递归左右子节点+1
return inLevel(node.right) + inLevel(node.left) + 1;
}
}
}

View File

@ -0,0 +1,174 @@
package cn.whaifree.leetCode.Stack;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
/**
* 225. 用队列实现栈
*
* 请你仅使用两个队列实现一个后入先出LIFO的栈并支持普通栈的全部四种操作pushtoppop empty
*
* 实现 MyStack
*
* void push(int x) 将元素 x 压入栈顶
* int pop() 移除并返回栈顶元素
* int top() 返回栈顶元素
* boolean empty() 如果栈是空的返回 true 否则返回 false
*
* 注意
*
* 你只能使用队列的基本操作 也就是 push to backpeek/pop from frontsize is empty 这些操作
* 你所使用的语言也许不支持队列 你可以使用 list 列表或者 deque双端队列来模拟一个队列 , 只要是标准的队列操作即可
*
* 示例
*
* 输入
* ["MyStack", "push", "push", "top", "pop", "empty"]
* [[], [1], [2], [], [], []]
* 输出
* [null, null, null, 2, 2, false]
*
* 解释
* MyStack myStack = new MyStack();
* myStack.push(1);
* myStack.push(2);
* myStack.top(); // 返回 2
* myStack.pop(); // 返回 2
* myStack.empty(); // 返回 False
*
*/
public class LeetCode225 {
@Test
public void test() {
Deque<Integer> objects = new LinkedList<>();
objects.add(1);
objects.add(2);
objects.push(3);
System.out.println(objects.pop());
// objects.forEach(x -> System.out.println(x));
MyStack1 myStack = new MyStack1();
myStack.push(1);
myStack.push(2);
myStack.push(3);
System.out.println(myStack.top());
System.out.println(myStack.pop());
}
/**
* 每次入栈就加入其中的非空队列
* 出栈就全部移动到另一个队列并获取最后一个元素
*
* 队列用add // add 尾巴进
* 栈用push // push 头进
* pop 头出
*
* - push pop
* - 队列 add pop
*/
class MyStack {
Deque<Integer> queue1;
Deque<Integer> queue2;
public MyStack() {
queue1 = new LinkedList<>();
queue2 = new LinkedList<>();
}
public void push(int x) {
if (!queue1.isEmpty()) {
queue1.add(x);
} else {
queue2.add(x);
}
}
public int pop() {
if (!queue1.isEmpty()) {
// 将queue全部导入queue2并获取最后一个元素返回
while (queue1.size()!=1) {
queue2.add(queue1.pop());
}
return queue1.pop();
} else {
// 将queue2全部导入queue1并获取最后一个元素返回
while (queue2.size()!=1) {
queue1.add(queue2.pop());
}
return queue2.pop();
}
}
public int top() {
if (!queue1.isEmpty()) {
// 将queue全部导入queue2并获取最后一个元素返回
while (queue1.size()>1) {
queue2.add(queue1.pop());
}
Integer pop = queue1.pop();
queue2.add(pop);
return pop;
} else {
// 将queue2全部导入queue1并获取最后一个元素返回
while (queue2.size()>1) {
queue1.add(queue2.pop());
}
Integer pop = queue2.pop();
queue1.add(pop);
return pop;
}
}
public boolean empty() {
return queue1.isEmpty() && queue2.isEmpty();
}
}
/**
* push 的时候 把其替换到头部
*/
class MyStack1 {
Deque<Integer> queue;
public MyStack1() {
queue = new LinkedList<>();
}
public void push(int x) {
queue.add(x);
int size = queue.size();
while (size != 1) {
queue.add(queue.pop());
size--;
}
}
public int pop() {
return queue.pop();
}
public int top() {
return queue.peek();
}
public boolean empty() {
return queue.isEmpty();
}
}
}

View File

@ -0,0 +1,148 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/19 14:54
* @注释
*/
public class LeetCode226 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTree(new Integer[]{1, 2, 3, 4, 5});
treeNode.printTree();
TreeNode treeNode1 = new Solution2().invertTree(treeNode);
treeNode1.printTree();
}
class Solution {
public TreeNode invertTree(TreeNode root) {
reverse(root);
return root;
}
public void reverse(TreeNode root) {
if (root == null) {
return;
}
swap(root);
invertTree(root.left);
invertTree(root.right);
}
public void swap(TreeNode root) {
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
}
}
class Solution1 {
/**
* 层次遍历
* @param root
* @return
*/
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return root;
}
Deque<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode pop = queue.pop();
swap(pop);
if (pop.right != null) {
queue.add(pop.right);
}
if (pop.left != null) {
queue.add(pop.left);
}
}
return root;
}
public void swap(TreeNode root) {
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
}
}
class Solution2 {
/**
* 先序遍历
* @param root
* @return
*/
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return root;
}
Deque<TreeNode> stack = new LinkedList<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode pop = stack.pop();
swap(pop);
if (pop.right != null) {
stack.push(pop.right);
}
if (pop.left != null) {
stack.push(pop.left);
}
}
return root;
}
public void swap(TreeNode root) {
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
}
}
class Solution3 {
/**
* 先序遍历
* @param root
* @return
*/
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return root;
}
Deque<TreeNode> stack = new LinkedList<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode pop = stack.pop();
swap(pop);
if (pop.right != null) {
stack.push(pop.right);
}
if (pop.left != null) {
stack.push(pop.left);
}
}
return root;
}
public void swap(TreeNode root) {
TreeNode tmp = root.left;
root.left = root.right;
root.right = tmp;
}
}
}

View File

@ -0,0 +1,87 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Future;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/22 14:56
* @注释
*/
public class LeetCode228 {
public static void main(String[] args) throws IOException {
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(Paths.get("D:\\project\\LeetCode\\README.md"), StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(1024);
Future<Integer> result = fileChannel.read(buffer, 0);
while (!result.isDone()) {
// do something
}
}
@Test
public void test() {
int[] nums = {0, 2};
System.out.println(new Solution().summaryRanges(nums));
}
class Solution {
// public List<String> summaryRanges(int[] nums) {
// List<String> path = new ArrayList<>();
// List<String> res = new ArrayList<>();
// for (int i = 1; i < nums.length; i++) {
// if (nums[i] != nums[i - 1]) {
// StringBuilder str = new StringBuilder();
// for (int j = 0; j < path.size()-1; j++) {
// str.append(path.get(j));
// str.append("->");
// }
// str.append(path.get(path.size() - 1));
// path.clear();
// }
// path.add(String.valueOf(nums[i]));
// }
// }
public List<String> summaryRanges(int[] nums) {
List<String> res = new ArrayList<>();
int left = 0;
int right = 1;
while (right < nums.length) {
if (nums[right] != nums[right - 1] + 1) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(nums[left]);
if (left != right - 1) {
stringBuilder.append("->");
stringBuilder.append(nums[right - 1]);
}
res.add(stringBuilder.toString());
left = right;
}
right++;
}
if (left < nums.length) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(nums[left]);
if (left != right - 1) {
stringBuilder.append("->");
stringBuilder.append(nums[right - 1]);
}
res.add(stringBuilder.toString());
}
return res;
}
}
}

View File

@ -0,0 +1,129 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
import java.util.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/5 12:00
* @注释
*/
public class LeetCode23 {
@Test
public void test()
{
new Solution2().mergeKLists(
new ListNode[]{
ListNode.listNodeFromArray(new int[]{}),
ListNode.listNodeFromArray(new int[]{1, 3, 4}),
ListNode.listNodeFromArray(new int[]{2, 6})
}
).printList();
}
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists.length == 0) {
return null;
}
List<ListNode> arrayList = new ArrayList<>(Arrays.asList(lists));
return merge(arrayList);
}
public ListNode merge(List<ListNode> lists) {
// 删除list中所有null
// 使用removeIf()方法删除所有null元素
lists.removeIf(Objects::isNull);
if (lists.size() == 0) {
return null;
}
int minIndex = 0;
// 找到最小的返回
// 这个最小的的下一个就是递归的
// 找到最小的头节点的位置
for (int i = 0; i < lists.size(); i++) {
if (lists.get(minIndex).val > lists.get(i).val) {
minIndex = i;
}
}
ListNode minNode = lists.get(minIndex);
// 去掉本节点
lists.set(minIndex, minNode.next);
minNode.next = merge(lists);
return minNode;
}
}
class Solution1 {
public ListNode mergeKLists(ListNode[] lists) {
for (int i = 1; i < lists.length; i++) {
lists[i] = merge(lists[i], lists[i - 1]);
}
return lists[lists.length - 1];
}
public ListNode merge(ListNode one, ListNode two) {
if (one == null) {
return two;
} else if (two == null){
return one;
}
if (one.val < two.val) {
one.next = merge(one.next, two);
return one;
}else {
two.next = merge(one, two.next);
return two;
}
}
}
class Solution2 {
// 时间复杂度
// O(nlogk)其中 k lists的长度n 为所有链表的节点数之和
//著作权归作者所有商业转载请联系作者获得授权非商业转载请注明出处
public ListNode mergeKLists(ListNode[] lists) {
PriorityQueue<ListNode> queue = new PriorityQueue<>(new Comparator<ListNode>() {
@Override
public int compare(ListNode o1, ListNode o2) {
return o1.val - o2.val;
}
});
for (ListNode list : lists) {
if (list!=null) queue.add(list);
}
ListNode head = new ListNode(-1);
ListNode headIndex = head;
while (!queue.isEmpty()) {
ListNode poll = queue.poll();
headIndex.next = poll;
headIndex = headIndex.next;
if (poll.next != null) {
queue.add(poll.next);
}
}
return head.next;
}
}
}

View File

@ -0,0 +1,48 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/3 17:00
* @注释
*/
public class LeetCode230 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTreeByArray(5,3,6,2,4,null,null,1);
System.out.println(new Solution().kthSmallest(treeNode, 3));
}
class Solution {
int res = 0;
public int kthSmallest(TreeNode root, int k) {
if (root == null) {
return -1;
}
int left = kthSmallest(root.left, k);
if (left != -1) {
return left;
}
res++;
if (res == k) {
return root.val;
}
int right = kthSmallest(root.right, k);
if (right != -1) {
return right;
}
return -1;
}
}
}

View File

@ -0,0 +1,122 @@
package cn.whaifree.leetCode.Stack;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
/**
* 232. 用栈实现队列
*
* 请你仅使用两个栈实现先入先出队列队列应当支持一般队列支持的所有操作pushpoppeekempty
*
* 实现 MyQueue
*
* void push(int x) 将元素 x 推到队列的末尾
* int pop() 从队列的开头移除并返回元素
* int peek() 返回队列开头的元素
* boolean empty() 如果队列为空返回 true 否则返回 false
* 说明
*
* 只能 使用标准的栈操作 也就是只有 push to top, peek/pop from top, size, is empty 操作是合法的
* 你所使用的语言也许不支持栈你可以使用 list 或者 deque双端队列来模拟一个栈只要是标准的栈操作即可
*
* 示例 1
*
* 输入
* ["MyQueue", "push", "push", "peek", "pop", "empty"]
* [[], [1], [2], [], [], []]
* 输出
* [null, null, null, 1, 1, false]
*
* 解释
* MyQueue myQueue = new MyQueue();
* myQueue.push(1); // queue is: [1]
* myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
* myQueue.peek(); // return 1
* myQueue.pop(); // return 1, queue is [2]
* myQueue.empty(); // return false
*
*
* 提示
*
* 1 <= x <= 9
* 最多调用 100 pushpoppeek empty
* 假设所有操作都是有效的 例如一个空的队列不会调用 pop 或者 peek 操作
*
*
* 进阶
*
* 你能否实现每个操作均摊时间复杂度为 O(1) 的队列换句话说执行 n 个操作的总时间复杂度为 O(n) 即使其中一个操作可能花费较长时间
*/
public class LeetCode232 {
@Test
public void test() {
MyQueue myQueue = new MyQueue();
System.out.println(myQueue.empty());
myQueue.push(1);
myQueue.push(2);
myQueue.push(3);
myQueue.push(4);
System.out.println(myQueue.peek());
System.out.println(myQueue.pop());
System.out.println(myQueue.empty());
}
/**
只能 使用标准的栈操作 也就是只有 push to top, peek/pop from top, size, is empty 操作是合法的
一个空的队列不会调用 pop 或者 peek 操作
* // 进队列全部放到Enter栈
* // 一旦要出栈检查Out栈有没有如果没有将目前Enter栈全部弹到Out栈再弹出第一个
*
*/
class MyQueue {
Deque<Integer> stackEnter;
Deque<Integer> stackOut;
public MyQueue() {
this.stackEnter = new LinkedList<>();
this.stackOut = new LinkedList<>();
}
public void push(int x) {
stackEnter.push(x);
}
public int pop() {
int peek = peek();
stackOut.pop();
return peek;
}
public int peek() {
if (stackOut.isEmpty()) {
while (!stackEnter.isEmpty()) {
stackOut.push(stackEnter.pop());
}
}
// 不会对空操作
return stackOut.peek();
}
public boolean empty() {
return stackEnter.isEmpty() && stackOut.isEmpty();
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/
}

View File

@ -0,0 +1,105 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.function.BiConsumer;
public class LeetCode234 {
public static void main(String[] args) throws InterruptedException {
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
for (int i = 0; i < 10; i++) {
map.put("1", 1);
}
CountDownLatch countDownLatch = new CountDownLatch(10);
new Thread(new Runnable() {
@Override
public void run() {
map.forEach(
new BiConsumer<String, Integer>() {
@Override
public void accept(String s, Integer integer) {
System.out.println(s + ":" + integer);
}
}
);
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
map.put("i" + i, i);
countDownLatch.countDown();
}
}
}).start();
countDownLatch.await();
System.out.println(map.size());
}
@Test
public void test()
{
ListNode listNode = ListNode.listNodeFromArray(new int[]{1, 3, 3,2, 1});
System.out.println(new Solution().isPalindrome(listNode));
}
/**
* 1. 截取一半
* - 逆转对比
* 2. 输出到list中再回问判断
* 3.
*/
class Solution {
public boolean isPalindrome(ListNode head) {
int len = 0;
ListNode index = head;
while (index != null) {
len++;
index = index.next;
}
index = head;
for (int i = 0; i < len / 2; i++) {
index = index.next;
}
ListNode newHead = reverseList(index);
ListNode A = head;
ListNode B = newHead;
while (B != null) {
if (A.val != B.val) {
return false;
}
A = A.next;
B = B.next;
}
return true;
}
private ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next;
curr.next = prev;
prev = curr;
curr = nextTemp;
}
return prev;
}
}
}

View File

@ -0,0 +1,66 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/30 21:10
* @注释
*/
public class LeetCode235 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTreeByArray(6,2,8,0,4,7,9,null,null,3,5);
new Solution().lowestCommonAncestor(treeNode, treeNode.left.right, treeNode.left).printTree();
}
class Solution {
/**
* 1. p,q在两边直接返回
* 2. pq在左边向左递归
* 3. pq在右边向右递归
* @param root
* @param p
* @param q
* @return
*/
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// if (root == null) {
// return null;
// }
// if (root == p || root == q) {
// // 找到元素
// return root;
// }
// if (p.val < root.val && q.val > root.val) {
// return root;
// }
// if (p.val > root.val && q.val < root.val) {
// return root;
// }
// 只有这个有用
if (p.val > root.val && q.val > root.val) {
// 向右递归
return lowestCommonAncestor(root.right, p, q);
} else if (p.val < root.val && q.val < root.val) {
// 向左递归
return lowestCommonAncestor(root.left, p, q);
}
return root;
}
public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) {
if (root.val > p.val && root.val > q.val) return lowestCommonAncestor1(root.left, p, q);
if (root.val < p.val && root.val < q.val) return lowestCommonAncestor1(root.right, p, q);
return root;
}
}
}

View File

@ -0,0 +1,100 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/30 17:35
* @注释
*/
public class LeetCode236 {
@Test
public void test() {
TreeNode treeNode = TreeNode.constructTreeByArray(1, 2, 3, 4, 5, 6);
new Solution1().lowestCommonAncestor(treeNode, treeNode.left.right, treeNode.left).printTree();
}
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// 先找到两个树
// 用两个List记录路径
// 挨个对比找到最后一个公共的点
ArrayList<TreeNode> e1 = new ArrayList<>();
findNode(root, p, e1);
ArrayList<TreeNode> e2 = new ArrayList<>();
findNode(root, q, e2);
int minSize = Math.min(e1.size(), e2.size());
int index = minSize - 1;
while (index >= 0) {
if (e1.get(index) == e2.get(index)) {
return e1.get(index);
}
index--;
}
return null;
}
public boolean findNode(TreeNode root, TreeNode wantFindNode, List<TreeNode> path) {
if (root==null) return false;
path.add(root);
if (root == wantFindNode) {
return true;
}
boolean left = findNode(root.left, wantFindNode, path);
if (left == true) {
return true;
}
boolean right = findNode(root.right, wantFindNode, path);
if (right == true) {
return true;
}
path.remove(path.size() - 1);
return left || right;
}
}
class Solution1 {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root==null) return null;
// 左右找到两个树
// 如果找到树了返回该节点
if (root.val == p.val || root.val == q.val) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if(left == null && right == null) { // 若未找到节点 p q
return null;
}else if(left == null && right != null) { // 若找到一个节点
return right;
}else if(left != null && right == null) { // 若找到一个节点
return left;
}else { // 若找到两个节点
return root;
}
}
}
}

View File

@ -0,0 +1,77 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
import java.util.Arrays;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/17 13:58
* @注释
*/
public class LeetCode238 {
@Test
public void test() {
int[] nums = {1, 2, 3, 4};
int[] ints = productExceptSelf(nums);
for (int anInt : ints) {
System.out.println(anInt);
}
}
class Solution {
/**
* [-1,1,0,-3,3]
* -1 -1 0 0 0
* 0 0 0 -9 3
*
* @param nums
* @return
*/
public int[] productExceptSelf(int[] nums) {
int[] preMul = new int[nums.length];
preMul[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
preMul[i] = preMul[i - 1] * nums[i];
}
int[] afterMul = new int[nums.length];
afterMul[nums.length - 1] = nums[nums.length - 1];
for (int i = nums.length - 2; i >= 0; i--) {
afterMul[i] = afterMul[i + 1] * nums[i];
}
for (int i = 0; i < nums.length; i++) {
int pre = (i > 0) ? preMul[i - 1] : 1;
int after = i < nums.length - 1 ? afterMul[i + 1] : 1;
nums[i] = pre * after;
}
return nums;
}
}
//维护两个变量beforeSum表示前缀和afterSum表示后缀和
// 两个指针不断缩小会相交
public int[] productExceptSelf(int[] nums) {
int n = nums.length;
int[] ans = new int[n];
Arrays.fill(ans, 1);
int beforeSum = 1;
int afterSum = 1;
int left = 0;
int right = nums.length - 1;
while (left < nums.length) {
ans[left] *= beforeSum;
ans[right] *= afterSum;
beforeSum *= nums[left];
afterSum *= nums[right];
left++;
right--;
}
return ans;
}
}

View File

@ -0,0 +1,94 @@
package cn.whaifree.leetCode.Stack;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
/**
* @Author whai文海
* @Date 2024/1/9 14:49
* @注释
*
* 239. 滑动窗口最大值
* 给你一个整数数组 nums有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧你只可以看到在滑动窗口内的 k 个数字滑动窗口每次只向右移动一位
*
* 返回 滑动窗口中的最大值
*
*
*
* 示例 1
*
* 输入nums = [1,3,-1,-3,5,3,6,7], k = 3
* 输出[3,3,5,5,6,7]
* 解释
* 滑动窗口的位置 最大值
* --------------- -----
* [1 3 -1] -3 5 3 6 7 3
* 1 [3 -1 -3] 5 3 6 7 3
* 1 3 [-1 -3 5] 3 6 7 5
* 1 3 -1 [-3 5 3] 6 7 5
* 1 3 -1 -3 [5 3 6] 7 6
* 1 3 -1 -3 5 [3 6 7] 7
* 示例 2
*
* 输入nums = [1], k = 1
* 输出[1]
*/
public class LeetCode239 {
@Test
public void test() {
int[] nums = new int[]{1, 3, -1, -3, 5, 3, 6, 7};
int[] res = new Solution().maxSlidingWindow(nums, 3);
for (int re : res) {
System.out.println(re);
}
}
class Solution {
/**
* 维持一个单调队列队列里存放的是对应值得下标
* 如果 此次队列头部指针为i即num[i]为目前窗口的最大值
* - 如果这个最大值的下标不在下一个窗口的范围内那么需要将这个值删除
* @param nums
* @param k
* @return
*/
public int[] maxSlidingWindow(int[] nums, int k) {
// 单调队列维持一个单调递减的队列
Deque<Integer> queue = new LinkedList<>();
// n个元素k个窗口一共为n-k个输出
int[] res = new int[nums.length - k + 1];
for (int i = 0; i < nums.length; i++) {
// 判断当前队首的值是否在本次的窗口内i-k为窗口左边
if (!queue.isEmpty()&&queue.peek() <= i - k) {
queue.pop();
}
// 保证单调递减
while (!queue.isEmpty() && nums[i] >= nums[queue.peekLast()]) {
queue.removeLast();
}
queue.addLast(i);
// 从第k个开始才有结果
if(i+1 >= k){
res[i+1-k] = nums[queue.peek()];
}
// 从第k个开始先把值存进去在下次循环判断是否这个值存在于这个新的区间中
}
return res;
}
}
}

View File

@ -0,0 +1,113 @@
package cn.whaifree.leetCode.LinkedList;
import org.junit.Test;
import cn.whaifree.leetCode.model.ListNode;
/**
* 两两交换链表中的节点
* 中等
* 相关标签
* 相关企业
* 给你一个链表两两交换其中相邻的节点并返回交换后链表的头节点你必须在不修改节点内部的值的情况下完成本题只能进行节点交换
*
* 示例 1
* 输入head = [1,2,3,4]
* 输出[2,1,4,3]
*
* 示例 2
* 输入head = []
* 输出[]
*
* 示例 3
* 输入head = [1]
* 输出[1]
*
*/
public class LeetCode24 {
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
* pre index tmp
* 0 -> 1 -> 2 -> 3 -> 4 -> 5
*
* pre index tmp
* 0 1 -> 2 -> 3 -> 4 -> 5
* ----------^
*
* -----------
* pre index tmp |
* 0 1 -> 2 -> 3 -> 4 -> 5
* ----------^
*
* -----------
* pre index tmp |
* 0 1 <- 2 -> 3 -> 4 -> 5
* ----------^
*
* pre tmp index
* 0-> 2 -> 1 -> 3 -> 4 -> 5
*
*
* pre tmp index
* 0-> 2 -> 1 -> 3 -> 4 -> 5
*/
public ListNode swapPairs(ListNode head) {
if (head == null) {
return head;
}
ListNode pre = new ListNode(0, head);
ListNode tmp = head.next;
ListNode index = head;
head = pre;
while (tmp != null) {
pre.next = tmp;
index.next = tmp.next;
tmp.next = index;
pre = index;
index = pre.next;
tmp = index == null ? null : index.next;
}
return head.next;
}
public ListNode swapPairsD(ListNode head) {
if (head == null) {
return head;
}
return swap(head, head.next);
}
/**
* 递归的关键
* 1. 结束条件
* 2. 递归条件只考虑当前这一点点的情况剩下的交给下次递归
* @param pre
* @param after
* @return
*/
public ListNode swap(ListNode pre, ListNode after) {
if (pre == null || after == null) {
return pre;
}
// 递归后面的指针
pre.next = swap(after.next, after.next == null ? null : after.next.next);
after.next = pre;
return after;
}
@Test
public void test() {
ListNode listNode = swapPairsD(ListNode.listNodeFromArray(new int[]{1,2,3,4,5}));
ListNode.printList(listNode);
}
}

View File

@ -0,0 +1,98 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
public class LeetCode2487 {
@Test
public void test() {
new Solution1().removeNodes(ListNode.listNodeFromArray(new int[]{5, 2, 13, 3, 8})).printList();
}
/**
* 找到最大的节点找到下一个最大的节点此区间全部删掉
* 每次删除后MaxNode为null
*
* 即最后变成了递减的链表
*
*/
class Solution {
/**
* 递归
* @param head
* @return
*/
// public ListNode removeNodes(ListNode head) {
// ListNode dummy = new ListNode(0, head);
// ListNode pre = dummy;
// ListNode index = head;
// ListNode maxNode = dummy;
// while (index != null) {
// if (index.val > maxNode.val) {
// maxNode = index;
// // 删除pre到maxNode的前一个节点
// pre.next = maxNode;
// maxNode.next = removeNodes(maxNode.next);
// }
// index = index.next;
// }
//
// return dummy.next;
// }
public ListNode removeNodes(ListNode head) {
return remove(new ListNode(0, head));
}
public ListNode remove(ListNode head) {
if (head == null) {
return null;
}
head.next = remove(head.next);
if (head.next != null && head.val < head.next.val) {
return head.next;
} else {
return head;
}
}
}
class Solution1 {
public ListNode removeNodes(ListNode head) {
ListNode newHead = reverse(head);
// 变成从右往左边移除比newHead小的
ListNode index = newHead;
ListNode tmpMaxNode = newHead;
while (index.next != null) {
if (index.next.val < tmpMaxNode.val) {
index.next = index.next.next;
} else {
index = index.next;
tmpMaxNode = index;
}
}
// 最后那个数是永远不会删除的
return reverse(newHead);
}
public ListNode reverse(ListNode head) {
// 反转链表
ListNode index = head;
ListNode pre = null;
while (index != null) {
ListNode tmp = index.next;
index.next = pre;
pre = index;
index = tmp;
}
// {5, 2, 13, 3, 8}
return pre;
}
}
}

View File

@ -0,0 +1,62 @@
package cn.whaifree.leetCode.LinkedList;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/23 13:43
* @注释
*/
public class LeetCode25 {
@Test
public void test() {
ListNode head = ListNode.listNodeFromArray(new int[]{1, 2, 3, 6, 7, 8, 9, 20});
// new Solution().reverse(null, head, 3).printList();
new Solution().reverseKGroup(head, 2).printList();
}
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode pre = new ListNode(-1, head);
return reverseRange(pre.next, k);
}
/**
* pre往后k个元素翻转
* @param pre
* @param k
* @return
*/
public ListNode reverseRange(ListNode pre, int k) {
ListNode index = pre;
ListNode nextNode = pre;
int i = 0;
while (i < k && nextNode != null) {
nextNode = nextNode.next;
i++;
}
if (i < k) {
return pre;
}
ListNode reverseAfterHead = reverse(null, index, k);
index.next = reverseRange(nextNode, k);
return reverseAfterHead;
}
public ListNode reverse(ListNode pre, ListNode after,int k) {
if (k <= 0) {
return pre;
}
if (after == null) {
return pre;
}
ListNode next = after.next;
after.next = pre;
return reverse(after, next, k - 1);
}
}
}

View File

@ -0,0 +1,173 @@
package cn.whaifree.leetCode.Tree;
import cn.whaifree.leetCode.model.Node;
import cn.whaifree.leetCode.model.TreeNode;
import org.junit.Test;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/1/22 21:54
* @注释
*/
public class LeetCode257 {
@Test
public void test() {
TreeNode root = TreeNode.constructTree(new Integer[]{1, 2, 3, 5,6,7,8,9,0,6});
root.printTree();
System.out.println(new Solution3().binaryTreePaths(root));
}
class Solution {
List<String> res = new ArrayList<String>();
public List<String> binaryTreePaths(TreeNode root) {
if (root == null) {
return res;
}
deal(root, "");
return res;
}
public void deal(TreeNode root, String s) {
if (root == null) return;
if (root.left == null && root.right == null) {
res.add(new StringBuilder(s).append(root.val).toString());
}
String tmp = new StringBuilder(s).append(root.val).append("->").toString();
deal(root.left, tmp);
deal(root.right, tmp);
}
}
class Solution1 {
List<String> res = new ArrayList<String>();
public List<String> binaryTreePaths(TreeNode root) {
if (root == null) {
return res;
}
deal(root, "");
return res;
}
public void deal(TreeNode treeNode, String s) {
if (treeNode==null) return;
//根节点
if (treeNode.right == null && treeNode.left == null) {
res.add(s + treeNode.val);
// res.add(new StringBuilder().append(s).append(treeNode.val).toString());
}
// String tmp = new StringBuilder().append(s).append("->").append(treeNode.val).toString();
String tmp = s + treeNode.val + "->";
deal(treeNode.left, tmp);
deal(treeNode.right, tmp);
}
}
class Solution2 {
List<String> res = new ArrayList<String>();
List<Integer> route = new ArrayList<Integer>();
public List<String> binaryTreePaths(TreeNode root) {
if (root == null) {
return res;
}
deal(root);
return res;
}
public void deal(TreeNode treeNode) {
if (treeNode == null) {
return;
}
route.add(treeNode.val);
if (treeNode.left == null && treeNode.right == null) {
// 根节点
// 可以知道结果了
StringBuilder stringBuilder = new StringBuilder();
int size = route.size();
for (int i = 0; i < size - 1; i++) {
stringBuilder.append(route.get(i)).append("->");
}
stringBuilder.append(route.get(size - 1));
res.add(stringBuilder.toString());
return;
}
if (treeNode.right != null) {
deal(treeNode.right);
// 回溯
route.remove(route.size() - 1);
}
if (treeNode.left != null) {
deal(treeNode.left);
route.remove(route.size() - 1);
}
}
}
class Solution3 {
public List<String> binaryTreePaths(TreeNode root) {
List<String> res = new ArrayList<String>();
if (root == null) {
return res;
}
Deque<Object> stack = new ArrayDeque<>();
stack.add(root);
stack.add(root.val + "");
while (!stack.isEmpty()) {
TreeNode nodePeek = (TreeNode) stack.pop();
String s = (String) stack.pop();
// 叶子节点
if (nodePeek.left == null && nodePeek.right == null) {
// s += "->" + nodePeek.val;
res.add(s);
}
// 左右进栈
if (nodePeek.left != null) {
stack.add(nodePeek.left);
stack.add(new StringBuilder().append(s).append("->").append(nodePeek.left.val).toString());
}
if (nodePeek.right != null) {
stack.add(nodePeek.right);
stack.add(new StringBuilder().append(s).append("->").append(nodePeek.right.val).toString());
}
}
return res;
}
}
}

View File

@ -0,0 +1,91 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
/**
* 删除有序数组中的重复项
* 简单
* 相关标签
* 相关企业
* 提示
* 给你一个 非严格递增排列 的数组 nums 请你 原地 删除重复出现的元素使每个元素 只出现一次 返回删除后数组的新长度元素的 相对顺序 应该保持 一致 然后返回 nums 中唯一元素的个数
*
* 考虑 nums 的唯一元素的数量为 k 你需要做以下事情确保你的题解可以被通过
*
* 更改数组 nums 使 nums 的前 k 个元素包含唯一元素并按照它们最初在 nums 中出现的顺序排列nums 的其余元素与 nums 的大小不重要
* 返回 k
* 判题标准:
*
* 系统会用下面的代码来测试你的题解:
*
* int[] nums = [...]; // 输入数组
* int[] expectedNums = [...]; // 长度正确的期望答案
*
* int k = removeDuplicates(nums); // 调用
*
* assert k == expectedNums.length;
* for (int i = 0; i < k; i++) {
* assert nums[i] == expectedNums[i];
* }
* 如果所有断言都通过那么您的题解将被 通过
*
*
*
* 示例 1
*
* 输入nums = [1,1,2]
* 输出2, nums = [1,2,_]
* 解释函数应该返回新的长度 2 并且原数组 nums 的前两个元素被修改为 1, 2 不需要考虑数组中超出新长度后面的元素
* 示例 2
*
* 输入nums = [0,0,1,1,1,2,2,3,3,4]
* 输出5, nums = [0,1,2,3,4]
* 解释函数应该返回新的长度 5 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 不需要考虑数组中超出新长度后面的元素
*
*
* 提示
*
* 1 <= nums.length <= 3 * 104
* -104 <= nums[i] <= 104
* nums 已按 非严格递增 排列
*/
public class LeetCode26 {
public int removeDuplicates(int[] nums) {
// 保证return k 的k nums 前k个为唯一递增的
int left = 0; // 左指针指向无重复元素数组的起始位置
int right = 1; // 右指针指向当前元素数组的位置
while (right < nums.length) {
if (nums[right] == nums[left]) { // 如果右指针指向的元素等于左指针指向的元素
right++; // 则右指针向右移动
} else {
nums[++left] = nums[right++]; // 若不相等则将当前元素放入无重复元素数组中并同时将左指针和右指针向右移动
}
}
return left + 1; // 返回无重复元素数组的长度
}
public int removeDuplicates1(int[] nums) {
// 保证return k 的k nums 前k个为唯一递增的
int left = 0;
int right = 1;
int jump = 0;
while (right < nums.length) {
if (nums[right] == nums[left]) {
right++;
jump++;
} else {
nums[left + 1] = nums[right];
right++;
left++;
}
}
return left + 1;
}
@Test
public void test() {
System.out.println(removeDuplicates(new int[]{1,1,2}));
}
}

View File

@ -0,0 +1,164 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/28 16:59
* @注释
*/
public class LeetCode2602 {
@Test
public void test()
{
Solution solution = new Solution();
int[] nums = {3,1,6,8};
int[] queries = {1,5};
List<Long> res = solution.minOperations(nums, queries);
res.forEach(System.out::println);
}
/**
* 超时
*/
class Solution {
public List<Long> minOperations(int[] nums, int[] queries) {
List<Long> res = new ArrayList<>();
for (int query : queries) {
res.add(target(nums, query));
}
return res;
}
public long target(int[] nums, int target) {
long res = 0;
for (int num : nums) {
res += Math.abs(target - num);
}
return res;
}
}
class Solution1 {
public List<Long> minOperations(int[] nums, int[] queries) {
List<Long> res = new ArrayList<>();
Arrays.sort(nums);
// 排序后找到对应的元素左边小于右边大于
// 求前缀和
int length = nums.length;
long[] preSum = new long[length + 1];
for (int i = 0; i < length; i++) {
preSum[i + 1] = preSum[i] + nums[i];
}
for (int target : queries) {
int index = findIndex(nums, target);
long left = (long) index * target - preSum[index];
// index 为横坐标 target为纵坐标高度 preSum为index位置前面的总和
long right = preSum[length] - preSum[index] - (long) target * (length - index);
res.add(left + right);
}
// 一侧的前缀和与 平均值*一侧区间长度 就代表这一侧的总操作数
return res;
}
public int findIndex(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] == target) {
return mid;
} else if (nums[mid] > target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return right;
}
}
@Test
public void test1()
{
Solution2 solution2 = new Solution2();
int[] nums = {3,1,6,8};
int[] queries = {5};
List<Long> res = solution2.minOperations(nums, queries);
res.forEach(System.out::println);
}
class Solution2 {
public List<Long> minOperations(int[] nums, int[] queries) {
Arrays.sort(nums);
// 计算前缀和
long[] preSum = new long[nums.length + 1];
for (int i = 1; i < preSum.length; i++) {
preSum[i] = preSum[i - 1] + nums[i - 1];
}
List<Long> res = new ArrayList<>();
for (int query : queries) {
res.add(getOperation(nums, query, preSum));
}
return res;
}
/**
* <img src="http://42.192.130.83:9000/picgo/imgs/1679808210-FVsAou-t3.png">
* </img>
* @param nums 原数组
* @param target 目标
* @param preSum 前缀和
* @return
*/
public Long getOperation(int[] nums, int target,long[] preSum) {
int index = findIndex(nums, target);
// index左边全部比他小右边全部比他大
// 0 - index 为小于他的数字个数 index-length为大于他的个数
// 小于他的数的总和 = 小于的个数 index * (target-nums[0]) - index位置的前缀和前缀和就是一个下三角形的面积
long leftIncr = (long) index * target - preSum[index];
long rightIncr =
preSum[nums.length] - preSum[index]
- (long) target * (nums.length - index);
return leftIncr + rightIncr;
}
/**
* 二分查找
* @param nums 有序数组
* @param target
* @return
*/
public int findIndex(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = (right + left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return left;
}
}
}

Some files were not shown because too many files have changed in this diff Show More