Compare commits

...

5 Commits

Author SHA1 Message Date
b6e5672f09 feat(leetcode): 添加多个 leetcode 问题的解决方案
- 新增了多个 leetcode 问题的 Java 解决方案,包括:
  - 问题 16: 最接近的三数之和
  - 问题 43: 字符串相乘
  - 问题 148: 排序链表
  - 问题274: H 指数
  - 问题 322: 零钱兑换
  - 问题 377: 组合总和Ⅳ
  - 问题474: 一和零
  - 问题 740: 删除并获得最大点数
- 更新了部分现有代码文件,优化了结构和注释

Default Changelist
.gitignore
AbstractClass.java
AbstractFactoryPattern.java
application.yaml
AProviderController.java
AService.java
BProviderController.java
BroomFilter.java
BService.java
CacheComparatorDemo.java
CacheConfig.java
CacheConstants.java
CacheDecoratorController.java
DynamicThreadPoolController.java
EventController.java
FactoryAndStrategy.java
FilterConfig.java
GlobalExceptionHandler.java
HttpStatus.java
IdempotenceController.java
LeetCode002.java
LeetCode16.java
LeetCode33.java
LeetCode43.java
LeetCode84.java
LeetCode148.java
LeetCode274.java
LeetCode322.java
LeetCode377.java
LeetCode474.java
LeetCode740.java
LimitType.java
ListNode.java
LoadBalanceConfig.java
MinioController.java
mvnw
mvnw.cmd
MyAutoConfiguration.java
P1.java
PersonProtocol.proto
pom.xml
protocolDemo.java
RabbitMQController.java
RateLimitAspect.java
RateLimiter.java
RedEnvelopeController.java
RedisConfig.java
RedisDataTest.java
redisson.yaml
RedissonConfig.java
RestConfig.java
ResVo.java
RobEnvelope.lua
SelfFilter.java
spring.factories
SpringDemoApplication.java
SpringDemoApplicationTests.java
SSEEmitter.java
TestController.java
UserService.java
WhiteListController.java
WxQrLoginController.java
工厂模式的几种类型,简单工厂、工厂方法、抽象工厂.md
Unversioned Files
D:\project\LeetCode\SpringCloud\ServiceA\src\main\resources\application.yaml
D:\project\LeetCode\SpringCloud\ServiceB\src\main\resources\application.yaml
D:\project\LeetCode\SpringCloud\ServiceA\pom.xml
D:\project\LeetCode\SpringCloud\ServiceB\pom.xml
D:\project\LeetCode\SpringCloud\pom.xml
D:\project\LeetCode\SpringCloud\ServiceA\src\main\java\com\whai\springcloud\servicea\ServiceAApplication.java
D:\project\LeetCode\SpringCloud\ServiceA\src\test\java\com\whai\springcloud\servicea\ServiceAApplicationTests.java
D:\project\LeetCode\SpringCloud\ServiceB\src\main\java\com\whai\springcloud\serviceb\ServiceBApplication.java
D:\project\LeetCode\SpringCloud\ServiceB\src\test\java\com\whai\springcloud\serviceb\ServiceBApplicationTests.java
D:\project\LeetCode\SpringCloud\ServiceA\src\test\java\com\whai\springcloud\springcloud\SpringCloudApplicationTests.java
D:\project\LeetCode\SpringCloud\ServiceB\src\test\java\com\whai\springcloud\springcloud\SpringCloudApplicationTests.java
2024-10-31 11:27:58 +08:00
7ea67e280f 修改LeetCode目录结构,不分类 2024-10-28 14:49:49 +08:00
aee514923d 修改LeetCode目录结构,不分类 2024-10-28 14:47:24 +08:00
25f4784daa feat(springDemo): 添加 Server-Sent Events (SSE) 功能和代理演示
- 新增 SSEEmitter 类实现 Server-Sent Events功能
- 添加 ProxyDemo 类演示动态代理
- 更新 UserService 类,增加 Bean 生命周期相关注释
- 调整 application.yaml 文件格式
2024-10-22 23:23:03 +08:00
72843c9027 feat(redo): 添加新的练习代码和解决方案
- 新增 LeetCode 69、135、376、763题目的解决方案
- 添加面试题练习代码
- 新建 SQL 查询练习题 stu,列 name, score, course,查询每一科分数大于 60 的学生姓名
2024-10-22 19:38:49 +08:00
344 changed files with 4826 additions and 2463 deletions

View File

@ -14,7 +14,6 @@
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>17</maven.compiler.source>
@ -24,6 +23,12 @@
<dependencies>
<!--jdbc Driver-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
@ -33,7 +38,6 @@
</dependency>
<!-- JPA API -->
<dependency>
<groupId>javax.persistence</groupId>

View File

@ -54,5 +54,6 @@ public class FactoryAndStrategy {
}
}
}

View File

@ -2,6 +2,11 @@ package cn.whaifree.designPattern.kama.CreateType.AbstractFactoryPattern;
public class AbstractFactoryPattern {
/**
* AbstractFactory--> ModernFactory --|
* --> ClassicFactory --|-->Sofa OR Chair
* @param args
*/
// https://kamacoder.com/problempage.php?pid=1077
public static void main(String[] args) {

View File

@ -0,0 +1,57 @@
### 简单工厂
一个工厂生产多种产品
```java
public static Product createProduct(String type) {
if ("A".equalsIgnoreCase(type)) {
return new ProductA();
} else if ("B".equalsIgnoreCase(type)) {
return new ProductB();
}
throw new IllegalArgumentException("Unknown product type");
}
```
### 工厂方法
对工厂抽象
```java
// 抽象工厂接口
interface Factory {
Product createProduct();
}
// 具体工厂A
class FactoryA implements Factory {
@Override
public Product createProduct() {
return new ProductA();
}
}
public static void main(String[] args) {
Factory factory = new FactoryA();
Product product = factory.createProduct();
product.use(); // 输出: Using Product A
}
```
### 抽象工厂
对产品再次抽象出不同属性
```java
// 产品族A接口
interface AbstractProductA {
void featureA();
}
// 具体产品A1
class ProductA1 implements AbstractProductA {
@Override
public void featureA() {
System.out.println("Feature A1");
}
}
```

View File

@ -0,0 +1,79 @@
package cn.whaifree.interview.PA;
import java.util.Scanner;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/30 17:38
* @注释
*/
public class P1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext hasNextLine 的区别
while (in.hasNextInt()) { // 注意 while 处理多个 case
int n = in.nextInt();
int m = in.nextInt();
/**
* 0 1 2
* 0 0 0 0
* 1 1 1 1
* 2 1 2 3
* 3 1 3 6
*/
int[] dp = new int[m + 1];
dp[0] = 1;
for (int i = 0; i < n; i++) {
for (int j = 1; j <= m; j++) {
dp[j] = dp[j] + dp[j - 1];
}
}
System.out.println(dp[m]);
}
}
}
class p2{
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String str = scanner.next();
int res = 0;
for (int right = 0; right <= str.length(); right++) {
for (int left = 0; left < right; left++) {
String leftStr = str.substring(0, left);
String rightStr = str.substring(right, str.length());
String concat = leftStr + rightStr;
if (!concat.isEmpty() && huiwen(concat)) {
System.out.println(concat);
res++;
}
}
}
System.out.println(res);
}
public static boolean huiwen(String str){
int left = 0;
int right = str.length() - 1;
while (left < right) {
if (str.charAt(left) != str.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
}

View File

@ -0,0 +1,59 @@
package cn.whaifree.interview.jr;
import java.util.Scanner;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/22 12:11
* @注释
*/
public class p1 {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int people = in.nextInt();
int gzNum = in.nextInt();
int[] nums = new int[people];
for (int i = 0; i < people; i++) {
nums[i] = in.nextInt();
}
int[] gzNums = new int[gzNum];
for (int i = 0; i < nums.length; i++) {
int want = nums[i];
gzNums[want - 1]++;
}
int res = 0;
for (int num : gzNums) {
int needSum = num / 2;
if (num % 2 == 1) {
res += (needSum + 1);
} else {
res += (needSum);
}
}
System.out.println(res);
}
}
class p2{
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext hasNextLine 的区别
int v0 = in.nextInt(); // 初始速度
int x = in.nextInt(); // v=v0+t*x
int y = in.nextInt(); // 总里程
// t1 = y / v = y / (v0+t*x)
// t = 2 / (t) t
// 速度t 2 2/t=2.8284271 t = 2/更好8 = 根号2/2
double t = Math.sqrt(2) / 2;
System.out.println(y / (v0 + t * x));
}
}

View File

