diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T100_LeastInterval.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T100_LeastInterval.java new file mode 100644 index 0000000..51887d3 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T100_LeastInterval.java @@ -0,0 +1,91 @@ +package com.markilue.leecode.hot100; + +import java.util.Arrays; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-04-14 10:05 + *@Description: + * TODO 力扣621 任务调度器: + * 给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表。 + * 其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行,并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间,CPU 可以完成一个任务,或者处于待命状态。 + * 然而,两个 相同种类 的任务之间必须有长度为整数 n 的冷却时间,因此至少有连续 n 个单位时间内 CPU 在执行不同的任务,或者在待命状态。 + * 你需要计算完成所有任务所需要的 最短时间 。 + *@Version: 1.0 + */ +public class T100_LeastInterval { + + + /** + * 评论区贪心算法: + * 速度击败83.55% 内存击败20.41% 2ms + * @param tasks + * @param n + * @return + */ + public int leastInterval(char[] tasks, int n) { + int[] count = new int[26];//记录每个单词出现的次数 + + //遍历task记录次数 + for (char task : tasks) { + count[task - 'A']++; + } + + //排序count,找出最大的count + Arrays.sort(count); + + //那么最小的长度,就是最大的长度按间隔n来 + //因为相同元素必须有n个冷却时间,假设A出现3次,n = 2,任务要执行完,至少形成AXX AXX A序列(X看作预占位置) + int minLength = (n + 1) * (count[25] - 1) + 1;//count-1是因为最后一个不用间隔只需要+1 + + //挨个遍历,找到相同的count的就+1 + //剩余的任务次数有两种情况: + //1.与A出现次数相同,比如B任务最优插入结果是ABX ABX AB,中间还剩两个空位,当前序列长度+1 + //2.比A出现次数少,若还有X,则按序插入X位置,比如C出现两次,形成ABC ABC AB的序列 + //直到X预占位置还没插满,剩余元素逐个放入X位置就满足冷却时间至少为n + for (int i = 24; i >= 0; i--) { + if (count[i] == count[25]) minLength++; + else break; + } + + //最后一种情况:全插满了,还有多的 + //在任意插满区间(这里是ABC)后面按序插入剩余元素,比如ABCD ABCD发现D之间距离至少为n+1,肯定满足冷却条件 + //因此,当X预占位置能插满时,最短序列长度就是task.length,不能插满则取最少预占序列长度 + return Math.max(minLength, tasks.length); + + } + + + /** + * 官方最快: + * 不用排序:时间复杂度降为O(n) + * 速度击败100% 内存击败23.82% 1ms + * @param tasks + * @param n + * @return + */ + public int leastInterval1(char[] tasks, int n) { + int len = tasks.length; + int[] nums = new int[26]; + for (int i = 0; i < len; i++) { + nums[tasks[i] - 'A']++; + } + int max = 0; + for (int i = 0; i < 26; i++) { + max = Math.max(max,nums[i]); + } + int count = 0; + for (int i = 0; i < 26; i++) { + if (nums[i] == max) { + count++; + } + } + int res = (n + 1) * (max - 1) + count; + if (len > res) { + return len; + } + return res; + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T101_CountSubstrings.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T101_CountSubstrings.java new file mode 100644 index 0000000..0213be9 --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T101_CountSubstrings.java @@ -0,0 +1,92 @@ +package com.markilue.leecode.hot100; + +import org.junit.Test; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-04-14 10:42 + *@Description: + * TODO 力扣647 回文子串: + * 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。 + * 回文字符串 是正着读和倒过来读一样的字符串。 + * 子字符串 是字符串中的由连续字符组成的一个序列。 + * 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。 + *@Version: 1.0 + * + */ +public class T101_CountSubstrings { + + @Test + public void test() { + System.out.println(countSubstrings("aaa")); + } + + + /** + * 思路: + * 动态规划:判断一个子串是不是回文,如果是就+1 + * dp[i][j]表示以i结尾,以j开头的子串是不是回文 + * 速度击败21.4% 内存击败41.25% 12ms + * @param s + * @return + */ + public int countSubstrings(String s) { + + boolean[][] dp = new boolean[s.length() + 1][s.length() + 1]; + int count = 0; + dp[0][0] = true; + + + for (int i = 1; i < dp.length; i++) { + for (int j = i; j >= 1; j--) { + if (s.charAt(j - 1) == s.charAt(i - 1)) { + if (j >= i - 1) { + dp[i][j] = true; + } else { + dp[i][j] = dp[i - 1][j + 1]; + } + } + + if (dp[i][j]) count++; + } + } + + return count; + + + } + + + /** + * 官方双指针法: + * 速度击败99.95% 内存击败58.65% 1ms + * @param s + * @return + */ + public int countSubstrings1(String s) { + int result = 0; + char[] chars = s.toCharArray(); + int length = chars.length; + + for (int i = 0; i < chars.length; i++) { + result +=extend(chars,i,i,length);//以i为中心 + result+=extend(chars,i,i+1,length);//以i和i+1为中心 + } + + return result; + + } + + public int extend(char[] chars, int i, int j, int length) { + int count = 0; + while (i >= 0 && j < length && chars[i] == chars[j]) { + count++; + i--; + j++; + } + + return count; + } +} diff --git a/Leecode/src/main/java/com/markilue/leecode/hot100/T102_DailyTemperatures.java b/Leecode/src/main/java/com/markilue/leecode/hot100/T102_DailyTemperatures.java new file mode 100644 index 0000000..462452f --- /dev/null +++ b/Leecode/src/main/java/com/markilue/leecode/hot100/T102_DailyTemperatures.java @@ -0,0 +1,124 @@ +package com.markilue.leecode.hot100; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.PriorityQueue; + +/** + *@BelongsProject: Leecode + *@BelongsPackage: com.markilue.leecode.hot100 + *@Author: markilue + *@CreateTime: 2023-04-14 11:06 + *@Description: + * TODO 力扣739 每日温度: + * 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer , + * 其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。 + *@Version: 1.0 + */ +public class T102_DailyTemperatures { + + @Test + public void test() { + int[] temperatures = {73, 74, 75, 71, 69, 72, 76, 73}; + System.out.println(Arrays.toString(dailyTemperatures1(temperatures))); + } + + + /** + * 用一个单调栈记录 + * @param temperatures + * @return + */ + public int[] dailyTemperatures(int[] temperatures) { + + LinkedList stack = new LinkedList<>(); + int[] result = new int[temperatures.length]; + + for (int i = temperatures.length - 1; i >= 0; i--) { + + int index = 0; + int size = stack.size(); + while (!stack.isEmpty() && temperatures[i] > stack.peek()) { + index++; + stack.poll(); + } + result[i] = index == size ? 0 : index; + stack.offer(temperatures[i]); + + + } + + + return result; + + } + + + /** + * 使用一个优先队列进行记录对应的位置 + * 速度击败43.8% 内存击败86.5% 41ms + * @param temperatures + * @return + */ + public int[] dailyTemperatures1(int[] temperatures) { + + PriorityQueue queue = new PriorityQueue<>(new Comparator() { + @Override + public int compare(int[] o1, int[] o2) { + return o1[0] == o2[0] ? o1[1] - o2[1] : o1[0] - o2[0]; + } + }); + int[] result = new int[temperatures.length]; + + for (int i = temperatures.length - 1; i >= 0; i--) { + + while (!queue.isEmpty() && temperatures[i] >= queue.peek()[0]) { + queue.poll(); + } + if (queue.isEmpty()) { + result[i] = 0; + } else { + result[i] = queue.peek()[1] - i; + } + queue.offer(new int[]{temperatures[i], i}); + + + } + + + return result; + + } + + + /** + * 官方最快:充分利用result去寻找一个比他更大的值 + * 速度击败100% 内存击败95.63% 7ms + * @param temperatures + * @return + */ + public int[] dailyTemperatures2(int[] temperatures) { + int max = 0; + int[] ans = new int[temperatures.length]; + + for (int i = ans.length-1; i >= 0; i--) { + int currTemp = temperatures[i]; + + if (currTemp >= max) { + max = currTemp; + continue; + } + + int days = 1; + while (temperatures[i+days] <= currTemp) { + days += ans[i+days]; + } + ans[i] = days; + } + + return ans; + } +}