diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T55_LRUCache.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T55_LRUCache.java index 0d70d80..07f6edc 100644 --- a/Leecode/src/main/java/com/markilue/leecode/hot100/T55_LRUCache.java +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T55_LRUCache.java @@ -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; diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T64_CanFinish.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T64_CanFinish.java new file mode 100644 index 0000000..061bb45 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T64_CanFinish.java @@ -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 数字,需要在他后面学的东西 + * 有问题 当处于一个循环的时候,后面没有办法再重新监测前面的内容 + * 过了42个用例 + * @param numCourses + * @param prerequisites + * @return + */ + public boolean canFinish(int numCourses, int[][] prerequisites) { + + HashMap> map = new HashMap>(); +// HashSet set1 = new HashSet<>(); + + + for (int[] prerequisite : prerequisites) { +// set1.add(prerequisite[0]); +// set1.add(prerequisite[1]); + if (!map.containsKey(prerequisite[1])) { + HashSet set = new HashSet<>(); + set.add(prerequisite[0]); + map.put(prerequisite[1], set); + }else { + HashSet 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()> edges; + int[] visited; + boolean valid = true; + + public boolean canFinish1(int numCourses, int[][] prerequisites) { + edges = new ArrayList>(); + for (int i = 0; i < numCourses; ++i) { + edges.add(new ArrayList()); + } + 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; + } + + + + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T66_FindKthLargest.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T66_FindKthLargest.java new file mode 100644 index 0000000..8702ac6 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T66_FindKthLargest.java @@ -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; + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T67_MaximalSquare.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T67_MaximalSquare.java new file mode 100644 index 0000000..14d4901 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T67_MaximalSquare.java @@ -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; + } + +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T68_InvertTree.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T68_InvertTree.java new file mode 100644 index 0000000..bc42ab4 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T68_InvertTree.java @@ -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; + + } +}