初始化

This commit is contained in:
whai 2023-12-01 21:20:53 +08:00
commit bc35fd83f4
8 changed files with 840 additions and 0 deletions

45
.gitignore vendored Normal file
View File

@ -0,0 +1,45 @@
HELP.md
docker/
target/
img/
files/
logs/
**/node_modules/
**/dist/
**/.idea/
**/**.jar
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### maven ###
.mvn/

22
pom.xml Normal file
View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>LeetCode</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
</dependencies>
</project>

View File

@ -0,0 +1,65 @@
package cn.whaifree.leetCode;
import java.util.HashMap;
import java.util.Map;
/**
*
* 给定一个整数数组 nums 和一个整数目标值 target请你在该数组中找出 和为目标值 target  的那 两个 整数并返回它们的数组下标
*
* 你可以假设每种输入只会对应一个答案但是数组中同一个元素在答案里不能重复出现
*
* 你可以按任意顺序返回答案
*
* 来源力扣LeetCode
* 链接https://leetcode.cn/problems/two-sum
* 著作权归领扣网络所有商业转载请联系官方授权非商业转载请注明出处
*
*
*
* 输入nums = [2,7,11,15], target = 9
* 输出[0,1]
* 解释因为 nums[0] + nums[1] == 9 返回 [0, 1]
*
*
* @author whaifree
* @package cn.whaifree.leetCode
* @Date: 2022/9/13 20:54
*/
public class LeetCode001 {
/**
* map存储key为nums内的值value为下标
* @param nums
* @param target
* @return
*/
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
int key;
for (int i = 0; i < nums.length; i++) {
//如果包含匹配的元素即输出下标
key = target - nums[i];
if (map.containsKey(key)){
return new int[]{map.get(key),i};
}else {
map.put(nums[i],i);
}
//不包含匹配的元素则增加到map中
}
return null;
}
public static void main(String[] args) {
int[] ints = new LeetCode001().twoSum(new int[]{2, 7, 11, 15}, 13);
for (int anInt : ints) {
System.out.println(anInt);
}
}
}

View File

@ -0,0 +1,116 @@
package cn.whaifree.leetCode;
/**
*
*
* 给你两个 非空 的链表表示两个非负的整数它们每位数字都是按照 逆序 的方式存储的并且每个节点只能存储 一位 数字
*
* 请你将两个数相加并以相同形式返回一个表示和的链表
*
* 你可以假设除了数字 0 之外这两个数都不会以 0 开头
*
* 来源力扣LeetCode
* 链接https://leetcode.cn/problems/add-two-numbers
* 著作权归领扣网络所有商业转载请联系官方授权非商业转载请注明出处
*
* @author whaifree
* @package cn.whaifree.leetCode
* @Date: 2022/9/13 21:18
*/
public class LeetCode002 {
/**
* l1和l2向下移动让答案节点的值为l1+l2+carrycarry表示上一节点所带来的增1
* @param l1
* @param l2
* @return
*/
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode ansNode=new ListNode(0);
ListNode ansIndex = ansNode;
int carry = 0;
while (l1!=null||l2!=null||carry!=0){
//如果l1和l2都空了但carry为1还是要多一个1节点的
int val1 = l1==null?0:l1.val;
int val2 = l2==null?0:l2.val;
int nodeVal = val1 + val2 + carry;
carry = nodeVal / 10;
ansIndex.next = new ListNode(nodeVal % 10);
ansIndex = ansIndex.next;
//一旦l1为空直接把l2接上
if (l1!=null){
l1 = l1.next;
}
//l2为空把l1接上
if (l2!=null){
l2 = l2.next;
}
}
return ansNode.next;
}
/**
* 从坐到右挨个相加
* val%10 取得余数
* val//10 取得整数十位
* @param l1
* @param l2
* @return
*/
public ListNode addTwoNumbers1(ListNode l1, ListNode l2) {
ListNode ansNode = new ListNode(0);
ListNode ansIndex = ansNode;
ListNode index1 = l1;
ListNode index2 = l2;
boolean flag = false;
while (index1 != null || index2 != null) {
//两个指针都非空的时候表示需要计算往下加
int val1 = index1.val;
int val2 = flag?index2.val+1:index2.val;
flag = false;
if (val1+val2<10){
//无需进1
ansIndex.next = new ListNode(val1+val2);
}else {
//需要进1
ansIndex.next = new ListNode((val1+val2)-10);
flag = true;
}
index1 = index1.next;
index2 = index2.next;
}
//直接追加
if (index1 != null) {
ansIndex.next = index1;
}else {
ansIndex.next = index2;
}
return ansNode.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; }
}