@ -1,127 +0,0 @@
package cn.whaifree.leetCode.Hash;
import cn.whaifree.leetCode.model.ListNode;
import org.junit.Test;
import java.security.Key;
import java.util.HashMap;
public class LeeCode146 {
@Test
public void test() {
LRUCache lruCache = new LRUCache(2);
lruCache.put(1, 1);
lruCache.put(2, 2);
System.out.println(lruCache.get(1));
lruCache.put(3, 3);
System.out.println(lruCache.get(2));
lruCache.put(4, 4);
System.out.println(lruCache.get(1));
System.out.println(lruCache.get(3));
System.out.println(lruCache.get(4));
}
class LRUCache {
static class EntryNode {
Integer key = null;
Integer object = null;
EntryNode pre = null;
EntryNode after = null;
public EntryNode(Integer object, EntryNode pre, EntryNode after) {
this.object = object;
this.pre = pre;
this.after = after;
}
public EntryNode(Integer key, Integer object) {
this.key = key;
this.object = object;
}
public EntryNode() {
}
}
HashMap<Integer, EntryNode> caches;
EntryNode head;
EntryNode tail;
Integer size = null;
public LRUCache(int capacity) {
caches = new HashMap<>();
size = capacity;
head = new EntryNode();
tail = new EntryNode();
head.after = tail;
tail.pre = head;
}
/**
* 1. 先判断hashmap中有没有
* 2. 如果有
*
* @param key
* @return
*/
public int get(int key) {
EntryNode entryNode = caches.get(key);
if (entryNode == null) {
return -1;
}
deleteNode(entryNode);
addNode(entryNode);
return entryNode.object;
}
public void put(int key, int value) {
if (caches.containsKey(key)) {
EntryNode entryNode = caches.get(key);
entryNode.object = value;
deleteNode(entryNode);
addNode(entryNode);
return;
}
EntryNode v = new EntryNode(key, value);
caches.put(key, v);
addNode(v);
if (caches.size() > size) {
//删除最早那个
caches.remove(head.after.key);
deleteNode(head.after);
}
}
/**
* 删除某个节点
*
* @param entryNode
*/
public void deleteNode(EntryNode entryNode) {
entryNode.pre.after = entryNode.after;
entryNode.after.pre = entryNode.pre;
}
/**
* 在尾部增加某个节点
*
* @param node
*/
public void addNode(EntryNode node) {
EntryNode pre = tail.pre;
pre.after = node;
node.pre = pre;
node.after = tail;
tail.pre = node;
}
}
}

View File

@ -1,74 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.io.Serializable;
import java.util.HashMap;
/**
* 1. 两数之和
*
* 给定一个整数数组 nums 和一个整数目标值 target请你在该数组中找出 和为目标值 target 的那 两个 整数并返回它们的数组下标
*
* 你可以假设每种输入只会对应一个答案但是数组中同一个元素在答案里不能重复出现
*
* 你可以按任意顺序返回答案
*
* 示例 1
*
* 输入nums = [2,7,11,15], target = 9
* 输出[0,1]
* 解释因为 nums[0] + nums[1] == 9 返回 [0, 1]
* 示例 2
*
* 输入nums = [3,2,4], target = 6
* 输出[1,2]
* 示例 3
*
* 输入nums = [3,3], target = 6
* 输出[0,1]
*
*
* 提示
*
* 2 <= nums.length <= 104
* -109 <= nums[i] <= 109
* -109 <= target <= 109
* 只会存在一个有效答案
*
*
* 进阶你可以想出一个时间复杂度小于 O(n2) 的算法吗
*/
public class LeetCode1 implements Serializable {
@Test
public void test() {
int[] ints = new Solution().twoSum(new int[]{1, 2, 3, 4}, 4);
for (int anInt : ints) {
System.out.println(anInt);
}
}
class Solution {
/**
* 时间复杂度 O(N) map.containsKey(key)的时间复杂度是O(1)因为Map的containsKey方法使用哈希表实现可以在常数时间内判断Map中是否包含指定的键
* 空间复杂度 O(N)
* @param nums
* @param target
* @return
*/
public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int key = target - nums[i];
if (map.containsKey(key)) {
return new int[]{i, map.get(key)};
}else {
map.put(nums[i], i);
}
}
return null;
}
}
}

View File

@ -1,45 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.HashSet;
import java.util.Set;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/21 13:53
* @注释
*/
public class LeetCode128 {
@Test
public void test() {
int[] nums = {4, 1, 3, 2};
System.out.println(longestConsecutive(nums));
}
public int longestConsecutive(int[] nums) {
Set<Integer> set = new HashSet<>();
for (int num : nums) {
set.add(num);
}
int longest = 0;
// ON
for (int num : set) {
// 这里是关键说明这个元素i是某一组排序的开头不存在i-1的元素
if (!set.contains(num-1)){
int len = 1;
while (set.contains(++num)) {
len++;
}
longest = Math.max(longest, len);
}
}
return longest;
}
}

View File

@ -1,66 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/20 22:35
* @注释
*/
public class LeetCode136 {
class Solution {
public int singleNumber(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
for (Map.Entry<Integer, Integer> integerIntegerEntry : map.entrySet()) {
if (integerIntegerEntry.getValue() == 1) {
return integerIntegerEntry.getKey();
}
}
return 0;
}
}
@Test
public void test() {
Solution1 solution = new Solution1();
int[] nums = {7, 10, 7};
int res = solution.singleNumber(nums);
System.out.println(res);
}
class Solution1 {
/**
* 任何数自身作^==0
*
* 某个元素只出现一次以外**其余每个元素均出现两次** ^后就为0
*
* @param nums
* @return
*/
public int singleNumber(int[] nums) {
int res = 0;
for (int num : nums) {
// 7^7=0
// 7^10=1101
// 7^10^7=1010(10)
System.out.println(Integer.toBinaryString(num));
res ^= num;
System.out.println(Integer.toBinaryString(res));
}
return res;
}
}
public static void main(String[] args) {
System.out.println(Integer.toBinaryString(7));
System.out.println(Integer.toBinaryString(10));
System.out.println(Integer.toBinaryString(7 ^ 10));
}
}

View File

@ -1,68 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.*;
import java.util.function.Consumer;
public class LeetCode15 {
@Test
public void test() {
new Solution().threeSum(new int[]{-1, 0, 1, 2, -1, -4}).forEach(integers -> {
System.out.println();
integers.forEach(
integer -> System.out.print(integer + " ")
);
});
}
class Solution {
/**
* TODO 2024-1-3 用三指针没做出来
* @param nums
* @return
*/
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> o = new ArrayList<>();
// 排序后第一个就大于0必然不可能有结果
if (nums[0] > 0) {
return o;
}
for (int i = 0; i < nums.length; i++) {
int left = i + 1;
int right = nums.length - 1;
// 如果前后两个i 相同跳过
if (i > 0 && nums[i] == nums[i - 1]) { // 去重a
continue;
}
while (left < right) {
int number = nums[i] + nums[right] + nums[left];
if (number > 0) {
right--;
} else if (number < 0) {
left++;
} else {
o.add(Arrays.asList(nums[i], nums[left], nums[right]));
// 去重逻辑应该放在找到一个三元组之后对b c去重
// 如果 right左边的两个一样去重跳过去但依然要保证要比left大
while (right > left && nums[right] == nums[right - 1]){
right--;
}
while (right > left && nums[left] == nums[left + 1]) {
left++;
}
right--;
left++;
}
}
}
return o;
}
}
}

View File

@ -1,127 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Assert;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 18. 四数之和
* 给你一个由 n 个整数组成的数组 nums 和一个目标值 target 请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] 若两个四元组元素一一对应则认为两个四元组重复
* 0 <= a, b, c, d < n
* abc d 互不相同
* nums[a] + nums[b] + nums[c] + nums[d] == target
* 你可以按 任意顺序 返回答案
*
*
*
* 示例 1
*
* 输入nums = [1,0,-1,0,-2,2], target = 0
* 输出[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
* 示例 2
*
* 输入nums = [2,2,2,2,2], target = 8
* 输出[[2,2,2,2]]
*
*
* 提示
*
* 1 <= nums.length <= 200
* -109 <= nums[i] <= 109
* -109 <= target <= 109
*
// 参考LeetCode15题
*
*/
public class LeetCode18 {
@Test
public void test() {
// System.out.println(new Solution().fourSum(new int[]{1, 0, -1, 0, -2, 2}, 0));
System.out.println(1000000000+1000000000+1000000000+1000000000); // -294967296
int[] nums = {1000000000,1000000000,1000000000,1000000000};
int target = -294967296;
List<List<Integer>> expected = new ArrayList<>();
expected.add(Arrays.asList(2, 5, 6, 7));
expected.add(Arrays.asList(3, 4, 6, 7));
expected.add(Arrays.asList(3, 5, 6, 6));
System.out.println(new Solution().fourSum(nums, target));
}
/**
* TODO 没完全做出来
* 和LeetCode 15题类似但需要考虑 2 2 2 2 2 target=8 这样去重的情况
*/
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
Arrays.sort(nums);
List<List<Integer>> lists = new ArrayList<>();
// 第一个数>0并且>目标值递增的数组一定为空
/**
* int[] nums = {1000000000,1000000000,1000000000,1000000000};
* int target = -294967296;
* 不加这段代码这个用例会报错
* System.out.println(1000000000+1000000000+1000000000+1000000000); // -294967296
* 因为 -109 <= nums[i] <= 109
* -109 <= target <= 109
*/
if (nums[0] > 0 && nums[0] > target) {
return lists;
}
for (int i = 0; i < nums.length - 3; i++) {
// TODO 保证能够进入一次循环 i>0
if (i > 0 && nums[i] == nums[i - 1]) {
// 去重
continue;
}
for (int j = i + 1; j < nums.length - 2; j++) {
if (j > i + 1 && nums[j] == nums[j - 1]) {
// 这里需要考虑这样一种情况 [-2, -1, 0, 0, 1, 2] 如果用nums[j] == num[j + 1] 判断 -2 0 0 2 这种会被忽略
// 去重可以考虑向前或者向后去重注意<p>去重是要让指针和已经指过的对比</p>
continue;
}
int left = j + 1;
int right = nums.length - 1;
while (left < right) {
int sum = nums[right] + nums[left] + nums[i] + nums[j];
if (sum > target) {
right--;
} else if (sum < target) {
left++;
} else {
lists.add(Arrays.asList(nums[right], nums[left], nums[i], nums[j]));
while (left != right && nums[left] == nums[left + 1]) {
left++;
}
while (left != right && nums[right] == nums[right - 1]) {
right--;
}
right--;
left++;
}
}
}
}
return lists;
}
}
}

