Leetcode刷题 2021.01.13
Leetcode1641 统计字典序元音字符串的数目
给你一个整数 n,请返回长度为 n 、仅由元音 (a, e, i, o, u) 组成且按 字典序排列 的字符串数量。
字符串 s 按 字典序排列 需要满足:对于所有有效的 i,s[i] 在字母表中的位置总是与 s[i+1] 相同或在 s[i+1] 之前。
这道题其实完全没想到用dp,就是找找规律然后做出来了,代码其实就是dp的意思(难道已经修炼到独孤九剑的无剑阶段,不知不觉间已经用上dp了,手动狗头)。
其实还是蛮好想的,和元音什么的没关系,一开始1+1+1+1+1,然后 5+4+3+2+1。这样从后往前更新的话,就相当于滚动数组了。
写完一直再想有没有通项公式,推了五分钟推不出来,就算了吧。。
class Solution {
//初始数组全为1
int[] arr = new int[]{1, 1, 1, 1, 1};
public int countVowelStrings(int n) {
//更新n - 1次
for(int i = 1; i < n; i++){
int sum = 0;
//从后往前更新
for(int j = 4; j >= 0; j--){
sum += arr[j];
arr[j] = sum;
}
}
int res = 0;
//最后算下总和
for(int i = 0; i < arr.length; i++){
res += arr[i];
}
return res;
}
}
Leetcode1647 字符频次唯一的最小删除次数
如果字符串 s 中 不存在 两个不同字符 频次 相同的情况,就称 s 是 优质字符串 。
给你一个字符串 s,返回使 s 成为 优质字符串 需要删除的 最小 字符数。
字符串中字符的 频次 是该字符在字符串中的出现次数。例如,在字符串 “aab” 中,‘a’ 的频次是 2,而 ‘b’ 的频次是 1 。
这题时间击败了98%,空间只击败20%,不知道哪里出了问题。想法还是比较简单的,先排序,用贪心,每一次保留一个唯一的数字就行。这个数字可能不连续,所以要判断一下。
class Solution {
public int minDeletions(String s) {
int[] nums = new int[26];
char[] arr = s.toCharArray();
//辅助数组统计字频
for(int i = 0; i < arr.length; i++){
nums[arr[i] - 'a']++;
}
//排序
Arrays.sort(nums);
int index = 25, res = 0, now = nums[25];
while (index >= 0 && nums[index] != 0){
//更新当前唯一的数字,
now = Math.min(now, nums[index]);
//如果不是就贪心地加上应该减掉的个数
if (now != nums[index]){
res += nums[index] - now;
}
//大于0才减一
if(now > 0) now--;
index--;
}
return res;
}
}
Leetcode1530 好叶子节点对的数量
给你二叉树的根节点 root 和一个整数 distance 。
如果二叉树中两个 叶 节点之间的 最短路径长度 小于或者等于 distance ,那它们就可以构成一组 好叶子节点对 。
返回树中 好叶子节点对的数量 。
又是二叉树,看评论里说是字节面试题。要是当时给我面这题多好。。二叉树主要还是要考虑应该返回什么,既然要考虑所有叶子节点,就在每一步左右子树返回所有叶子节点到该点的路径长度。然后在根节点上判断是否小于distance,也是自底向上的递归。想好了之后在处理根节点为null,和叶子节点返回什么就可以了。
一开始想找O(n)的,后来看题解也是O(n^2)。要是面试的时候可以和面试官交流能优化到什么时间复杂度吧。
class Solution {
//结果
int res = 0;
public int countPairs(TreeNode root, int distance) {
helper(root, distance);
return res;
}
private int[] helper(TreeNode root, int distance){
//空结点,返回一个空数组
if (root == null) return new int[]{};
//叶子节点返回1
if (root.left == null && root.right == null) return new int[]{1};
//自底向下,返回左右子树的叶子节点到root节点的距离
int[] l = helper(root.left, distance);
int[] r = helper(root.right, distance);
//O(n^2)找符合条件的叶子节点
for(int i = 0; i < l.length; i++){
for(int j = 0; j < r.length; j++){
if (l[i] + r[j] <= distance) {
res++;
}
}
}
//新建一个数组,把两个合并一起返回给再上一个节点
int[] arr = new int[l.length + r.length];
int index = 0;
for(int i = 0; i < l.length; i++){
arr[index++] = l[i] + 1;
}
for(int i = 0; i < r.length; i++){
arr[index++] = r[i] + 1;
}
return arr;
}
}