diff --git a/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode1143.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode1143.java new file mode 100644 index 0000000..942e279 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode1143.java @@ -0,0 +1,52 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/24 12:00 + * @注释 + */ +public class LeetCode1143 { + + @Test + public void test() { + Solution solution = new Solution(); + int res = solution.longestCommonSubsequence("bsbininm","jmjkbkjkv" ); + System.out.println(res); + } + + class Solution { + public int longestCommonSubsequence(String text1, String text2) { + + // 公共子序列 dp[len1+1][len2+1] + // dp[i][j] 表示 text1的前i-1与text2的前j-1中有多长的公共子序列长度 + // dp[i][j]:长度为[0, i - 1]的字符串text1与长度为[0, j - 1]的字符串text2的最长公共子序列为dp[i][j] + // if text1[i]==text2[i] + // + // + int len1 = text1.length(); + int len2 = text2.length(); + + int[][] dp = new int[len1 + 1][len2 + 1]; + + for (int i = 1; i <= len1; i++) { + for (int j = 1; j <= len2; j++) { + // 如果相等 + if (text1.charAt(i - 1) == text2.charAt(j - 1)) { + dp[i][j] = dp[i - 1][j - 1] + 1; + //dp[i][j] = Math.max(dp[i][j - 1] + 1, dp[i][j]); + } else { + dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]); + // dp[i][j] = Math.max(dp[i - 1][j - 1], Math.max(dp[i - 1][j], dp[i][j - 1])); + } + + } + } + + return dp[len1][len2]; + } + } + +} diff --git a/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode300.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode300.java new file mode 100644 index 0000000..139f828 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode300.java @@ -0,0 +1,79 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +import java.util.Arrays; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/22 13:23 + * @注释 + */ +public class LeetCode300 { + + @Test + public void test() + { + int[] nums = {4,10,4,3,8,9}; + Solution solution = new Solution(); + int i = solution.lengthOfLIS(nums); + System.out.println(i); + } + + class Solution { + /** + * int[i][j] 表示i-j的最长严格递增子序列长度 + * @param nums + * @return + */ + public int lengthOfLIS(int[] nums) { + int[] dp = new int[nums.length]; + + + // dp[i]表示i之前包括i的以(nums[i]结尾)(即每次都必须包括i,每次都需要和i比较)的最长递增子序列的长度 + // 位置i的最长升序子序列 = j从0到i-1各个位置的 最长升序子序列 + 1 的 最大值 + Arrays.fill(dp, 1); + int res = 1; + for (int i = 1; i < nums.length; i++) { + for (int j = 0; j < i; j++) { + if (nums[j] < nums[i]) { + dp[i] = Math.max(dp[i], dp[j] + 1); + } + } + + res = Math.max(res, dp[i]);// 取长的子序列 + } + + return res; + } + } + + + class Solution1 { + + public int lengthOfLIS(int[] nums) { + // 最长严格递增子序列的长度 + /** + * dp[i] 表示包含从0-i包含i(i在每次循环中是最后一个)的最长递增子序列的长度 + */ + int[] dp = new int[nums.length]; + Arrays.fill(dp, 1); // 最初就是1个 + + int res = 1; + for (int i = 1; i < nums.length; i++) { + for (int j = 0; j < i; j++) { + // 从0到i-1 + // nums[j] < nums[i] 就证明 nums[j] 小于 nums[i] ,前面有多少个j就计算多少次 + if (nums[j] < nums[i]) { + dp[i] = Math.max(dp[i], dp[j] + 1); // dp[i] 为0-(j-1)的最长递增子序列长度,dp[j] + 1 为0-j的最长递增子序列长度,取两者最大值 + } + } + res = Math.max(res, dp[i]); // 每次获得以i为最后一个的最长递增子序列的长度 + } + return res; + } + } + + +} diff --git a/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode674.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode674.java new file mode 100644 index 0000000..980372d --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode674.java @@ -0,0 +1,95 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/23 11:56 + * @注释 + */ +public class LeetCode674 { + @Test + public void test() + { + + int[] nums = new int[]{1,1,1,1}; + int lengthOfLCIS = new Solution1().findLengthOfLCIS(nums); + System.out.println(lengthOfLCIS); + } + + class Solution2 { + /** + * 如果当前元素大于前一个元素,则递增计数,并将计数与结果中的最大值进行比较更新。 + * 如果当前元素不大于前一个元素,则将计数重置为1。 + * @param nums + * @return + */ + public int findLengthOfLCIS(int[] nums) { + int res = 1; + int count = 1; + for (int i = 1; i < nums.length; i++) { + if (nums[i] > nums[i - 1]) { + count++; + res = Math.max(res, count); + } else { + count = 1; + } + } + return res; + } + } + + class Solution { + + + /** + * 最长且 连续递增的子序列 + * @param nums + * @return + */ + public int findLengthOfLCIS(int[] nums) { + // 找到所有递增区间 + int left = 0; + int right = 0; + int maxLength = 0; + while (right < nums.length - 1) { + if (nums[right + 1] <= nums[right]) { + maxLength = Math.max(maxLength, right - left + 1); + right++; + left = right; + }else { + right++; + } + } + + return Math.max(maxLength, right - left + 1); + } + } + + class Solution1 { + public int findLengthOfLCIS(int[] nums) { + /** + * dp[i] 表示可包含i的最长子序列长度 + * if nums[i] > nums[i-1] 递增 + * dp[i] = dp[i-1]+1 + * else + * dp[i] = 1 一旦出现递减,因为前面的连续递增是不能用的,需要直接重置 + */ + int[] dp = new int[nums.length]; + dp[0] = 1; + int ans = 1; + for (int i = 1; i < nums.length; i++) { + if (nums[i] > nums[i-1]) { + dp[i] = dp[i-1] + 1; + }else { + dp[i] = 1; + } + ans = Math.max(ans, dp[i]); + } + return ans; + } + + + } +} diff --git a/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode718.java b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode718.java new file mode 100644 index 0000000..771b9d6 --- /dev/null +++ b/src/main/java/cn/whaifree/leetCode/Dynamic/LeetCode718.java @@ -0,0 +1,78 @@ +package cn.whaifree.leetCode.Dynamic; + +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/23 12:22 + * @注释 + */ + +public class LeetCode718 { + @Test + public void test() + { + int[] nums1 = {1,2,3,2,1}; + int[] nums2 = {3,2,1,4,7}; + + int i = new Solution1().findLength(nums1, nums2); + System.out.println(i); + } + + class Solution { + public int findLength(int[] nums1, int[] nums2) { + + /** + * 用二维数组可以记录两个字符串的所有比较情况 + * dp[i][j] 表示 以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度 + * dp[i][j] 可以由dp[i-1][j-1] + 1 和 0 两种情况推出 + * + * dp[i][j] + * if nums1[i]==nums[j] + * dp[i][j] = dp[i-1][j-1] + 1 + * else + * dp[i][j] = 0 + */ + int[][] dp = new int[nums1.length + 1][nums2.length + 1]; + int res = 0; + for (int i = 1; i <= nums1.length; i++) { + for (int j = 1; j <= nums2.length; j++) { + if (nums1[i - 1] == nums2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = 0; + } + res = Math.max(res, dp[i][j]); + } + } + + return res; + } + } + + class Solution1 { + public int findLength(int[] nums1, int[] nums2) { + + /** + * dp[i][j]都是由dp[i - 1][j - 1]推出。那么压缩为一维数组,也就是dp[j]都是由dp[j - 1]推出。 + * + */ + int[] dp = new int[nums1.length + 1]; + int res = 0; + for (int i = 1; i <= nums1.length; i++) { + for (int j = nums2.length; j > 0; j--) { // 从后面开始比较,避免重复覆盖dp[i] + if (nums1[i - 1] == nums2[j - 1]) { + dp[j] = dp[j - 1] + 1; + } else { + dp[j] = 0; + } + res = Math.max(res, dp[j]); + } + } + + return res; + } + } + +} diff --git a/src/main/java/cn/whaifree/redo/redo_24_4_20/LeetCode32.java b/src/main/java/cn/whaifree/redo/redo_24_4_20/LeetCode32.java new file mode 100644 index 0000000..084e279 --- /dev/null +++ b/src/main/java/cn/whaifree/redo/redo_24_4_20/LeetCode32.java @@ -0,0 +1,103 @@ +package cn.whaifree.redo.redo_24_4_20; + +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/22 11:20 + * @注释 + */ +public class LeetCode32 { + + @Test + public void test() { + + int i = new Solution1().longestValidParentheses("()(()"); + System.out.println(i); + } + + class Solution { + /** + * 左右括号的数量,遇到右括号数量>左括号就重置 + * @param s + * @return + */ + public int longestValidParentheses(String s) { + int max = 0; + + int left = 0, right = 0; + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == '(') { + left++; + }else { + right++; + } + + if (left == right) { + max = Math.max(max, 2 * right); + } + + if (left < right) { + left = 0; + right = 0; + } + } + + left = 0; + right = 0; + for (int i = s.length() - 1; i > 0; i--) { + if (s.charAt(i) == '(') { + left++; + } else { + right++; + } + + if (left == right) { + max = Math.max(max, 2 * right); + } + + if (left > right) { + left = 0; + right = 0; + } + } + + return max; + } + } + + class Solution1 { + public int longestValidParentheses(String s) { + Deque stack = new LinkedList<>(); + // boolean 判断是否出现过 + boolean[] flag = new boolean[s.length()]; + char[] chars = s.toCharArray(); + for (int i = 0; i < chars.length; i++) { + if (chars[i] == '(') { + stack.push(i); + }else if (!stack.isEmpty()){ + Integer index = stack.pop(); + flag[index] = true; + flag[i] = true; + } + } + // 计算boolean[]中连续true的数量 + int max = 0; + int now = 0; + for (boolean b : flag) { + if (b) { + now++; + }else { + now = 0; + } + max = Math.max(max, now); + } + return max; + } + + } +} diff --git a/src/main/java/cn/whaifree/redo/redo_24_4_20/LeetCode337.java b/src/main/java/cn/whaifree/redo/redo_24_4_20/LeetCode337.java new file mode 100644 index 0000000..ed326df --- /dev/null +++ b/src/main/java/cn/whaifree/redo/redo_24_4_20/LeetCode337.java @@ -0,0 +1,48 @@ +package cn.whaifree.redo.redo_24_4_20; + +import cn.whaifree.leetCode.model.TreeNode; +import org.junit.Test; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/22 11:44 + * @注释 + */ +public class LeetCode337 { + @Test + public void test() + { + + int rob = new Solution().rob(TreeNode.constructTreeByArray(1)); + System.out.println(rob); + } + + class Solution { + public int rob(TreeNode root) { + int[] circle = circle(root); + return Math.max(circle[0], circle[1]); + } + + /** + * int[0] 表示 不偷该点的最大收益 + * int[1] 表示 偷该点的最大收益 + * @param root + * @return + */ + public int[] circle(TreeNode root) { + if (root == null) { + return new int[]{0, 0}; + } + + int[] left = circle(root.left); + int[] right = circle(root.right); + int[] res = new int[2]; + // 该店不偷,子节点可偷可不偷 只要最大收益 + res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]); + res[1] = left[0] + right[0] + root.val; + + return res; + } + } +} diff --git a/src/main/java/cn/whaifree/redo/redo_24_4_20/LeetCode84.java b/src/main/java/cn/whaifree/redo/redo_24_4_20/LeetCode84.java new file mode 100644 index 0000000..004a84b --- /dev/null +++ b/src/main/java/cn/whaifree/redo/redo_24_4_20/LeetCode84.java @@ -0,0 +1,91 @@ +package cn.whaifree.redo.redo_24_4_20; + +import org.junit.Test; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * @version 1.0 + * @Author whai文海 + * @Date 2024/4/22 11:51 + * @注释 + */ +public class LeetCode84 { + + @Test + public void test() + { + int[] heights = {2,1,2}; + int i = new Solution1().largestRectangleArea(heights); + System.out.println(i); + } + + class Solution { + public int largestRectangleArea(int[] heights) { + if (heights.length == 1) { + return heights[0]; + } + /** + * 找到凸点 + * 对于每个index,找到左右第一个比他矮的 + */ + + int length = heights.length; + int[] left = new int[length]; + int[] right = new int[length]; + left[0] = -1; + + int leftIndex = 0; // 标记第一个小于当前i的 + for (int i = 1; i < length; i++) { + leftIndex = i - 1; + while (leftIndex >= 0 && heights[leftIndex] >= heights[i]) { + // 也可以简单粗暴的leftIndex--,但会超时 + leftIndex = left[leftIndex]; + } + left[i] = leftIndex; + } + + right[length - 1] = length; + int rightIndex = 0; // 标记第一个小于当前i的 + for (int i = length - 2; i >= 0; i--) { + rightIndex = i + 1; + while (rightIndex <= length - 1 && heights[rightIndex] >= heights[i]) { + rightIndex = right[rightIndex]; + } + right[i] = rightIndex; + } + + int maxRegin = 0; + for (int i = 0; i < length; i++) { + maxRegin = Math.max(heights[i] * (right[i] - left[i] - 1), maxRegin); + } + return maxRegin; + } + } + + class Solution1 { + public int largestRectangleArea(int[] heights) { + + int[] ints = new int[heights.length + 2]; + System.arraycopy(heights, 0, ints, 1, heights.length); + heights = ints; + + Deque stack = new LinkedList<>(); + stack.push(0); + int maxRegin = 0; + for (int i = 1; i < heights.length; i++) { + if (heights[i] < heights[stack.peek()]) { + while (!stack.isEmpty() && heights[i] < heights[stack.peek()]) { + Integer pop = stack.pop(); + if (!stack.isEmpty()) { + maxRegin = Math.max(maxRegin, (i - stack.peek() - 1) * heights[pop]); + } + } + } + stack.push(i); + } + return maxRegin; + } + } +}