View File

@ -1,116 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.HashSet;
import java.util.Set;
/**
* 202. 快乐数
* 编写一个算法来判断一个数 n 是不是快乐数
*
* 快乐数 定义为
*
* 对于一个正整数每一次将该数替换为它每个位置上的数字的平方和
* 然后重复这个过程直到这个数变为 1也可能是 无限循环 但始终变不到 1
* 如果这个过程 结果为 1那么这个数就是快乐数
* 如果 n 快乐数 就返回 true 不是则返回 false
*
* 示例 1
*
* 输入n = 19
* 输出true
* 解释
* 12 + 92 = 82
* 82 + 22 = 68
* 62 + 82 = 100
* 12 + 02 + 02 = 1
* 示例 2
*
* 输入n = 2
* 输出false
*
*
* 提示
*
* 1 <= n <= 231 - 1
*/
public class LeetCode202 {
@Test
public void test() {
System.out.println(new Solution1().isHappy(2));
}
class Solution {
Set<Integer> set = new HashSet<>();
/**
* 计算的结果是否会重复出现如果出现就证明会进入循环
* @param n
* @return
*/
public boolean isHappy(int n) {
char[] chars = String.valueOf(n).toCharArray();
int ans = 0;
// StringBuilder stringBuilder = new StringBuilder("$");
for (char aChar : chars) {
aChar -= 48;
ans += aChar * aChar;
// stringBuilder.append("+" + (int)aChar + "^2");
}
// stringBuilder.append("=" + ans + "$");
// System.out.println(stringBuilder.toString());
if (ans == 1) {
return true;
} else if (set.contains(ans)) {
return false;
} else {
set.add(ans);
return isHappy(ans);
}
}
}
class Solution1 {
/**
* 计算的结果是否会重复出现如果出现就证明会进入循环
* @param n
* @return
*/
public boolean isHappy(int n) {
Set<Integer> set = new HashSet<>();
while (n != 1) {
n = getNextNumber(n);
System.out.println(n);
if (set.contains(n)) {
return false;
} else {
set.add(n);
}
}
return true;
}
public int getNextNumber(int n) {
int res = 0;
// 获取每个位
while (n > 0) {
int i = n % 10;
res += i * i;
n /= 10;
}
return res;
}
}
}

View File

@ -1,68 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.HashMap;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/21 13:32
* @注释
*/
public class LeetCode205 {
@Test
public void test() {
String s = "badc";
String t = "baba";
System.out.println(new Solution().isIsomorphic(s, t));
}
class Solution {
public boolean isIsomorphic(String s, String t) {
return is(s, t) && is(t, s);
}
public boolean is(String s, String t) {
HashMap<Character, Character> map = new HashMap<>();
for (int i = 0; i < s.length(); i++) {
char key = s.charAt(i);
if (!map.containsKey(key)) {
map.put(key, t.charAt(i));
} else if (map.get(key) != t.charAt(i)) {
return false;
}
}
return true;
}
}
class Solution1 {
/**
* 每个字符第一次出现的位置都一样就能保证同构成
* abc c和d第一次出现的 位置为1和2不一样会false
* cdd
*
* indexOf时间复杂度oN
* @param s
* @param t
* @return
*/
public boolean isIsomorphic(String s, String t) {
if (s.length() != t.length()) {
return false;
}
for (int i = 0; i < s.length(); i++) {
char s1 = s.charAt(i);
char t1 = t.charAt(i);
if (s.indexOf(s1) != t.indexOf(t1)) {
return false;
}
}
return true;
}
}
}

View File

@ -1,101 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* 242. 有效的字母异位词
*
* 给定两个字符串 s t 编写一个函数来判断 t 是否是 s 的字母异位词
*
* 注意 s t 中每个字符出现的次数都相同则称 s t 互为字母异位词
*
* 示例 1:
*
* 输入: s = "anagram", t = "nagaram"
* 输出: true
* 示例 2:
*
* 输入: s = "rat", t = "car"
* 输出: false
*
*
* 提示:
*
* 1 <= s.length, t.length <= 5 * 104
* s t 仅包含小写字母
*
*
* 进阶: 如果输入字符串包含 unicode 字符怎么办你能否调整你的解法来应对这种情况
*/
public class LeetCode242 {
@Test
public void test() {
Solution1 solution1 = new Solution1();
System.out.println(solution1.isAnagram("abcde", "ecbad"));
}
class Solution {
public boolean isAnagram(String s, String t) {
Map<Byte, Integer> S = getMap(s);
Map<Byte, Integer> T = getMap(t);
for (Byte aByte : S.keySet()) {
if (!S.get(aByte).equals(T.get(aByte))) {
return false;
}
}
for (Byte aByte : T.keySet()) {
if (!T.get(aByte).equals(S.get(aByte))) {
return false;
}
}
return true;
}
public Map<Byte, Integer> getMap(String s) {
HashMap<Byte, Integer> mapS = new HashMap<>();
for (byte aByte : s.getBytes()) {
if (mapS.containsKey(aByte)) {
mapS.put(aByte, mapS.get(aByte) + 1);
} else {
mapS.put(aByte, 1);
}
}
return mapS;
}
}
// s t 仅包含小写字母
// 小写字母的Unicode范围从aU+0061到zU+007A以下是这些字符的具体Unicode码
class Solution1 {
public boolean isAnagram(String s, String t) {
if (s.length() != t.length()) {
return false;
}
int[] S = new int[26];
for (byte aByte : s.getBytes()) {
S[aByte-97]++;
}
for (byte aByte : t.getBytes()) {
S[aByte-97]--;
}
for (int i = 0; i < S.length; i++) {
if (S[i] != 0) {
return false;
}
}
return true;
}
}
}

View File

@ -1,49 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/22 13:09
* @注释
*/
public class LeetCode290 {
@Test
public void test() {
String pattern = "abbc";
String s = "dog cat cat dog";
System.out.println(new Solution().wordPattern(pattern, s));
}
class Solution {
public boolean wordPattern(String pattern, String s) {
Map<Character, String> map = new HashMap<>();
Map<String, Character> map2 = new HashMap<>();
s = s.trim();
String[] split = s.split(" ");
if (pattern.length() != split.length) {
return false;
}
int len = pattern.length();
for (int i = 0; i < len; i++) {
char key1 = pattern.charAt(i);
String key2 = split[i];
if (!map.containsKey(key1)) {
map.put(key1, key2);
}
if (!map2.containsKey(key2)) {
map2.put(key2, key1);
}
if (!map.get(key1).equals(key2) || map2.get(key2) != key1) {
return false;
}
}
return true;
}
}
}

View File

@ -1,89 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.*;
import java.util.function.ToIntFunction;
/**
* 349. 两个数组的交集
* 给定两个数组 nums1 nums2 返回 它们的交集 输出结果中的每个元素一定是 唯一 我们可以 不考虑输出结果的顺序
*
*
* 示例 1
*
* 输入nums1 = [1,2,2,1], nums2 = [2,2]
* 输出[2]
* 示例 2
*
* 输入nums1 = [4,9,5], nums2 = [9,4,9,8,4]
* 输出[9,4]
* 解释[4,9] 也是可通过的
*
*
* 提示
*
* 1 <= nums1.length, nums2.length <= 1000
* 0 <= nums1[i], nums2[i] <= 1000
*/
public class LeetCode349 {
@Test
public void test() {
int[] nums1 = {9,4,9,8,4};
int[] nums2 = {4,9,5};
int[] res = new Solution1().intersection(nums1, nums2);
System.out.println(Arrays.toString(res));
}
class Solution {
public int[] intersection(int[] nums1, int[] nums2) {
HashSet<Integer> target = new HashSet<>();
HashSet<Integer> res = new HashSet<>();
for (int i : nums1) {
target.add(i);
}
for (int i : nums2) {
if (target.contains(i)) {
res.add(i);
}
}
return res.stream().mapToInt(new ToIntFunction<Integer>() {
@Override
public int applyAsInt(Integer value) {
return value;
}
}).toArray();
}
}
class Solution1 {
public int[] intersection(int[] nums1, int[] nums2) {
int[] A = new int[1001];
int[] B = new int[1001];
for (int i : nums1) {
A[i]++;
}
for (int i : nums2) {
B[i]++;
}
ArrayList<Integer> res = new ArrayList<>();
for (int i = 0; i < A.length; i++) {
if (A[i] != 0 && B[i] != 0) {
res.add(i);
}
}
return res.stream().mapToInt(i -> i).toArray();
}
}
}

