leecode更新
This commit is contained in:
parent
89885c0e53
commit
4d659677a1
|
|
@ -3,6 +3,7 @@ package com.markilue.leecode.hot100;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.omg.CORBA.PUBLIC_MEMBER;
|
import org.omg.CORBA.PUBLIC_MEMBER;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue