优化代码结构,提高代码可读性和可维护性

This commit is contained in:
whaifree 2024-04-24 13:20:11 +08:00
parent 392278d319
commit e20cf9cea7
7 changed files with 546 additions and 0 deletions

View File

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

View File

@ -0,0 +1,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包含ii在每次循环中是最后一个的最长递增子序列的长度
*/
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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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<Integer> 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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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<Integer> 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;
}
}
}