View File

@ -1,140 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
/**
* 给你两个整数数组 nums1 nums2 请你以数组形式返回两数组的交集返回结果中每个元素出现的次数应与元素在两个数组中都出现的次数一致如果出现次数不一致则考虑取较小值可以不考虑输出结果的顺序*
* 示例 1
*
* 输入nums1 = [1,2,2,1], nums2 = [2,2]
* 输出[2,2]
* 示例 2:
* 输入nums1 = [4,9,5], nums2 = [9,4,9,8,4]
* 输出[4,9]
*
* 提示
*
* 1 <= nums1.length, nums2.length <= 1000
* 0 <= nums1[i], nums2[i] <= 1000
*
*
* 进阶
*
* 如果给定的数组已经排好序呢你将如何优化你的算法
* 如果 nums1 的大小比 nums2 哪种方法更优
* 如果 nums2 的元素存储在磁盘上内存是有限的并且你不能一次加载所有的元素到内存中你该怎么办
*/
public class LeetCode350 {
@Test
public void test() {
int[] nums2 = {4,9,9,5};
int[] nums1 = {9,4,9,8,4};
int[] res = new Solution2().intersect(nums1, nums2);
System.out.println(Arrays.toString(res));
}
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
int[] A = new int[1001];
int[] B = new int[1001];
for (int i : nums1) {
A[i]++;
}
for (int i : nums2) {
B[i]++;
}
int[] ans = new int[1001];
for (int i = 0; i < A.length; i++) {
ans[i] = Math.min(A[i], B[i]);
}
ArrayList<Integer> objects = new ArrayList<>();
for (int i = 0; i < ans.length; i++) {
for (int j = 0; j < ans[i]; j++) {
objects.add(i);
}
}
return objects.stream().mapToInt(i -> i).toArray();
}
}
class Solution1 {
/**
* 计算两个数组的交集
* @param nums1 第一个数组
* @param nums2 第二个数组
* @return 一个包含交集元素的数组
*/
public int[] intersect(int[] nums1, int[] nums2) {
// 创建一个长度为1001的数组A并初始化为0
int[] A = new int[1001];
// 遍历第一个数组将数组中的元素作为索引将对应索引的值加1
for (int i : nums1) {
A[i]++;
}
// 创建一个长度为第一个数组和第二个数组中较小长度的数组res用于存储交集元素
int[] res = new int[Math.min(nums1.length, nums2.length)];
// 初始化索引为0
int index = 0;
// 遍历第二个数组判断对应索引的值是否为0
// 如果不为0说明该元素在第一个数组中出现过将该元素加入res数组中并将对应索引的值减1
// 同时将索引加1
for (int i : nums2) {
if (A[i] != 0) {
res[index++] = i;
A[i]--;
}
}
// 截取res数组中实际的长度并返回结果
return Arrays.copyOfRange(res, 0, index);
}
}
class Solution2 {
/**
* 如果两个数组是有序的则可以使用双指针的方法得到两个数组的交集
* @param nums1 第一个数组
* @param nums2 第二个数组
* @return 一个包含交集元素的数组
*/
public int[] intersect(int[] nums1, int[] nums2) {
if (nums1.length < nums2.length) {
return intersect(nums2, nums1);
}
// 排序
Arrays.sort(nums1);
Arrays.sort(nums2);
int[] res = new int[nums2.length];
int index = 0 ;
int indexA = 0;
int indexB = 0;
// 使用两个指针不断向前移动如果哪个指针所指的数小了就让他向前移动
while (index < res.length && indexB < nums2.length && indexA < nums1.length) {
if (nums1[indexA] == nums2[indexB]) {
res[index++] = nums1[indexA++];
indexB++;
} else if (nums1[indexA] < nums2[indexB]) {
indexA++;
} else if (nums1[indexA] > nums2[indexB]) {
indexB++;
}
}
return Arrays.copyOfRange(res, 0, index);
}
}
}

View File

@ -1,76 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/16 19:18
* @注释
*/
public class LeetCode380 {
@Test
public void test()
{
// ["RandomizedSet","remove","remove","insert","getRandom","remove","insert"]
// [[],[0],[0],[0],[],[0],[0]]
RandomizedSet randomizedSet = new RandomizedSet();
randomizedSet.remove(0);
randomizedSet.remove(0);
randomizedSet.insert(0);
randomizedSet.getRandom();
randomizedSet.remove(0);
randomizedSet.insert(0);
}
class RandomizedSet {
List<Integer> list;
Map<Integer, Integer> map;
Random random;
public RandomizedSet() {
list = new ArrayList<>();
map = new HashMap<>();
random = new Random();
}
public boolean insert(int val) {
// 存在返回false
if (map.containsKey(val)) {
return false;
}
int size = list.size();
list.add(size, val);
map.put(val, size);
return true;
}
public boolean remove(int val) {
if (!map.containsKey(val)) {
return false;
}
Integer idx = map.get(val); // 删除的元素index
Integer lastElement = list.get(list.size() - 1); // 最后一个元素的值
// 更新最后一个元素覆盖原来的list
list.set(idx, lastElement);
map.put(lastElement, idx);
// 删除元素放最后
list.remove(list.size() - 1);
map.remove(val);
return true;
}
public int getRandom() {
return list.get(random.nextInt(list.size()));
}
}
}

View File

@ -1,94 +0,0 @@
package cn.whaifree.leetCode.Hash;
import cn.hutool.core.map.MapUtil;
import cn.whaifree.leetCode.utils.MapUtils;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
/**
* 383. 赎金信
* 给你两个字符串ransomNote magazine 判断 ransomNote 能不能由 magazine 里面的字符构成
*
* 如果可以返回 true 否则返回 false
*
* magazine 中的每个字符只能在 ransomNote 中使用一次
*
* 示例 1
*
* 输入ransomNote = "a", magazine = "b"
* 输出false
* 示例 2
*
* 输入ransomNote = "aa", magazine = "ab"
* 输出false
* 示例 3
*
* 输入ransomNote = "aa", magazine = "aab"
* 输出true
*
*
* 提示
*
* 1 <= ransomNote.length, magazine.length <= 105
* ransomNote magazine 由小写英文字母组成
*/
public class LeetCode383 {
@Test
public void test() {
boolean b = new Solution1().canConstruct("aabb", "aabbc");
System.out.println(b);
}
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
Map<Character, Integer> mapR = new HashMap<>();
for (char c : ransomNote.toCharArray()) {
mapR.put(c, mapR.getOrDefault(c, 0) + 1);
}
Map<Character, Integer> mapM = new HashMap<>();
for (char c : magazine.toCharArray()) {
mapM.put(c, mapM.getOrDefault(c, 0) + 1);
}
MapUtils.printMap(mapR);
MapUtils.printMap(mapM);
for (Character c : mapR.keySet()) {
if (mapM.getOrDefault(c, 0) < mapR.getOrDefault(c, 0)) {
return false;
}
}
return true;
}
}
class Solution1 {
// ransomNote magazine 由小写英文字母组成
public boolean canConstruct(String ransomNote, String magazine) {
int[] map = new int[26];
// 大的先存入Map
// 相比转换为Char更快
for (int i = 0; i < magazine.length(); i++) map[magazine.charAt(i) - 'a'] += 1;
// 减去小的如果小于0如果不够减就返回false
for (int i = 0; i < ransomNote.length(); i++) {
int index = ransomNote.charAt(i) - 97;
map[index] -= 1;
if (map[index] < 0) {
return false;
}
}
return true;
}
}
}

View File

@ -1,105 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.HashMap;
/**
* 给你四个整数数组 nums1nums2nums3 nums4 数组长度都是 n 请你计算有多少个元组 (i, j, k, l) 能满足
*
* 0 <= i, j, k, l < n
* nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
*
*
* 示例 1
*
* 输入nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
* 输出2
* 解释
* 两个元组如下
* 1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
* 2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0
* 示例 2
*
* 输入nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
* 输出1
*
*
* 提示
*
* n == nums1.length
* n == nums2.length
* n == nums3.length
* n == nums4.length
* 1 <= n <= 200
* -228 <= nums1[i], nums2[i], nums3[i], nums4[i] <= 228
*/
public class LeetCode454 {
@Test
public void test() {
//[1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
System.out.println(new Solution().fourSumCount(
new int[]{1, 2, 3},
new int[]{-1, -2, -3},
new int[]{-1, 2, -3},
new int[]{0, 2, 3}
));
}
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums1.length; i++) {
for (int j = 0; j < nums2.length; j++) {
if (map.get(nums1[i] + nums2[j]) == null) {
map.put(nums1[i] + nums2[j], 1);
} else {
map.put(nums1[i] + nums2[j], map.get(nums1[i] + nums2[j])+1);
}
}
}
map.forEach(
(k, v) -> System.out.println(k + "=" + v)
);
int res = 0;
for (int i = 0; i < nums3.length; i++) {
for (int j = 0; j < nums4.length; j++) {
int integer = nums3[i] + nums4[j];
if (map.containsKey(-integer)) {
// 表示前两个数 和后两个数相加为0 nums1[i] + nums2[j] = -nums3[i] + nums4[j]
res += map.get(-integer);
}
}
}
return res;
}
}
class Solution1 {
// 时间复杂度O(N2)
// 空间复杂度O(N) 在最坏的情况下A[i]+B[j] 的值均不相同因此也就需要 O(n^2) 的空间
//1
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
HashMap<Integer, Integer> map = new HashMap<>();
for (int i : nums1) {
for (int j : nums2) {
int sum = i + j;
map.put(sum, map.getOrDefault(sum, 0) + 1);
// getOrDefault 如果没有则用默认值就不用使用Contain了
}
}
int res = 0;
for (int k : nums3) {
for (int i : nums4) {
int integer = k + i;
res += map.getOrDefault(- integer, 0);
}
}
return res;
}
}
}

