leecode更新

This commit is contained in:
markilue 2023-03-16 13:29:26 +08:00
parent 89885c0e53
commit 4d659677a1
5 changed files with 429 additions and 0 deletions

View File

@ -3,6 +3,7 @@ package com.markilue.leecode.hot100;
import org.junit.Test;
import org.omg.CORBA.PUBLIC_MEMBER;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

View File

@ -0,0 +1,150 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
import java.util.*;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-16 09:54
*@Description:
* TODO 力扣207题 课程表:
* 你这个学期必须选修 numCourses 门课程记为 0 numCourses - 1
* 在选修某些课程之前需要一些先修课程 先修课程按数组 prerequisites 给出其中 prerequisites[i] = [ai, bi] 表示如果要学习课程 ai 必须 先学习课程 bi
* 例如先修课程对 [0, 1] 表示想要学习课程 0 你需要先完成课程 1
* 请你判断是否可能完成所有课程的学习如果可以返回 true 否则返回 false
*@Version: 1.0
*/
public class T64_CanFinish {
@Test
public void test(){
int numCourses = 3;
int[][] prerequisites = {{1,0},{0,2},{2,1}};
System.out.println(canFinish(numCourses,prerequisites));
}
/**
* 思路:使用一个Map<Integer,List> 数字需要在他后面学的东西
* 有问题 当处于一个循环的时候后面没有办法再重新监测前面的内容
* 过了42个用例
* @param numCourses
* @param prerequisites
* @return
*/
public boolean canFinish(int numCourses, int[][] prerequisites) {
HashMap<Integer, HashSet<Integer>> map = new HashMap<Integer, HashSet<Integer>>();
// HashSet<Integer> set1 = new HashSet<>();
for (int[] prerequisite : prerequisites) {
// set1.add(prerequisite[0]);
// set1.add(prerequisite[1]);
if (!map.containsKey(prerequisite[1])) {
HashSet<Integer> set = new HashSet<>();
set.add(prerequisite[0]);
map.put(prerequisite[1], set);
}else {
HashSet<Integer> set = map.get(prerequisite[1]);
set.add(prerequisite[0]);
}
if(map.containsKey(prerequisite[0])){
//看看必须在他后面完成的里面有没有prerequisite[1]
if(map.get(prerequisite[0]).contains(prerequisite[1])){//1必须在0之前完成
return false;
}
}
}
// if(set1.size()<numCourses){//课程数不够
// return false;
// }
return true;
}
/**
* 官方深度优先算法:
* 时间复杂度O(N+M)
* 速度击败92..85% 内存击败38.86% 3ms
*/
List<List<Integer>> edges;
int[] visited;
boolean valid = true;
public boolean canFinish1(int numCourses, int[][] prerequisites) {
edges = new ArrayList<List<Integer>>();
for (int i = 0; i < numCourses; ++i) {
edges.add(new ArrayList<Integer>());
}
visited = new int[numCourses];
for (int[] info : prerequisites) {
edges.get(info[1]).add(info[0]);
}
for (int i = 0; i < numCourses && valid; ++i) {
if (visited[i] == 0) {
dfs(i);
}
}
return valid;
}
public void dfs(int u) {
visited[u] = 1;//搜索中
for (int v: edges.get(u)) {
if (visited[v] == 0) {
dfs(v);
if (!valid) {
return;
}
} else if (visited[v] == 1) {//肯定要在当前节点之后进行遍历到才行
valid = false;
return;
}
}
visited[u] = 2;//已完成
}
/**
* 官方最快:
* 速度击败100% 内存击败93.16% 1ms
* @param numCourses
* @param prerequisites
* @return
*/
public boolean canFinish2(int numCourses, int[][] prerequisites) {
int len = prerequisites.length;
if (len == 0) return true;
int[] pointer = new int[numCourses];// 每个课程被指向的次数
for (int[] p : prerequisites) ++pointer[p[1]];
boolean[] removed = new boolean[len];// 标记prerequisites中的元素是否被移除
int remove = 0;// 移除的元素数量
while (remove < len) {
int currRemove = 0;// 本轮移除的元素数量
for (int i = 0; i < len; i++) {
if (removed[i]) continue;// 被移除的元素跳过
int[] p = prerequisites[i];
if (pointer[p[0]] == 0) {// 如果被安全课程指向
--pointer[p[1]];// 被指向次数减1
removed[i] = true;
++currRemove;
}
}
if (currRemove == 0) return false;// 如果一轮跑下来一个元素都没移除则没必要进行下一轮
remove += currRemove;
}
return true;
}
}

View File

@ -0,0 +1,124 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-16 11:09
*@Description:
* TODO 力扣215 数组中的第K个最大元素:
* 给定整数数组 nums 和整数 k请返回数组中第 k 个最大的元素
* 请注意你需要找的是数组排序后的第 k 个最大的元素而不是第 k 个不同的元素
* 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题
*@Version: 1.0
*/
public class T66_FindKthLargest {
@Test
public void test() {
int[] nums = {3, 2, 1, 5, 6, 4};
int k = 2;
System.out.println(findKthLargest(nums, k));
}
@Test
public void test1() {
int[] nums = {2, 1};
int k = 1;
System.out.println(findKthLargest(nums, k));
}
/**
* 快排的思路:通过partition找到对应的位置然后抛弃另一半
* 速度击败64.38% 内存击败78.98% 14ms
* @param nums
* @param k
* @return
*/
public int findKthLargest(int[] nums, int k) {
return partition(nums, 0, nums.length - 1, nums.length - k);
}
public int partition(int[] nums, int start, int end, int k) {
if (start == end) {
return nums[start];
}
int index = sort(nums, start, end);
if (index < k) return partition(nums, index + 1, end, k);
else if (index > k) return partition(nums, start, index - 1, k);
else return nums[index];
}
public int sort(int[] nums, int start, int end) {
int left = start;
int right = end + 1;
int compare = nums[start];
while (left <= right) {
while (++left < nums.length && nums[left] < compare) {
continue;
}
while (--right >= 0 && nums[right] > compare) {
continue;
}
if (left > right) break;
swap(nums, left, right);
}
swap(nums, start, right);
return right;
}
public void swap(int[] nums, int left, int right) {
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
}
/**
* 官方最快:记录每个数出现的次数然后进行相减当k<=0就是所需要的那个数
* 速度击败100% 内存击败5% 1ms
* @param nums
* @param k
* @return
*/
public int findKthLargest1(int[] nums, int k) {
int max = nums[0];
int min = nums[0];
//寻找最大值和最小值
for (int num : nums) {
if (max < num) {
max = num;
}
if (min > num) {
min = num;
}
}
int[] allnums = new int[max - min + 1];
for (int num : nums) {
allnums[num - min]++;//记录每个数出现的次数
}
for (int i = max - min; i >= 0; i--) {
k = k - allnums[i];//次数相减
if (k <= 0) {
return i + min;
}
}
return -1;
}
}

View File

@ -0,0 +1,120 @@
package com.markilue.leecode.hot100;
import org.junit.Test;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-16 11:48
*@Description:
* TODO 力扣221 最大正方形:
* 在一个由 '0' '1' 组成的二维矩阵内找到只包含 '1' 的最大正方形并返回其面积
*@Version: 1.0
*/
public class T67_MaximalSquare {
@Test
public void test(){
char[][] matrix={
{'1', '1', '1', '1', '0'},
{'1', '1', '1', '1', '0'},
{'1', '1', '1', '1', '1'},
{'1', '1', '1', '1', '1'},
{'0', '0', '1', '1', '1'}
};
maximalSquare1(matrix);
}
/**
* 思路:动态规划法:
* TODO DP五部曲:
* 1.dp定义: dp[i][j]表示位于nums[i][j]位置的最大正方形面积
* 2.dp状态转移方程:
* if(nums[i][j]==1){
* if(dp[i-1][j]!=0&&dp[i][j-1]==dp[i-1][j]){
* dp[i][j]=(sqrt(dp[i-1][j-1])+1)*
* }
* }
* 3.dp初始化:
* 4.dp遍历顺序:
* 5.dp举例推导:
* 通过63个用例test用例无法过
* @param matrix
* @return
*/
public int maximalSquare(char[][] matrix) {
int[][] dp = new int[matrix.length][matrix[0].length];
int result = 0;
for (int i = 0; i < dp.length; i++) {
if (matrix[i][0] == '1') {
dp[i][0] =1;
result=1;
}
}
for (int i = 0; i < dp[0].length; i++) {
if (matrix[0][i] == '1') {
dp[0][i] =1;
result=1;
}
}
for (int i = 1; i < matrix.length; i++) {
for (int j = 1; j < matrix[0].length; j++) {
if (matrix[i][j] == '1') {
if (dp[i - 1][j] != 0 && dp[i][j - 1] == dp[i - 1][j]) {
dp[i][j] = (int) Math.pow((Math.sqrt(dp[i - 1][j - 1]) + 1), 2);
} else {
dp[i][j] = 1;
}
}
if (result < dp[i][j]) result = dp[i][j];
}
}
return result;
}
/**
* 官方动态规划法:
* TODO
* DP定义:我们用 dp(i,j) 表示以 (i,j) 为右下角且只包含 1 的正方形的边长最大值
* 如果我们能计算出所有 dp(i,j) 的值那么其中的最大值即为矩阵中只包含 1的正方形的边长最大值其平方即为最大正方形的面积
* 速度击败89.83% 内存击败34.75% 6ms
* @param matrix
* @return
*/
public int maximalSquare1(char[][] matrix) {
int maxSide = 0;
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return maxSide;
}
int rows = matrix.length, columns = matrix[0].length;
int[][] dp = new int[rows][columns];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (matrix[i][j] == '1') {
if (i == 0 || j == 0) {
dp[i][j] = 1;
} else {
dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
}
maxSide = Math.max(maxSide, dp[i][j]);
}
}
}
int maxSquare = maxSide * maxSide;
return maxSquare;
}
}

View File

@ -0,0 +1,34 @@
package com.markilue.leecode.hot100;
import com.markilue.leecode.tree.TreeNode;
/**
*@BelongsProject: Leecode
*@BelongsPackage: com.markilue.leecode.hot100
*@Author: markilue
*@CreateTime: 2023-03-16 12:42
*@Description:
* TODO 力扣226题 翻转二叉树:
* 给你一棵二叉树的根节点 root 翻转这棵二叉树并返回其根节点
*@Version: 1.0
*/
public class T68_InvertTree {
/**
* 优先深度或者优先广度都行
* 速度击败100% 内存击败55.93%
* @param root
* @return
*/
public TreeNode invertTree(TreeNode root) {
if(root==null)return null;
TreeNode temp=root.left;
root.left=invertTree(root.right);
root.right=invertTree(temp);
return root;
}
}