View File

@ -0,0 +1,107 @@
package cn.whaifree.leetCode;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
*
* 给定一个字符串 s 请你找出其中不含有重复字符的 最长子串 的长度
*
*  
*
* 示例 1:
*
* 输入: s = "abcabcbb"
* 输出: 3
* 解释: 因为无重复字符的最长子串是 "abc"所以其长度为 3
* 示例 2:
*
* 输入: s = "bbbbb"
* 输出: 1
* 解释: 因为无重复字符的最长子串是 "b"所以其长度为 1
* 示例 3:
*
* 输入: s = "pwwkew"
* 输出: 3
* 解释: 因为无重复字符的最长子串是 "wke"所以其长度为 3
*   请注意你的答案必须是 子串 的长度"pwke" 是一个子序列不是子串
*  
*
* 来源力扣LeetCode
* 链接https://leetcode.cn/problems/longest-substring-without-repeating-characters
* 著作权归领扣网络所有商业转载请联系官方授权非商业转载请注明出处
*
*
* @author whaifree
* @package cn.whaifree.leetCode
* @Date: 2022/9/15 19:01
*/
public class LeetCode003 {
/**
* 使用一个Map key为字符的值value为字符的下标
* 每次遇到没有的就往Map添加并且右指针移动
* 遇到有的就左指针指向前一个的value
* @param s
* @return
*/
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> map = new HashMap<>();
//获得s每个字符
char[] chars = s.toCharArray();
//lengthIndex作为当前长度的标志
//maxLength用于给出最后的结果
int maxLength = 0;
//需要两个左右指针
int leftIndex = 0;
for (int i = 0; i < chars.length; i++) {
if (map.containsKey(chars[i])){
//出现过了 左指针右移到它上次出现地方的下一个位置
//但如abba移动到最后一个a时left应该指向第二个b而不是a的位置+1
leftIndex = Math.max(leftIndex,map.get(chars[i])+1);
}
map.put(chars[i], i);
maxLength = Math.max(maxLength, i - leftIndex + 1);
}
return maxLength;
}
public static void main(String[] args) {
System.out.println(new LeetCode003().lengthOfLongestSubstring1("abba"));
}
/**
* 使用Map abbcd
* @param s
* @return
*/
public int lengthOfLongestSubstring1(String s) {
//key为char字符value为下标
Map<Character, Integer> map = new HashMap<>();
int maxLength = 0,left = 0;
for (int i = 0; i < s.length(); i++) {
//如果出现过
if (map.containsKey(s.charAt(i))){
left = Math.max(left, map.get(s.charAt(i)) + 1);
}
//加入队列
map.put(s.charAt(i),i);
//更新maxLength
maxLength = Math.max(maxLength, i - left + 1);
}
return maxLength;
}
}

View File

@ -0,0 +1,135 @@
package cn.whaifree.leetCode;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
/**
*
* 找出该数组中满足其和 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] 并返回其长度如果不存在符合条件的子数组返回 0
*
* 来源力扣LeetCode
* 链接https://leetcode.cn/problems/minimum-size-subarray-sum
* 著作权归领扣网络所有商业转载请联系官方授权非商业转载请注明出处
*
* 示例 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
*
* @author whaifree
* @package cn.whaifree.leetCode
* @Date: 2022/9/20 10:16
*/
public class LeetCode209 {
public int minSubArrayLen(int target, int[] nums) {
//滑动窗口
Queue<Integer> queue = new LinkedList<Integer>();
//标记最短长度
int shortest = 100000;
int sum = 0;
for (int i = 0; i < nums.length; i++) {
queue.add(nums[i]);
if (sum + nums[i] >= target) {
//达标了需要将shortest更新为最短的
if (shortest>queue.size()){
shortest = queue.size();
}
//sum减去上一个
sum -= queue.poll();
}
sum += nums[i];
}
if (queue.size()==nums.length){
return 0;
}
return shortest;
}
public static void main(String[] args) {
System.out.println(new LeetCode209().minSubArrayLen2(8, new int[]{1,1,1,1,1,1,1,1}));
}
public int minSubArrayLen1(int target, int[] nums) {
//使用队列不停得入队直到大于target再不停出队直到小于target
Queue<Integer> queue = new LinkedList<>();
int sum = 0;
int shortest = 100000;
int nowSum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
//入队
queue.add(nums[i]);
//队列内的值之和
nowSum += nums[i];
while (nowSum >= target) {
if (shortest > queue.size()){
shortest = queue.size();
}
//不停出队
nowSum -= queue.poll();
}
}
//判断nums之和小于target的情况
if (sum < target) {
return 0;
}
return shortest;
}
/**
* 使用nums数组作为队列
* @param target
* @param nums
* @return
*/
public int minSubArrayLen2(int target, int[] nums) {
int leftIndex = 0, rightIndex = 0;
int shortest = 100000;
int nowSum = 0;
for (int i = 0; i < nums.length; i++) {
nowSum += nums[i];
//入队
rightIndex++;
while (nowSum >= target){
//更新shortest
shortest = Math.min(shortest, rightIndex - leftIndex);
nowSum -= nums[leftIndex++];
//出队
}
}
if (nums.length==rightIndex-leftIndex){
return 0;
}
return shortest;
}
}