View File

@ -1,128 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
import java.util.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/9/22 13:22
* @注释
*/
public class LeetCode49 {
@Test
public void test() {
String[] strs = {"eat", "tea", "tan", "ate", "nat", "bat"};
System.out.println(new Solution().groupAnagrams(strs));
}
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>();
for (String str : strs) {
char[] charArray = str.toCharArray(); // 排序后 key 一样
Arrays.sort(charArray);
String key = new String(charArray);
if (!map.containsKey(key)) {
map.put(key, new ArrayList<>());
}
map.get(key).add(str);
}
return new ArrayList<>(map.values());
}
}
class Solution1 {
/**
* 统计每个字母出现的个数并按照a2b1c4这种格式变成String作为key
*
* 统计次数ON*M
* @param strs
* @return
*/
public List<List<String>> groupAnagrams(String[] strs) {
List<List<String>> res = new ArrayList<>();
Map<String, List<String>> map = new HashMap<>();
for (String str : strs) {
int[] count = new int[26];
for (int i = 0; i < str.length(); i++) {
int index = str.charAt(i) - 'a';
count[index]++;
}
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < count.length; i++) {
if (count[i] != 0) {
// a12b19这种形式
stringBuilder.append((char) ('a' + i));
stringBuilder.append(count[i]);
}
}
String key = stringBuilder.toString();
if (!map.containsKey(key)) {
map.put(key, new ArrayList<>());
}
map.get(key).add(str);
}
return new ArrayList<>(map.values());
}
}
//
// class Solution {
//
// static List<Integer> anagrams = null;
// static List<List<String>> res = null;
// public List<List<String>> groupAnagrams(String[] strs) {
// int[][] nums = new int[strs.length][26];
// for (int i = 0; i < strs.length; i++) {
// String str = strs[i];
// for (int j = 0; j < str.length(); j++) {
// nums[i][str.charAt(j) - 'a']++;
// }
// }
//
// anagrams = new ArrayList<>();
// res = new ArrayList<>();
// backTracking(strs, nums, 0);
// return res;
// }
//
// public static void backTracking(String[] strs, int[][] map, int start) {
// if (start >= map.length - 1) {
// List<String> anagram = new ArrayList<>();
// for (Integer a : anagrams) {
// anagram.add(strs[a]);
// }
// res.add(new ArrayList<>(anagram));
// return;
// }
//
// if (!anagrams.isEmpty() && !match(map, anagrams.get(anagrams.size() - 1), start)) {
// return;
// }
//
// for (int i = start; i < map.length; i++) {
// anagrams.add(i);
// backTracking(strs, map, i + 1);
// anagrams.remove(anagrams.size() - 1);
// }
//
// }
//
// public static boolean match(int[][] map, int a, int b) {
// int[] A = map[a];
// int[] B = map[b];
// for (int i = 0; i < 26; i++) {
// if (A[i] != B[i]) return false;
// }
// return true;
// }
// }
}

View File

