This commit is contained in:
whai 2024-04-06 18:20:51 +08:00
parent d8c1950a6b
commit 21761b49b5
12 changed files with 1018 additions and 0 deletions

View File

@ -0,0 +1,161 @@
package cn.whaifree.leetCode.Array;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/5 13:18
* @注释
*/
public class LeetCode31 {
@Test
public void test() {
int[] nums = {3,2,1};
new Solution1().nextPermutation(nums);
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + " ");
}
}
class Solution {
public void nextPermutation(int[] nums) {
if (nums.length == 1) {
return;
}
// 1.下一个数 比当前数大
// 将后面的大数与前面的小数交换就能得到更大的数
// 2. 下一个数 增加的幅度尽可能的小
// - 尽可能靠右的低位 进行交换
// - 将一个 尽可能小的大数 与前面的小数交换
// 123465 5和4换
// - 大数后面的所有数 重置为升序
// 123564 把5后面重新排序
// 1. 从后往前找到第一个升序排列此时后面那部分一定是降序
int i;
for (i = nums.length - 2; i >= 0; i--) {
if (nums[i] < nums[i + 1]) {
break;
}
}
if (i == -1) {
// 最后一个排序 654321直接逆转
reverse(nums, 0, nums.length - 1);
return;
}
// 2. 从i+1开始找到最小的值
int min;
for (min = nums.length - 1; min > 0; min--) {
if (nums[min] > nums[i]) {
break;
}
}
// 3. 交换i和minIndex
swap(nums, i, min);
// 4. 后面为降序直接让其逆转变为升序
reverse(nums, i + 1, 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;
}
}
class Solution1 {
public void nextPermutation(int[] nums) {
if (nums.length == 1) {
return;
}
int i = nums.length - 2;
while (i >= 0) {
if (nums[i] < nums[i + 1]) {
break;
}
i--;
}
if (i == -1) {
// 最后一个排序 654321直接逆转
reverse(nums, 0, nums.length - 1);
return;
}
int min = nums.length - 1;
while (min > 0) {
if (nums[min] > nums[i]) {
break;
}
min--;
}
// 3. 交换i和minIndex
swap(nums, i, min);
// 4. 后面为降序直接让其逆转变为升序
reverse(nums, i + 1, 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;
}
}
}
class ass extends as{
@Override
public void test() {
}
@Override
void test1() {
}
@Override
protected void test2() {
}
}
abstract class as{
abstract public void test() ;
abstract void test1();
abstract protected void test2();
}

View File

@ -0,0 +1,155 @@
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

@ -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,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,73 @@
package cn.whaifree.redo.redo_24_4_1;
import org.junit.Test;
import java.util.Arrays;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/6 15:07
* @注释
*/
public class LeetCode209 {
@Test
public void test() {
int[] nums = {2, 3, 1, 2, 4, 3};
int target = 7;
int i = new Solution2().minSubArrayLen(target, nums);
System.out.println(i);
}
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int right = 0;
int left = 0;
int sum = 0;
int minLength = Integer.MAX_VALUE;
while (right < nums.length) {
sum += nums[right];
while (left <= right && sum >= target) {
minLength = Math.min(minLength, right - left + 1);
sum -= nums[left];
left++;
}
right++;
}
return minLength == Integer.MAX_VALUE ? 0 : minLength;
}
}
class Solution2 {
/**
* <img src="http://42.192.130.83:9000/picgo/imgs/image-20240329122057505.png"></img>
* @param target
* @param nums
* @return
*/
public int minSubArrayLen(int target, int[] nums) {
// 前缀和
int[] preSum = new int[nums.length + 1];
for (int i = 1; i < preSum.length; i++) {
preSum[i] = preSum[i - 1] + nums[i - 1];
}
int minLen = Integer.MAX_VALUE;
for (int i = 0; i < preSum.length; i++) {
// preSum[right] = target + preSum[i]
int fill = target + preSum[i];
int right = Arrays.binarySearch(preSum, fill);
if (right < 0) {
right = -right - 1;
}
if (right < preSum.length) {
minLen = Math.min(minLen, right - i);
}
}
return minLen == Integer.MAX_VALUE ? 0 : minLen;
}
}
}

View File

@ -0,0 +1,78 @@
package cn.whaifree.redo.redo_24_4_1;
import org.junit.Test;
import java.util.Arrays;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/6 16:07
* @注释
*/
public class LeetCode279 {
@Test
public void test()
{
Solution solution = new Solution();
int i = solution.numSquares3(1);
System.out.println(i);
}
class Solution {
public int numSquares(int n) {
// dp[j] 表示从[0-i*i]和为j的完全平方数的数量
// dp[j] = dp[j-i*i]+1
int[] dp = new int[n+1];
int sqrt = (int) Math.sqrt(n);
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 0;
for (int j = 1; j < n + 1; j++) {
for (int i = 1; i <= sqrt; i++) {
if (j >= i * i) {
dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
}
}
}
return dp[n];
}
public int numSquares1(int n) {
// dp[j] 表示从[0-i*i]和为j的完全平方数的数量
// dp[j] = dp[j-i*i]+1
int[] dp = new int[n+1];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 0;
for (int j = 1; j < n + 1; j++) {
for (int i = 1; i * i <= j; i++) {
dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
}
}
return dp[n];
}
public int numSquares3(int n) {
// dp[j] 表示从[0-i*i]和为j的完全平方数的数量
// dp[j] = dp[j-i*i]+1
int[] dp = new int[n+1];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 0;
for (int i = 1; i <= n; i++) {
for (int j = i * i; j <= n; j++) {
dp[j] = Math.min(dp[j], dp[j - i * i] + 1);
}
}
return dp[n];
}
}
}

View File

@ -0,0 +1,49 @@
package cn.whaifree.redo.redo_24_4_1;
import org.junit.Test;
import java.util.Arrays;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/6 16:28
* @注释
*/
public class LeetCode322 {
@Test
public void test() {
int[] coins = { 2 };
int amount = 3;
Solution solution = new Solution();
int i = solution.coinChange(coins, amount);
System.out.println(i);
}
class Solution {
/**
* 背包容量amount+1
*
* dp[j] 表示从0-i中任意取放入amount
* dp[j] = math.min(dp[j] , dp[j-coins[i]]+1)
*
*
* @param coins
* @param amount
* @return
*/
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount + 1];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 0;
for (int i = 0; i < coins.length; i++) {
for (int j = coins[i]; j < amount + 1; j++) {
if (dp[j - coins[i]] != Integer.MAX_VALUE) {
dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);
}
}
}
return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount];
}
}
}

View File

@ -0,0 +1,45 @@
package cn.whaifree.redo.redo_24_4_1;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/6 17:00
* @注释
*/
public class LeetCode377 {
@Test
public void test() {
Solution solution = new Solution();
int[] nums = {9};
int target = 3;
int i = solution.combinationSum4(nums, target);
System.out.println(i);
}
class Solution {
public int combinationSum4(int[] nums, int target) {
int[] dp = new int[target + 1];
dp[0] = 1;
for (int j = 0; j < target + 1; j++) {
for (int i = 0; i < nums.length; i++) {
if (nums[i] <= j) {
dp[j] = dp[j] + dp[j - nums[i]];
}
}
}
// for (int i = 0; i < nums.length; i++) {
// for (int j = nums[i]; j <= target; j++) {
// dp[j] = dp[j] + dp[j - nums[i]];
// }
// }
return dp[target];
}
}
}

View File

@ -0,0 +1,74 @@
package cn.whaifree.redo.redo_24_4_1;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/6 17:08
* @注释
*/
public class LeetCode474 {
@Test
public void test() {
String[] strs = new String[]{"10", "0001", "111001", "1", "0"};
int m = 5;
int n = 3;
System.out.println(new Solution().findMaxForm(strs, m, n));
}
class Solution {
public int findMaxForm(String[] strs, int m, int n) {
/**
* dp[i][j][k] 表示包含 i个0j个1从前k个子集中取出的最大子集长度
*
* i j 为背包容量
* k为物品
*
* for 背包
* 统计01数量
* fori
* forj
* if(i>=zero j>=one)
* dp[i][j][k] = max(dp[i][j][k-1],dp[i-zero][j-one][k-1]+1)
* else
* dp[i][j][k] = dp[i][j][k-1]
*
*/
int[][][] dp = new int[m + 1][n + 1][strs.length + 1];
for (int k = 1; k <= strs.length; k++) {
String str = strs[k-1];
int zero = calculateZeroNumber(str);
int one = str.length() - zero;
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (i >= zero && j >= one) {
dp[i][j][k] = Math.max(dp[i][j][k - 1], dp[i - zero][j - one][k - 1] + 1);
} else {
dp[i][j][k] = dp[i][j][k - 1];
}
}
}
}
return dp[m][n][strs.length];
}
public int calculateZeroNumber(String str) {
int num = 0;
for (int i = 0; i < str.length(); i++) {
if (str.charAt(i) == '0') {
num++;
}
}
return num;
}
}
}

View File

@ -0,0 +1,47 @@
package cn.whaifree.redo.redo_24_4_1;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/6 17:34
* @注释
*/
public class LeetCode494 {
@Test
public void test()
{
Solution solution = new Solution();
int[] nums = new int[]{1, 1, 1, 1, 1};
int target = 3;
int i = solution.findTargetSumWays(nums, target);
System.out.println(i);
}
class Solution {
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
if (Math.abs(target) > sum) return 0; // 此时没有方案
if ((target + sum) % 2 == 1) return 0; // 此时没有方案
int left = (sum + target) / 2;
// dp[j] 表示 从0-i 中任意取背包容量为 j 能装下的组合数
// dp[j] = dp[j] + dp[j-nums[i]]
int[] dp = new int[left + 1];
dp[0] = 1;
for (int i = 0; i < nums.length; i++) {
for (int j = left; j >= nums[i]; j--) {
// 已经有一个1nums[i] 的话 dp[4]种方法 凑成 容量为5的背包
dp[j] = dp[j] + dp[j - nums[i]];
}
}
return dp[left];
}
}
}

View File

@ -0,0 +1,126 @@
package cn.whaifree.redo.redo_24_4_1;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/6 12:44
* @注释
*/
public class LeetCode53 {
@Test
public void test() {
int[] nums = new int[]{1};
int maxSubArray = new Solution1().maxSubArray(nums);
System.out.println(maxSubArray);
}
class Solution {
public int maxSubArray(int[] nums) {
// 滑动窗口
// 遇到和为负数就一直缩小left
int maxSum = Integer.MIN_VALUE;
int nowSum = 0;
for (int i = 0; i < nums.length; i++) {
nowSum += nums[i];
maxSum = Math.max(maxSum, nowSum);
if (nowSum < 0) {
nowSum = 0;
}
}
return maxSum;
}
}
class Solution1 {
/**
* dp
*
* dp[i] 表示i处结尾的的最大连续子数组的和
*
* dp[0] = nums[0]
* dp[i]
* if nums[i]+dp[i-1] > 0
* dp[i] = dp[i-1]+nums[i]
* else
* dp[i] = nums[i]
*
* @param nums
* @return
*/
public int maxSubArray(int[] nums) {
int[] dp = new int[nums.length];
dp[0] = nums[0];
int max = nums[0];
for (int i = 1; i < nums.length; i++) {
if (dp[i - 1] > 0 && nums[i] + dp[i - 1] > 0) {
dp[i] = dp[i - 1] + nums[i];
} else {
dp[i] = nums[i];
}
max = Math.max(max, dp[i]);
}
return max;
}
}
class Solution4 {
/**
* 前缀和
* @param nums
* @return
*/
// public int maxSubArray(int[] nums) {
//
// int[] preSum = new int[nums.length + 1];
// for (int i = 1; i < nums.length; i++) {
// preSum[i] = preSum[i - 1] + nums[i - 1];
// }
//
//
// }
}
}
class XieChen {
/**
* 将偶数的区间/2 让整个区间最大
* 给定一个数组对一个区间区间内全部都是偶数全部/2使得整个数组和最大求数组最大和
*/
public static void main(String[] args) {
}
public void xc(int[] nums) {
// 前缀和
int[] preSum = new int[nums.length + 1];
for (int i = 1; i < nums.length; i++) {
preSum[i] = preSum[i - 1] + nums[i - 1];
}
int minLoc = 0;
int left = 0;
int right = 0;
while (right < nums.length) {
right++;
}
}
}

View File

@ -0,0 +1,42 @@
package cn.whaifree.redo.redo_24_4_6;
import org.junit.Test;
/**
* @version 1.0
* @Author whai文海
* @Date 2024/4/6 12: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 {
public int maxArea(int[] height) {
// capacity = (right-left)*min(right,left)
// 移动短的可能变大不变变小
// 移动长的只会变小
int left = 0;
int right = height.length - 1;
int capacity = Integer.MIN_VALUE;
while (left < right) {
capacity = Math.max(capacity, (right - left) * Math.min(height[left], height[right]));
if (height[left] < height[right]) {
left++;
}else {
right--;
}
}
return capacity;
}
}
}