View File

@ -0,0 +1,131 @@
package cn.whaifree.leetCode;
/**
*
* 给两个整数数组 nums1 nums2 返回 两个数组中 公共的 长度最长的子数组的长度
*
*
*
* 示例 1
*
* 输入nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7]
* 输出3
* 解释长度最长的公共子数组是 [3,2,1]
* 示例 2
*
* 输入nums1 = [0,0,0,0,0], nums2 = [0,0,0,0,0]
* 输出5
*
*
* 提示
*
* 1 <= nums1.length, nums2.length <= 1000
* 0 <= nums1[i], nums2[i] <= 100
*
* @author whaifree
* @package cn.whaifree.leetCode
* @Date: 2022/9/24 15:39
*/
public class LeetCode718 {
public static void main(String[] args) {
System.out.println(new LeetCode718().findLength(new int[]{1,2,3,2,1},new int[]{3,2,1,4,7}));
}
/**
* 两层循环 动态规划
* @param nums1
* @param nums2
* @return
*/
public int findLength(int[] nums1, int[] nums2) {
//存储标记
int db[][] = new int[nums1.length+1][nums2.length+1];
for (int i = 0; i < nums1.length; i++) {
for (int j = 0; j < nums2.length; j++) {
//如果两个数组在某处重复就在i-1,j-1的基础上+1表示新已知最大子数组长度+1
if (nums1[i]==nums2[j]){
db[i + 1][j + 1] = db[i][j] + 1;
}
}
}
//求得二维度最大值
int max = 0;
for (int[] ints : db) {
for (int anInt : ints) {
max = Math.max(max, anInt);
}
}
return max;
}
/**
* 默认nums1短 nums2长
* @param nums1
* @param nums2
* @return
*//*
public int findLength2(int[] nums1, int[] nums2) {
int max = 0;
for (int i = 0; i < nums1.length; i++) {
max = Math.max(max, findMaxInTwo(nums1, 0, nums2, nums2.length-i, i));
}
for (int i = 0; i < nums1.length; i++) {
max = Math.max(max, findMaxInTwo(nums1, 0, nums2, nums2.length-i, i));
}
for (int i = 0; i < nums1.length; i++) {
max = Math.max(max, findMaxInTwo(nums1, 0, nums2, nums2.length-i, i));
}
}
*//**
* findMaxInTwo({2,3,4},1,{3,4,5},0,2) 就是从两个数组中找到字串为2的公共字串长度
*
*
* A: |*|*|*|*|
* B: |*|*|*|*|*|*|
*
*
* @param nums1
* @param nums1Index
* @param nums2
* @param nums2Index
* @param len
* @return
*//*
int findMaxInTwo(int[] nums1,int nums1Index ,int[] nums2,int nums2Index,int len){
//判断是否有重复子串
int count = 0;
//存放现在的匹配字串长度值
int max = 0;
for (int i = 0; i < len; i++) {
//遇到相等的就当前匹配长度++
if (nums1[nums1Index + i] == nums2[nums2Index + i]) {
count++;
} else {
//遇到不相等的就判断一下当前匹配字串与最大匹配字串长度
max = Math.max(max, count);
count = 0;
}
}
//找到最大匹配的字串长度
return Math.max(max,count);
}*/
}

View File

