leecode更新

This commit is contained in:
markilue 2023-03-06 15:59:27 +08:00
parent f5a1d35d7c
commit b5dc4022bc
5 changed files with 428 additions and 0 deletions

View File

@ -0,0 +1,124 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
import java.util.Arrays;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-06 10:04
*@Description:
* TODO 力扣34题 在排序数组中查找元素的第一个和最后一个位置:
* 给你一个按照非递减顺序排列的整数数组 nums和一个目标值 target请你找出给定目标值在数组中的开始位置和结束位置
* 如果数组中不存在目标值 target返回 [-1, -1]
* 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题
*@Version: 1.0
*/
public class T21_SearchRange {
@Test
public void test() {
int[] nums = {8, 8, 8, 8, 8, 8};
int target = 8;
System.out.println(Arrays.toString(searchRange(nums, target)));
}
@Test
public void test1() {
int[] nums = {5, 7, 7, 8, 8, 10};
int target = 6;
System.out.println(Arrays.toString(searchRange(nums, target)));
}
@Test
public void test2() {
int[] nums = {2, 2};
int target = 3;
System.out.println(Arrays.toString(searchRange(nums, target)));
}
/**
* 思路:本质上就是二分查找查找多个相同值的位置
* 速度击败100% 内存击败30.39% 0ms
* @param nums
* @param target
* @return
*/
public int[] searchRange(int[] nums, int target) {
if (nums.length == 0) {
return new int[]{-1, -1};
}
int start = 0;
int end = nums.length - 1;
int mid = 0;
while (start <= end) {
mid = start + ((end - start) >> 1);
if (nums[mid] < target) {
start = mid + 1;
} else if (nums[mid] > target) {
end = mid - 1;
} else {
//找到了
break;
}
}
if (start > end) {
return new int[]{-1, -1};//没找到
} else {
int left = mid;
int right = mid;
while (left > 0 && nums[left - 1] == nums[mid]) {
left--;
}
while (right < nums.length - 1 && nums[right + 1] == nums[mid]) {
right++;
}
return new int[]{left, right};
}
}
/**
* 评论区的简洁写法
* @param nums
* @param target
* @return
*/
public int[] searchRange1(int[] nums, int target) {
if (nums.length == 0) {
return new int[]{-1, -1};
}
int start = 0;
int end = nums.length - 1;
int mid = 0;
while (start <= end) {
mid = start + ((end - start) >> 1);
if (nums[mid] == target) {
int left = mid;
int right = mid;
while (left > 0 && nums[left - 1] == nums[mid]) ++left;
while (right < nums.length - 1 && nums[right + 1] == nums[mid]) --right;
return new int[]{left, right};
} else if (nums[mid] < target) {
start = mid + 1;
}else {
end=mid-1;
}
}
return new int[]{-1, -1};//没找到
}
}

View File

@ -0,0 +1,64 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-06 10:29
*@Description:
* TODO 力扣39题 组合总和:
* 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target 找出 candidates 中可以使数字和为目标数 target 所有 不同组合 并以列表形式返回你可以按 任意顺序 返回这些组合
* candidates 中的 同一个 数字可以 无限制重复被选取 如果至少一个数字的被选数量不同则两种组合是不同的
* 对于给定的输入保证和为 target 的不同组合数少于 150
*@Version: 1.0
*/
public class T22_CombinationSum {
@Test
public void test() {
int[] candidates = {2, 3, 6, 7};
int target = 7;
System.out.println(combinationSum(candidates, target));
}
List<Integer> cur = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
/**
* 回溯注意树枝去重和树层去重方式
* 速度击败75.99% 内存击败83.16% 可能数sum没有使用回溯的方式写稍微有点慢
* @param candidates
* @param target
* @return
*/
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
backtracking(candidates, target, 0,0);
return result;
}
public void backtracking(int[] candidates, int target, int sum,int start) {
if (sum == target) {
result.add(new ArrayList<>(cur));
return;
}
for (int i = start; i < candidates.length && sum + candidates[i] <= target; i++) {//加上start树枝去重
//从这个杜绝sum>target
if (i > 0 && candidates[i] == candidates[i - 1]) {
continue;//树层去重
}
cur.add(candidates[i]);
backtracking(candidates, target, sum + candidates[i],i);
cur.remove(cur.size() - 1);
}
}
}

View File

@ -0,0 +1,112 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-06 10:48
*@Description:
* TODO 力扣42题 接雨水:
* 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图计算按此排列的柱子下雨之后能接多少雨水
*@Version: 1.0
*/
public class T23_Trap {
@Test
public void test() {
int[] height = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1};
System.out.println(trap2(height));
}
/**
* 思路:先尝试动态规划法
* 分别从两边进行动态规划分别寻找考虑两边的最大值
* 速度击败78.21% 内存击败82.6% 1ms
* @param height
* @return
*/
public int trap(int[] height) {
int[] left = new int[height.length];
left[0] = height[0];
for (int i = 1; i < height.length; i++) {
left[i] = Math.max(height[i], left[i - 1]);//本质上就是记录从左看的最大值
}
int[] right = new int[height.length];//记录从右看的最大
right[right.length - 1] = height[height.length - 1];
for (int i = height.length - 2; i >= 0; i--) {
right[i] = Math.max(height[i], right[i + 1]);
}
//通过分别从左和右看的最大值来判断当前位置所接的雨水量
int sum = 0;
for (int i = 0; i < right.length; i++) {
//当前位置的雨水量 取决于 从左和右看中的最小值
sum += Math.min(left[i], right[i]) - height[i];
}
return sum;
}
/**
* 思路:先尝试双指针法
* 分别从两边进行规划指针谁小谁往对方方向走
* TODO 本人的正确应该是纯属凑巧(不可借鉴)
* 速度击败78.21% 内存击败47.5% 1ms
* @param height
* @return
*/
public int trap1(int[] height) {
int left = 0;
int right = height.length - 1;
int leftMax = height[left];
int rightMax = height[right];
int sum = 0;
for (int i = 0; i < height.length; i++) {
leftMax = Math.max(height[left], leftMax);
rightMax = Math.max(height[right], rightMax);
//当前位置的雨水量取决于左右两边最小的那个
sum += Math.min(leftMax, rightMax) - height[i];
if (leftMax < rightMax) {
left++;
} else {
right--;
}
}
return sum;
}
/**
* 官方的左右指针法:浅优化(每次循环少判断一次)
* @param height
* @return
*/
public int trap2(int[] height) {
int ans = 0;
int left = 0, right = height.length - 1;
int leftMax = 0, rightMax = 0;
while (left < right) {
leftMax = Math.max(leftMax, height[left]);
rightMax = Math.max(rightMax, height[right]);
if (height[left] < height[right]) {
//如果左边的小那么左边的水一定可以蓄起来那么就计算左边的水
ans += leftMax - height[left];
++left;
} else {
ans += rightMax - height[right];
--right;
}
}
return ans;
}
}

View File

@ -0,0 +1,60 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-06 11:34
*@Description:
* TODO 力扣46题 全排列:
* 给定一个不含重复数字的数组 nums 返回其 所有可能的全排列 你可以 按任意顺序 返回答案
*@Version: 1.0
*/
public class T24_Permute {
@Test
public void test() {
int[] nums = {1, 2, 3};
System.out.println(permute(nums));
}
List<Integer> cur = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
/**
* 核心就是需要知道哪些位置用过哪些位置没有用过
* 速度击败100% 内存击败69.64% 1ms
* @param nums
* @return
*/
public List<List<Integer>> permute(int[] nums) {
boolean[] used = new boolean[nums.length];
backtracking(nums, used);
return result;
}
public void backtracking(int[] nums, boolean[] used) {
if (cur.size() == nums.length) {
result.add(new ArrayList<>(cur));
return;
}
for (int i = 0; i < nums.length; i++) {
if (!used[i]) {
used[i] = true;
cur.add(nums[i]);
backtracking(nums, used);
used[i] = false;
cur.remove(cur.size() - 1);
}
}
}
}

View File

@ -0,0 +1,68 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
import java.util.Arrays;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-06 11:42
*@Description:
* TODO 力扣48题 旋转图像:
* 给定一个 n × n 的二维矩阵 matrix 表示一个图像请你将图像顺时针旋转 90
* 你必须在 原地 旋转图像这意味着你需要直接修改输入的二维矩阵请不要 使用另一个矩阵来旋转图像
*@Version: 1.0
*/
public class T25_Rotate {
@Test
public void test() {
int[][] matrix = {{5,1,9,11}, {2,4,8,10}, {13,3,6,7},{15,14,12,16}};
rotate(matrix);
for (int[] ints : matrix) {
System.out.println(Arrays.toString(ints));
}
}
/**
* 思路:这题跟螺旋数组那题很像:都是寻找循环不变量
* 速度击败100% 内存击败67.68% 0ms
* @param matrix
*/
public void rotate(int[][] matrix) {
//i为层
for (int i = 0; i < matrix.length / 2; i++) {
int row = i;//row方向移动
int col = i;//col方向移动
int row1 = i;//需要复制的row方向
int col1 = matrix.length - 1 - i;//需要复制的col方向
int[] last = new int[matrix.length - 1 - i];//记录上次的位置
for (int index = 0; col < matrix.length - 1 - i; col++, row1++) {
last[index++] = matrix[row1][col1];
matrix[row1][col1] = matrix[row][col];
}
for (int index = 0; col1 > i; col1--) {
int temp = matrix[row1][col1];
matrix[row1][col1] = last[index];
last[index++] = temp;
}
for (int index = 0; row1 > i; row1--) {
int temp = matrix[row1][col1];
matrix[row1][col1] = last[index];
last[index++] = temp;
}
for (int index = 0; col1 < matrix.length - 1 - i; col1++) {
matrix[row1][col1] = last[index++];
}
}
}
}