leecode更新
This commit is contained in:
parent
f5a1d35d7c
commit
b5dc4022bc
|
|
@ -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};//没找到
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue