944. 删列造序
2022.5.12 每日一题
题目描述
给你由 n 个小写字母字符串组成的数组 strs,其中每个字符串长度相等。
这些字符串可以每个一行,排成一个网格。例如,strs = [“abc”, “bce”, “cae”] 可以排列为:
abc
bce
cae
你需要找出并删除 不是按字典序升序排列的 列。在上面的例子(下标从 0 开始)中,列 0(‘a’, ‘b’, ‘c’)和列 2(‘c’, ‘e’, ‘e’)都是按升序排列的,而列 1(‘b’, ‘c’, ‘a’)不是,所以要删除列 1 。
返回你需要删除的列数。
示例 1:
输入:strs = [“cba”,“daf”,“ghi”]
输出:1
解释:网格示意如下:
cba
daf
ghi
列 0 和列 2 按升序排列,但列 1 不是,所以只需要删除列 1 。
示例 2:
输入:strs = [“a”,“b”]
输出:0
解释:网格示意如下:
a
b
只有列 0 这一列,且已经按升序排列,所以不用删除任何列。
示例 3:
输入:strs = [“zyx”,“wvu”,“tsr”]
输出:3
解释:网格示意如下:
zyx
wvu
tsr
所有 3 列都是非升序排列的,所以都要删除。
提示:
n == strs.length
1 <= n <= 100
1 <= strs[i].length <= 1000
strs[i] 由小写英文字母组成
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/delete-columns-to-make-sorted
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
简单模拟
class Solution {
public int minDeletionSize(String[] strs) {
//直接按列遍历判断就行了
int n = strs.length;
int l = strs[0].length();
int del = 0;
for(int j = 0; j < l; j++){
char pre = strs[0].charAt(j);
for(int i = 1; i < n; i++){
if(strs[i].charAt(j) < pre){
del++;
break;
}
pre = strs[i].charAt(j);
}
}
return del;
}
}
面试题 01.05. 一次编辑
2022.5.13 每日一题
题目描述
字符串有三种编辑操作:插入一个字符、删除一个字符或者替换一个字符。 给定两个字符串,编写一个函数判定它们是否只需要一次(或者零次)编辑。
示例 1:
输入:
first = “pale”
second = “ple”
输出: True
示例 2:
输入:
first = “pales”
second = “pal”
输出: False
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/one-away-lcci
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
我的思路,从左到右遍历找第一个不匹配的字符,从右到左再找一遍,如果两个找到的位置相同,那么说明可以一次编辑,否则不行
好像题解都是双指针,从一个方向找的
class Solution {
public boolean oneEditAway(String first, String second) {
//先看长度,如果差一个就是添加或者删除,如果长度相同就是修改
int l1 = first.length();
int l2 = second.length();
if(Math.abs(l1- l2) > 1)
return false;
//保证first的长度是长的
if(l2 > l1){
String temp = first;
first = second;
second = temp;
int t = l1;
l1 = l2;
l2 = t;
}
int left = 0;
int right = l1 - 1;
//从左到右找第一个不匹配的字符
while(left < l1 && left < l2 && first.charAt(left) == second.charAt(left)){
left++;
}
//从右到左找第一个不匹配的字符
while(right >= 0 && l2 - (l1 - right) >= 0 && first.charAt(right) == second.charAt(l2 - (l1 - right))){
right--;
}
//如果左边找到的下标大于等于右边找到的下标,说明仅有一个不同或者都相同
if(left >= right)
return true;
else
return false;
}
}
691. 贴纸拼词
2022.5.14 每日一题
题目描述
我们有 n 种不同的贴纸。每个贴纸上都有一个小写的英文单词。
您想要拼写出给定的字符串 target ,方法是从收集的贴纸中切割单个字母并重新排列它们。如果你愿意,你可以多次使用每个贴纸,每个贴纸的数量是无限的。
返回你需要拼出 target 的最小贴纸数量。如果任务不可能,则返回 -1 。
注意:在所有的测试用例中,所有的单词都是从 1000 个最常见的美国英语单词中随机选择的,并且 target 被选择为两个随机单词的连接。
示例 1:
输入: stickers = [“with”,“example”,“science”], target = “thehat”
输出:3
解释:
我们可以使用 2 个 “with” 贴纸,和 1 个 “example” 贴纸。
把贴纸上的字母剪下来并重新排列后,就可以形成目标 “thehat“ 了。
此外,这是形成目标字符串所需的最小贴纸数量。
示例 2:
输入:stickers = [“notice”,“possible”], target = “basicbasic”
输出:-1
解释:我们不能通过剪切给定贴纸的字母来形成目标“basicbasic”。
提示:
n == stickers.length
1 <= n <= 50
1 <= stickers[i].length <= 10
1 <= target <= 15
stickers[i] 和 target 由小写英文单词组成
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/stickers-to-spell-word
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
第一时间看到这个题感觉是动态规划,但是想到的是统计target中每一个字符的数量,用一个数组统计,然后dfs看达到每个状态,状态也就是这个数组,需要的最少单词。然后发现统计这样的状态还需要写个类,重写equals,非常麻烦,就感觉不对
然后看题解才发现是状态压缩,因为target长度最长也就是15,还没有26个字母长,所以直接状态压缩,统计每个状态所需要的最少单词来进行动态规划。
遍历stickers中所有单词,如果这个单词中有target中出现的单词,那么就将状态改变,继续递归
这样一个记忆化搜索加状压dp就完成了
应该能自己做出来的。。
class Solution {
public int minStickers(String[] stickers, String target) {
//感觉像是完全背包问题,即每个物品可以用多次
//递归的去遍历所有单词,然后从target中去除存在的字母
//去除的时候可以选一次这个单词也可以选多次
int l = target.length();
//memo表示达到这个状态最少需要几个单词
int[] memo = new int[1 << l];
Arrays.fill(memo, -1);
memo[0] = 0;
int res = dfs(target, stickers, memo, (1 << l) - 1);
return res <= l ? res : -1;
}
public int dfs(String target, String[] stickers, int[] memo, int mask){
int l = target.length();
//如果当前状态是没有被赋值的,那么进行处理
if(memo[mask] < 0){
//先将res赋予不可能的最大值(最大值就是每个字符都由一个单词贡献,即 l)
int res = l + 1;
//遍历所有单词,看哪个构成最小
for(String s : stickers){
int init = mask;
int[] count = new int[26];
for(char c : s.toCharArray()){
count[c - 'a']++;
}
//查看这个单词在target中有几个字符出现,将这些字符从mask中去除
for(int i = 0; i < l; i++){
char c = target.charAt(i);
if(((mask >> i) & 1) == 1 && count[c - 'a'] > 0){
count[c - 'a']--;
init ^= 1 << i;
}
}
//如果这个单词能构成target,那么继续递归
if(init < mask){
res = Math.min(res, dfs(target, stickers, memo, init) + 1);
}
}
memo[mask] = res;
}
return memo[mask];
}
}