@ -1,67 +0,0 @@
package cn.whaifree.leetCode.Hash;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/14 13:15
* @注释
*/
public class LeetCode705 {
@Test
public void test()
{
MyHashSet myHashSet = new MyHashSet();
myHashSet.add(1); // set = [1]
myHashSet.add(2); // set = [1, 2]
System.out.println(myHashSet.contains(1)); // 返回 True
System.out.println(myHashSet.contains(3)); // 返回 False 未找到
System.out.println(myHashSet.contains(2));
myHashSet.remove(2);
System.out.println(myHashSet.contains(2)); // 返回 False 已移除
}
/**
* int 表示4字节 32位 每一位代表一个位置
* 1000000/32 40000表示桶
*/
class MyHashSet {
int[] bucket = null;
public MyHashSet() {
bucket = new int[40000];
}
public void add(int key) {
int bkLoc = key / 32;
int ex = key % 32;
int num = bucket[bkLoc];
// 如num=4 (100) 1<<1= 010 进行|操作后变成 110
bucket[bkLoc] = num | (1 << ex);
}
public void remove(int key) {
int bkLoc = key / 32;
int ex = key % 32;
int num = bucket[bkLoc];
// 如num=7 (111) 1<<1= 010 进行~后变成101 & 操作后变成 101
bucket[bkLoc] = num & ~(1 << ex);
}
public boolean contains(int key) {
int bkLoc = key / 32;
int ex = key % 32; // 偏移
int num = bucket[bkLoc]; // 数字
return ((num >> ex) & 1) == 1;
// 如num=7 (111) 1<<1= 010 进行~后变成101 & 操作后变成 101
// int i = num & (1 << ex);
// return 1 << ex == i;
}
}
}

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,165 @@
package cn.whaifree.LCR;
import org.junit.Test;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/24 15:09
* @注释
*/
public class LCR031 {
class LRUCache {
int maxCap = 0;
LinkedHashMap<Integer, Integer> map = new LinkedHashMap<>();
public LRUCache(int capacity) {
maxCap = capacity;
}
public int get(int key) {
if (map.containsKey(key)) {
Integer i = map.get(key);
map.remove(key);
map.put(key, i);
return i;
}
return -1;
}
public void put(int key, int value) {
if (map.containsKey(key)) {
map.remove(key);
map.get(key);
map.put(key, value);
return;
}
map.put(key, value);
if (map.size() > maxCap) {
for (Integer i : map.keySet()) {
map.remove(i); // 只删除一个
break;
}
}
}
}
@Test
public void test() {
// ["LRUCache","put","put","get","put","put","get"]
// [[2],[2,1],[2,2],[2],[1,1],[4,1],[2]]
LRUCache cache = new LRUCache(2);
cache.put(2, 1);
cache.put(2, 2);
System.out.println(cache.get(2));
cache.put(1, 1);
cache.put(4, 1);
System.out.println(cache.get(2));
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
@Test
public void test2() {
P2.LRUCache cache = new P2.LRUCache(2);
cache.put(2, 1);
cache.put(2, 2);
System.out.println(cache.get(2));
cache.put(1, 1);
cache.put(4, 1);
System.out.println(cache.get(2));
}
}
class P2{
static class Entry{
Entry before;
Entry next;
int value;
int key;
public Entry(Entry before, Entry next, int value, int key) {
this.before = before;
this.next = next;
this.value = value;
this.key = key;
}
}
static class LRUCache {
Map<Integer, Entry> map = new HashMap<>();
Entry head;
Entry tail;
int maxSize;
public LRUCache(int capacity) {
maxSize = capacity;
head = new Entry(null, null, Integer.MIN_VALUE, Integer.MIN_VALUE);
tail = new Entry(null, null, Integer.MAX_VALUE, Integer.MAX_VALUE);
tail.before = head;
head.next = tail;
}
public void addToHead(Entry entry) {
Entry next = head.next;
head.next = entry;
entry.before = head;
entry.next = next;
next.before = entry;
}
public void removeIndex(Entry entry) {
entry.before.next = entry.next;
entry.next.before = entry.before;
}
public int get(int key) {
if (map.containsKey(key)) {
Entry entry = map.get(key);
removeIndex(entry);
addToHead(entry);
return entry.value;
}
return -1;
}
public void put(int key, int value) {
if (map.containsKey(key)) {
Entry entry = map.get(key);
entry.value = value;
removeIndex(entry);
addToHead(entry);
return;
}
Entry newEntry = new Entry(null, null, value, key);
addToHead(newEntry);
map.put(key, newEntry);
if (map.size() > maxSize) {
Entry before = tail.before;
map.remove(before.key);
removeIndex(tail.before);
}
}
}
}

View File

@ -0,0 +1,198 @@
package cn.whaifree.LCR;
import org.junit.Test;
import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/25 15:03
* @注释
*/
public class LCR106 {
@Test
public void test() {
// [[1,2,3],[0,2],[0,1,3],[0,2]]
int[][] graph = {{1, 2, 3}, {0, 2}, {0, 1, 3}, {0, 2}};
// [[],[2,4,6],[1,4,8,9],[7,8],[1,2,8,9],[6,9],[1,5,7,8,9],[3,6,9],[2,3,4,6,9],[2,4,5,6,7,8]]
graph = new int[][]{{}, {2, 4, 6}, {1, 4, 8, 9}, {7, 8}, {1, 2, 8, 9}, {6, 9}, {1, 5, 7, 8, 9}, {3, 6, 9}, {2, 3, 4, 6, 9}, {2, 4, 5, 6, 7, 8}};
Solution solution = new Solution();
boolean bipartite = solution.isBipartite(graph);
System.out.println(bipartite);
}
class Solution {
private final static int UN_SIGN = 0;
private final static int RED_SIGN = 1;
private final static int BLACK_SIGN = 2;
int[] color = null;
boolean res = true;
/**
* 深度优先遍历dfs
* 如果是没有标记过的红标记为黑黑标记为红
* 如果是标记过的如果颜色一样直接返回false
*
* @param graph
* @return
*/
public boolean isBipartite(int[][] graph) {
int n = graph.length;
color = new int[n];
// 这个for确保每个连通的图都遍历一遍
// [[],[2,4,6],[1,4,8,9],[7,8],[1,2,8,9],[6,9],[1,5,7,8,9],[3,6,9],[2,3,4,6,9],[2,4,5,6,7,8]]
// 比如这个第一个0与任何都不连通就会直接返回true
for (int i = 0; i < n && res; i++) {
if (color[i] == UN_SIGN) {
color[i] = RED_SIGN;
dfs(graph, i, RED_SIGN);
}
}
return res;
}
/**
*
* @param graph
* @param now 现在是拿个节点I
* @param nowColor 此节点now的颜色
*/
public void dfs(int[][] graph, int now, int nowColor) {
int hopeNextColor;
if (nowColor == RED_SIGN) {
hopeNextColor = BLACK_SIGN;
}else {
hopeNextColor = RED_SIGN;
}
int[] targets = graph[now];
for (int target : targets) {
if (color[target] == UN_SIGN) {
color[target] = hopeNextColor;
dfs(graph, target, hopeNextColor);
if (!res) { // 一旦有false直接返回剪枝
return;
}
} else if (color[target] != hopeNextColor) {
// 本节点已经遍历过了并且与期望不一样直接false
res = false;
return;
}
}
}
}
class Solution1 {
private final static int UN_SIGN = 0;
private final static int RED_SIGN = 1;
private final static int BLACK_SIGN = 2;
int[] color = null;
boolean res = true;
/**
*
* @param graph
* @return
*/
public boolean isBipartite(int[][] graph) {
int n = graph.length;
color = new int[n];
Arrays.fill(color, UN_SIGN);
for (int i = 0; i < n; i++) {
if (color[i] == UN_SIGN) {
if (!WFS(graph, i, RED_SIGN)) {
return false;
}
}
}
return true;
}
public boolean WFS(int[][] graph, int now, int nowColor) {
Deque<Integer> queue = new LinkedList<>();
queue.add(now);
color[now] = RED_SIGN;
while (!queue.isEmpty()) {
Integer pop = queue.pop();
int HopeNext = 0;
if (color[pop] == RED_SIGN) {
HopeNext = BLACK_SIGN;
} else {
HopeNext = RED_SIGN;
}
int[] Targets = graph[pop];
for (int target : Targets) {
if (color[target] == UN_SIGN) {
color[target] = HopeNext;
queue.add(target);
}else if (color[target] != HopeNext) {
return false;
}
}
}
return true;
}
}
// class Solution {
// Set<Integer> set1;
// Set<Integer> set2;
// LinkedList<Integer> path;
// /**
// * 建立两个Set
// *
// * 递归深度遍历
// * - 如果Set中存在直接return
// * - 如果不存在加入Set
// *
// * @param graph
// * @return
// */
// public boolean isBipartite(int[][] graph) {
// set1 = new HashSet<>();
// set2 = new HashSet<>();
// path = new LinkedList<>();
// path.add(0);
// boolean dfs = dfs(graph, 0, true);
// return dfs;
// }
//
// public boolean dfs(int[][] graph,int now,boolean toSet1) {
// if (set1.contains(now) || set2.contains(now)) {
// return false;
// }
// if (toSet1) {
// set1.add(now);
// }else {
// set2.add(now);
// }
//
//
// int[] tos = graph[now];
// for (int i = 0; i < tos.length; i++) {
// int wantTo = tos[i];
// // 这个边的两头在同一个集合
// if (toSet1 && set1.contains(wantTo)) {
// continue;
// }
// if (!toSet1 && set2.contains(wantTo)) {
// continue;
// }
// path.add(wantTo);
// if (dfs(graph, wantTo, !toSet1)) {
// return true;
// }
//
// path.remove(path.size() - 1);
// }
//
// return false;
// }
// }
}

View File

@ -1,51 +0,0 @@
package cn.whaifree.leetCode.LeetCode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/3 17:35
* @注释
*/
public class LeetCode11 {
@Test
public void test() {
Solution solution = new Solution();
int[] height = {1,1};
int i = solution.maxArea(height);
System.out.println(i);
}
class Solution {
/**
* $S(i,j)=min(h[i],h[j])*(j-i)$
* 双指针
* 长板移动面积不变或 变小
* 短板移动 变大 或不变
* 不断移动短板
* @param height
* @return
*/
public int maxArea(int[] height) {
int storage = 0;
int left = 0;
int right = height.length - 1;
while (left < right) {
storage = Math.max(getArea(height, left, right), storage);
if (height[left] < height[right]) {
left++;
}else {
right--;
}
}
return storage;
}
public int getArea(int[] height, int start, int end) {
return Math.min(height[start], height[end]) * (end - start);
}
}
}

View File

@ -1,115 +0,0 @@
package cn.whaifree.leetCode.LeetCode;
import org.junit.Test;
import java.util.*;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/4 13:44
* @注释
*/
public class LeetCode22 {
@Test
public void test() {
List<String> res =new Solution1().generateParenthesis(3);
System.out.println(res);
}
class Solution {
List<String> res = new ArrayList<>();
StringBuilder path = new StringBuilder();
/**
*
* @param n
* @return
*/
public List<String> generateParenthesis(int n) {
backTracking(n, 0, 0);
return res;
}
/**
*
* @param n
* @param leftCount 左括号用了几个
* @param rightCount 右括号用了几个
*/
public void backTracking(int n, int leftCount , int rightCount) {
if (leftCount > n || rightCount > leftCount) {
return;
}
if (path.length() == n * 2) {
res.add(path.toString());
return;
}
path.append("(");
backTracking(n, leftCount + 1, rightCount);
path.deleteCharAt(path.length() - 1); // 回溯
path.append(")");
backTracking(n, leftCount, rightCount + 1);
path.deleteCharAt(path.length() - 1); // 回溯
}
}
class Solution1 {
List<String> res = new ArrayList<>();
StringBuilder path = new StringBuilder();
/**
*
* @param n
* @return
*/
public List<String> generateParenthesis(int n) {
backTracking(n, n, n);
return res;
}
/**
*
* @param n
* @param leftCount 左括号可用数
* @param rightCount 右括号可用数
*/
public void backTracking(int n, int leftCount , int rightCount) {
if (leftCount == 0 && rightCount == 0) {
res.add(path.toString());
return;
}
if (leftCount > rightCount) {
return;
}
if (leftCount > 0) {
path.append("(");
backTracking(n, leftCount - 1, rightCount);
path.deleteCharAt(path.length() - 1);
}
if (rightCount > 0) {
path.append(")");
backTracking(n, leftCount, rightCount - 1);
path.deleteCharAt(path.length() - 1);
}
}
}
}

View File

@ -1,155 +0,0 @@
package cn.whaifree.leetCode.LeetCode;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/6 11:27
* @注释
*/
public class LeetCode32 {
@Test
public void test() {
int i = new Solution3().longestValidParentheses("(()");
System.out.println(i);
}
class Solution {
/**
* 找出最长有效格式正确且连续括号子串的长度
*
* dp[i] 表示从0-i内最长有效括号子串的长度
*
* if char[i]='(' || retailLeft<0
* = dp[i-1]
* if char[i]=')'&&retailLeft>0
* = dp[i-1]+2
*
* @param s
* @return
*/
public int longestValidParentheses(String s) {
char[] chars = s.toCharArray();
int[] dp = new int[s.length() + 1];
int retailLeft = 0;
for (int i = 0; i < chars.length; i++) {
if (chars[i] == '(' ) {
retailLeft++;
dp[i] = dp[i - 1];
} else if (chars[i] == ')' && retailLeft > 0) {
}
}
return 0;
}
}
class Solution1 {
/**
* ()(()
*
* <a href="https://leetcode.cn/problems/longest-valid-parentheses/solutions/2719468/chao-jian-dan-fang-fa-zhi-hui-gua-hao-pi-nbby">...</a>
*
* 1.匹配成功 用栈匹配把所有匹配成功的flag设置为1
* 2.最长连续 统计flag中最长连续1的长度
*
* @param s
* @return
*/
public int longestValidParentheses(String s) {
int[] flag = new int[s.length()];
Deque<Integer> stack = new LinkedList<>();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
stack.push(i);
} else if (!stack.isEmpty()) {
Integer pop = stack.pop();
if (s.charAt(pop) == '(') {
flag[i] = 1;
flag[pop] = 1;
}
}
}
// 计算flag中最长连续出现1的次数
int len = 0;
int maxLen = Integer.MIN_VALUE;
for (int i = 0; i < flag.length; i++) {
if (flag[i] == 1) {
len += 1;
}else {
maxLen = Math.max(maxLen,len);
len = 0;
}
}
return Math.max(maxLen, len); // (() 这个用例
}
}
class Solution3 {
/**
* 使用两个计数器
* - 当两个计数器相等 则检查最长匹配
* - 当右边比左边还多重置
*
* 需要 从前往后+从后往前
*
* @param s
* @return
*/
public int longestValidParentheses(String s) {
int left = 0, right = 0, maxlength = 0;
// 左右计数器
// - 一旦右边计数比左边大的时候重置
// - 左右计数器相等的时候匹配maxLength
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
left++;
} else if (s.charAt(i) == ')') {
right++;
}
if (left == right) {
maxlength = Math.max(maxlength, left + right);
} else if (right > left) {
// 右边比左边还多重置重新计算
right = 0;
left = 0;
}
}
// 重新从下一个字符开始计算但这样会漏掉一种情况就是遍历的时候左括号的数量始终大于右括号的数量 (() 这种时候最长有效括号是求不出来的
// 只要从左到右再来一次
left = 0;
right = 0;
for (int i = s.length() - 1; i > 0; i--) {
if (s.charAt(i) == '(') {
left++;
} else if (s.charAt(i) == ')') {
right++;
}
if (left == right) {
maxlength = Math.max(maxlength, left + right);
} else if (left > right) {
// 右边比左边还多重置重新计算
right = 0;
left = 0;
}
}
return maxlength;
}
}
}