@ -0,0 +1,219 @@
package cn.whaifree.leetCode;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author whaifree
* @package cn.whaifree.leetCode
* @Date: 2022/9/11 19:14
*
* 在一个长度为 n 的数组 nums 里的所有数字都在 0n-1 的范围内
* 数组中某些数字是重复的但不知道有几个数字重复了也不知道每个数字重复了几次请找出数组中任意一个重复的数字
*
* 示例 1
*
* 输入
* [2, 3, 1, 0, 2, 5, 3]
* 输出2 3
*  
*
* 限制
*
* 2 <= n <= 100000
*
* 来源力扣LeetCode
* 链接https://leetcode.cn/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof
* 著作权归领扣网络所有商业转载请联系官方授权非商业转载请注明出处
*/
public class Offer03 {
public static void main(String[] args) {
// System.out.println(new Solution1().findRepeatNumber5(new int[]{1, 2, 3,2, 3}));
}
}
class Solution1 {
/**
* 1. 找一个num长度的数组n遍历统计n内大于1输出
* 2. Map key为数字value自增遍历Map获得value>1的key
* 3. 先排序再向下找重复
*/
/**
* Map方法
* @param nums
* @return
*/
public int findRepeatNumber(int[] nums) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
int integer = 0;
for (int num : nums) {
if (map.containsKey(num)){
//原来是有这个数字的
integer = map.get(num);
map.put(num,++integer);
}else {
//没有这个数字
map.put(num,1);
}
}
/**
* 遍历map的方法
* 1. 遍历keySet的Set<K>
* 2. 遍历Values只能遍历Value
* 3. 遍历entrySet()
* 4. forEach遍历
*/
//遍历map的key
// System.out.println("1. 遍历keySet的Set<K>");
for (Integer i : map.keySet()) {
if (map.get(i)>1){
System.out.println(i);
}
}
// System.out.println("3. 遍历entrySet()");
// for (Map.Entry<Integer, Integer> integerIntegerEntry : map.entrySet()) {
// System.out.println("key = " + integerIntegerEntry.getKey());
// System.out.println("value = " + integerIntegerEntry.getValue());
// }
//
// System.out.println("4. forEach遍历");
// map.forEach((key,value)->{
// System.out.println("key is "+ key);
// System.out.println("value is "+ value);
// });
return 0;
}
/**
* 排序向下找重复
* @param nums
* @return
*/
public int findRepeatNumber2(int[] nums) {
//冒泡排序
boolean flag = true;
int c=0;
int length = nums.length;
for (int i = 0; i < length; i++) {
for (int j = 0; j < length-i-1; j++) {
if (nums[j] > nums[j+1]) {
c = nums[j+1];
nums[j+1] = nums [j];
nums[j] = c;
}
}
}
/*for (int num : nums) {
System.out.println(num);
}*/
//排序完成
/**
* 在已经排序的里面找到有出现大于两次的
*/
return 0;
}
/**
*
* 完成
*
* 题目找出任意一个重复的数字
* @param nums
* @return
*/
public int findRepeatNumber3(int[] nums) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int num : nums) {
if (map.containsKey(num)){
//原来是有这个数字的证明不是第一次出现了直接输出就是结果
return num;
}else {
//没有这个数字,首次出现
map.put(num,1);
}
}
return 0;
}
/**
* 使用HashSet
* @param nums
* @return
*/
public int findRepeatNumber4(int[] nums) {
Set<Integer> set = new HashSet<>();
for (int num : nums) {
if (set.contains(num)){
//有这个数字直接输出
return num;
}else {
//没有这个数字就增加在set中
set.add(num);
}
}
return 0;
}
/**
* 下标法不停交换元素使得元素和对应下标相等
* nums[i]=i
* nums[nums[i]] = nums[i] 下标与元素值相等
*
* 通过索引映射对应的值起到与字典等价的作用
* 长度为 n 的数组 nums 里的所有数字都在 0n-1 的范围内即能够确定索引的大小
*
* @param nums
* @return
*/
public int findRepeatNumber5(int[] nums){
int flag = 0;
int i = 0;
while (i < nums.length){
//遍历每个数
//1. 不在正确位置上进行交换
// 如果交换的位置已经有正确的数字直接输出结果
//2. 在正确的位置上continue
if (nums[i]!=i){
//需要进行交换
if (nums[nums[i]]==nums[i]){
//在该位置已经有正确的位置提前占好了
return nums[i];
}
//交换 nums[nums[i]]和nums[i]
flag = nums[i];
nums[i] = nums[nums[i]];
nums[flag] = flag;
}else {
i++;
}
}
return -1;
}
}