View File

@ -1,95 +0,0 @@
package cn.whaifree.leetCode.LeetCode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/3/21 16:57
* @注释
*/
public class LeetCode4 {
@Test
public void test()
{
Solution2 solution = new Solution2();
int[] nums1 = {1,3};
int[] nums2 = {2};
double medianSortedArrays = solution.findMedianSortedArrays(nums1, nums2);
System.out.println(medianSortedArrays);
}
class Solution1 {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int length = nums1.length + nums2.length;
int middle = length / 2;
int index1 = 0;
int index2 = 0;
boolean flag = false;
while (index1 + index2 < middle - 1) {
if (nums1[index1] < nums2[index2]) {
flag = false;
index1++;
} else {
flag = true;
index2++;
}
}
if (length % 2 != 0) {
return flag ? nums2[index2] : nums1[index1];
}else {
return (double) (nums1[index1] + nums2[index2]) / 2;
}
}
}
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int[] nums = new int[nums1.length + nums2.length];
int indexA = 0;
int indexB = 0;
int index = 0;
while (indexA < nums1.length && indexB < nums2.length) {
if (nums1[indexA] <= nums2[indexB]) {
nums[index++] = nums1[indexA++];
}else {
nums[index++] = nums2[indexB++];
}
}
while (indexA < nums1.length) {
nums[index++] = nums1[indexA++];
}
while (indexB < nums2.length) {
nums[index++] = nums2[indexB++];
}
int length = nums.length;
return length % 2 == 1 ? (double) nums[length / 2] : (double) (nums[length/2 - 1] + nums[length/2]) / 2;
}
}
class Solution2 {
/**
* 二分查找
* @param nums1
* @param nums2
* @return
*/
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
return 1;
}
}
}

View File

@ -1,106 +0,0 @@
package cn.whaifree.leetCode.LeetCode;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/8 11:23
* @注释
*/
public class LeetCode42 {
@Test
public void test()
{
int[] height = new int[]{0,1,0,2,1,0,1,3,2,1,2,1};
int trap = new Solution2().trap(height);
System.out.println(trap);
}
class Solution {
/**
* 从左到右 获得每个位置的左边最高
* 从右到左 获得每个位置的右边最高
*
* 取交集
*
* @param height
* @return
*/
public int trap(int[] height) {
int[] leftHeight = new int[height.length];
int leftH = 0;
for (int i = 0; i < height.length; i++) {
leftH = Math.max(leftH, height[i]);
leftHeight[i] = leftH;
}
int[] rightHeight = new int[height.length];
int rightH = 0;
for (int i = height.length - 1; i >= 0; i--) {
rightH = Math.max(rightH, height[i]);
rightHeight[i] = rightH;
}
int res = 0;
for (int i = 0; i < height.length; i++) {
res += Math.min(rightHeight[i], leftHeight[i]) - height[i];
}
return res;
}
}
class Solution2{
/**
* 关键在于
* - i值 < 栈顶值 入栈
* 3 2 1 递减下一个遇到5时先计算left=2 mid=1 right=5 的容积,再while left=3 mid=1 right=5的容积
* - i值 > 栈顶值 需要计算i为槽时的容积
* - i值 == 栈顶值 更新
* @param height
* @return
*/
public int trap(int[] height) {
// 单调栈 找到右边第一个高于他的墙
// 保证栈内元素从上到下为递增的这样就能获取到槽的两边并且确保不会有一边为空的
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
int res = 0;
for (int i = 1; i < height.length; i++) {
if (height[i] > height[stack.peek()]) {
// 遇到凹陷
//pop up all lower value
int heightAtIdx = height[i]; // 右边墙的高度
// 不断判断左边的墙因为如果左边的墙存在必然大于上一个左墙 如height 3 2 1 5
while (!stack.isEmpty() && (heightAtIdx > height[stack.peek()])){
int mid = stack.pop(); // 中间槽的下标
if (!stack.isEmpty()){
int left = stack.peek(); // 左边墙的下标
int h = Math.min(height[left], height[i]) - height[mid];
int w = i - left - 1;
int hold = h * w;
if (hold > 0) res += hold;
}
}
stack.push(i);
} else if (height[i] == height[stack.peek()]) {
stack.pop();
stack.push(i);
}else {
stack.push(i);
}
}
return res;
}
}
}

View File

@ -1,113 +0,0 @@
package cn.whaifree.leetCode.LeetCode;
import org.junit.Test;
import java.util.Arrays;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.concurrent.ConcurrentHashMap;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/9 10:50
* @注释
*/
public class LeetCode496 {
@Test
public void test() {
ConcurrentHashMap<Object, Object> c = new ConcurrentHashMap<>();
c.put("1", "1");
int[] nums1 = {4, 1, 2};
int[] nums2 = {1, 3, 4, 2};
int[] res = new Solution1().nextGreaterElement(nums1, nums2);
for (int i : res) {
System.out.println(i);
}
}
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
// 栈从上到下肯定是递增的
// nums2 判断是否比stack1中的栈顶大如果不是就进入栈2否则
int[] res = new int[nums1.length];
Arrays.fill(res, -1);
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums1.length; i++) {
map.put(nums1[i], i);
}
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
for (int i = 1; i < nums2.length; i++) {
if (nums2[i] < nums2[stack.peek()]) {
// 小于 入栈
stack.push(i);
} else if (nums2[i] > nums2[stack.peek()]) {
// 大于则至少stack.peek找到了结果
// 判断nums1中是否存在
// 即栈顶元素找到了 nums2中第一个大于的元素
while (!stack.isEmpty() && nums2[i] > nums2[stack.peek()]) {
if (map.containsKey(nums2[stack.peek()])) {
Integer loc = map.get(nums2[stack.peek()]);
res[loc] = nums2[i];
}
stack.pop();
}
stack.push(i);
}else {
// 小于 入栈
stack.push(i);
}
}
return res;
}
}
class Solution1 {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
// nums1 中数字 x 下一个更大元素 是指 x nums2 中对应位置 右侧 第一个 x 大的元素
HashMap<Integer, Integer> map = new HashMap<>();
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
for (int i = 1; i < nums2.length; i++) {
if (nums2[stack.peek()] < nums2[i]) {
while (!stack.isEmpty() && nums2[stack.peek()] < nums2[i]) {
int key = nums2[stack.pop()];
int value = nums2[i];
map.put(key, value);
}
stack.push(i);
}else if (nums2[stack.peek()] > nums2[i]) {
stack.push(i);
}else {
stack.push(i);
}
}
int[] res = new int[nums1.length];
for (int i = 0; i < nums1.length; i++) {
if (map.containsKey(nums1[i])) {
res[i] = map.get(nums1[i]);
}else {
res[i] = -1;
}
}
return res;
}
}
}

View File

@ -1,77 +0,0 @@
package cn.whaifree.leetCode.LeetCode;
import org.junit.Test;
import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/11 13:07
* @注释
*/
public class LeetCode503 {
@Test
public void test()
{
int[] nums = {1,2,3,4,3};
Solution solution = new Solution();
int[] res = solution.nextGreaterElements(nums);
for (int i = 0; i < res.length; i++) {
System.out.println(res[i]);
}
}
class Solution {
/**
* 循环
* 1. 两倍拼接
* 2. 模拟走两遍
* @param nums
* @return
*/
public int[] nextGreaterElements(int[] nums) {
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
int[] res = new int[nums.length];
Arrays.fill(res, -1);
for (int i = 1; i < nums.length * 2; i++) {
if (nums[stack.peek()] < nums[i % nums.length]) {
// 找到了栈顶比他大的值
while (!stack.isEmpty() && nums[stack.peek()] < nums[i % nums.length]) {
res[stack.peek()] = nums[i % nums.length];
stack.pop();
}
stack.push(i % nums.length);
} else if (nums[stack.peek()] > nums[i % nums.length]) {
stack.push(i % nums.length);
} else {
stack.push(i % nums.length);
}
}
return res;
}
public int[] nextGreaterElements1(int[] nums) {
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
int[] res = new int[nums.length];
Arrays.fill(res, -1);
for (int i = 1; i < nums.length * 2; i++) {
// 找到了栈顶比他大的值
int h = i % nums.length;
while (!stack.isEmpty() && nums[stack.peek()] < nums[h]) {
res[stack.peek()] = nums[h];
stack.pop();
}
stack.push(h);
}
return res;
}
}
}

View File

@ -1,53 +0,0 @@
package cn.whaifree.leetCode.LeetCode;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/16 11:45
* @注释
*/
public class LeetCode72 {
@Test
public void test()
{
String word1 = "horse";
String word2 = "ros";
int res = new Solution().minDistance(word1, word2);
System.out.println(res);
}
class Solution {
public int minDistance(String word1, String word2) {
// dp[i][j] 表示将word1的第i个位置字符 替换为 word2的第j个字符所需的最小操作数
// - 删除 dp[i-1][j]
// - 增加 dp[i][j-1]
// - 替换 dp[i-1][j-1]
// dp[i][j] = min +1
int wL1 = word1.length();
int wL2 = word2.length();
int[][] dp = new int[wL1 + 1][wL2 + 1];
for (int i = 0; i <= wL1; i++) {
dp[i][0] = i;
}
for (int i = 0; i <= wL2; i++) {
dp[0][i] = i;
}
for (int i = 1; i <= wL1; i++) {
for (int j = 1; j <= wL2; j++) {
if (word1.charAt(i - 1) == word2.charAt(j - 1)){
// 如果对应位置两个字母相等不用做任何操作直接使用dp[i - 1][j - 1]
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1], dp[i][j - 1]), dp[i - 1][j]) + 1;
}
}
}
return dp[wL1][wL2];
}
}
}

View File

@ -1,111 +0,0 @@
package cn.whaifree.leetCode.LeetCode;
import org.junit.Test;
import java.util.Deque;
import java.util.LinkedList;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/11 13:42
* @注释
*/
public class LeetCode84 {
@Test
public void test()
{
int[] heights = {0};
int i = new Solution1().largestRectangleArea(heights);
System.out.println(i);
}
class Solution {
public int largestRectangleArea(int[] heights) {
int[] left = new int[heights.length];
int[] right = new int[heights.length];
// 记录左右第一个小于i的坐标这样就能计算以heights[i]为高的面积
left[0] = -1;
for (int i = 1; i < heights.length; i++) {
int index = i - 1;
while (index >= 0 && heights[index] >= heights[i]) {
// index--; 这样会超时
index = left[index];
}
left[i] = index;
}
right[right.length - 1] = right.length;
for (int i = right.length - 2; i >= 0; i--) {
int index = i + 1;
while (index < right.length && heights[index] >= heights[i]) {
index = right[index];
}
right[i] = index;
}
// 获得左边右边比他小的第一个数就能计算最大面积
int max = Integer.MIN_VALUE;
for (int i = 0; i < left.length; i++) {
int sum = (right[i] - left[i] - 1) * heights[i];
max = Math.max(max, sum);
}
return max;
}
}
class Solution1 {
/**
* 找每个柱子左右两边第一个小于该柱子的柱子
*
* 找到凸的地方
*
* @param heights
* @return
*/
public int largestRectangleArea(int[] heights) {
// 数组扩容在头和尾各加入一个元素因为要计算以i为高的最大面积
int [] newHeights = new int[heights.length + 2];
newHeights[0] = 0;
newHeights[newHeights.length - 1] = 0;
for (int index = 0; index < heights.length; index++){
newHeights[index + 1] = heights[index];
}
heights = newHeights;
// 扩容是为了在计算最大矩形面积时能处理以下两种特殊情况
// 包含第一个柱子的最大矩形
// 包含最后一个柱子的最大矩形
Deque<Integer> stack = new LinkedList<>();
stack.push(0);
int res = 0;
for (int i = 1; i < heights.length; i++) {
if (heights[i] == heights[stack.peek()]) {
// 如果 栈顶 i
stack.push(i);
} else if (heights[i] < heights[stack.peek()]) {
// 4 栈顶[6 3...]
while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) {
// 顶和栈顶的下一个元素以及要入栈的三个元素组成了我们要求最大面积的高度和宽度
Integer mid = stack.pop(); // 凸的中间
if (!stack.isEmpty()) {
Integer left = stack.peek();
Integer right = i;
res = Math.max(res, (right - left - 1) * heights[mid]);
}
}
stack.push(i);
} else {
stack.push(i);
}
}
return res;
}
}
}

View File

@ -1,5 +1,7 @@
package cn.whaifree.leetCode;
import cn.whaifree.leetCode.model.ListNode;
import java.util.ArrayList;
/**
@ -109,13 +111,13 @@ public class LeetCode002 {
}
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 ListNode {
// int val;
// ListNode next;
// ListNode() {}
// ListNode(int val) { this.val = val; }
// ListNode(int val, ListNode next) { this.val = val; this.next = next; }
//}
class RefCountGC{
// 这个成员属性的唯一作用就是占用一点内存

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

@ -13,7 +13,7 @@ public class LeetCode115 {
public void test()
{
Solution solution = new Solution();
System.out.println(solution.numDistinct("rabbbit", "rabbit"));
System.out.println(solution.numDistinct("babgbag", "bag"));
}
class Solution {

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

@ -10,7 +10,7 @@ import cn.whaifree.leetCode.model.TreeNode;
*/
public class LeetCode129 {
public class LeetCode129_2 {
/**

View File

@ -0,0 +1,116 @@
package cn.whaifree.leetCode;
import org.junit.Test;
import cn.whaifree.leetCode.model.ListNode;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/29 14:35
* @注释
*/
public class LeetCode148 {
@Test
public void test() {
ListNode listNode = ListNode.listNodeFromArray(new int[]{-1,5,3,4,0});
ListNode listNode1 = new Solution().sortList(listNode);
listNode1.printList();
}
class Solution {
/**
* 冒泡
* @param head
* @return
*/
public ListNode sortList(ListNode head) {
ListNode resList = new ListNode(-1);
ListNode tmpHead = new ListNode(-1, head);
ListNode pre = tmpHead;
ListNode index = pre; // 用于对比index.next和index.next的指针
ListNode markMaxPre = pre; // 用于标记一次循环的最大值
while (index.next != null) {
// 一次循环找到最大的一个
while (index.next != null) {
if (markMaxPre.next.val < index.next.val) {
markMaxPre = index;
}
index = index.next;
}
ListNode thisMax = markMaxPre.next;
markMaxPre.next = markMaxPre.next.next;
addToHead(resList, thisMax);
index = pre;
markMaxPre = pre;
}
return resList.next;
}
public void addToHead(ListNode pre, ListNode newNode) {
if (newNode == null) {
return;
}
ListNode next = pre.next;
pre.next = newNode;
newNode.next = next;
}
}
@Test
public void test2() {
ListNode listNode = ListNode.listNodeFromArray(new int[]{4,2,1,3});
ListNode listNode1 = new Solution2().sortList(listNode);
listNode1.printList();
}
/**
* 归并排序
*/
class Solution2 {
// 我们使用 fast,slow 快慢双指针法奇数个节点找到中点偶数个节点找到中心左边的节点
public ListNode sortList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode fast = head.next; // 注意不要一起开始
ListNode slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
ListNode BHead = slow.next;
slow.next = null;
ListNode sortAfterA = sortList(head);
ListNode sortAfterB = sortList(BHead);
return merge(sortAfterA, sortAfterB);
}
public ListNode merge(ListNode A, ListNode B) {
ListNode dummy = new ListNode(-1);
ListNode cur = dummy;
while (A != null && B != null) {
if (A.val < B.val) {
cur.next = A;
A = A.next;
} else {
cur.next = B;
B = B.next;
}
cur = cur.next;
}
cur.next = A != null ? A : B;
return dummy.next;
}
}
}

View File

@ -0,0 +1,51 @@
package cn.whaifree.leetCode;
import org.junit.Test;
import java.util.Arrays;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/10/28 14:50
* @注释
*/
public class LeetCode16 {
@Test
public void test() {
int[] nums = {4, 0, 5, -5, 3, 3, 0, -4, -5};
System.out.println(new Solution().threeSumClosest(nums, -2));
}
class Solution {
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int closeV = Integer.MAX_VALUE;
for (int left = 0; left < nums.length; left++) {
int mid = left + 1;
int right = nums.length - 1;
while (mid < right) {
int mv = nums[mid] + nums[left] + nums[right];
if (Math.abs(mv - target) < Math.abs(closeV - target)) {
closeV = mv;
}
if (mv > target) {
right = right - 1;
} else if (mv < target) {
mid = mid + 1;
} else {
return target;
}
}
}
return closeV;
}
}
}

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