题目描述
- 有字符串s和t,可以对字符串s进行两种操作:1. 增加mhy子序列, 2.删除mhy子序列。判断字符串s经过任意次操作后,能否变为t
- 题目来源: 3月19日米哈游的前端笔试题
思路
- 将s中m、h、y出现的次数减去这三者中次数最小的那一个。t同样操作
- s可以通过新增和删除字符串mhy来变成t,那么s中得到smap,把mhy的数量减去最少的数量,即mhy成对的增加和删除,这样的话,再比较,因为新增和删除对源字符串s没有任何影响。所以t中也是
- 比较s和t剩下的m、h、y的出现次数是否相等。不相等的话就返回No
- 再比较s和t中不能成对增加和删除的mhy出现次数是否相等,这是无法匹配的m,h,y。
- 这里为什么不对mhy的顺序做要求呢?
- 因为ymh和mhy是一样的,因为ymh可以通过在前面增加mh和后面增加y再删除一个mhy,既可以得到mhy
- 所以最后剩下的mhy只需要数量相等即可(mhy的顺序是不作要求的,可以任意出现,反正它最后都可以通过删除和添加得到)
- 最后删除掉s和t中的mhy,比较剩下的字符串是否相等。
- 虽然mhy不要求顺序。但是其它字符比如a,b这种就要求按顺序出现。也就是说不能像mhy一样,只比较mhy出现的次数。还需确保a和b的顺序一样
- 把字符中要求无序的删除掉,剩下的就是要求有序的,直接判断是否相等就可以
- 也就是说最后把s和t中的mhy删除掉,再比较二者是否相等
代码
let myfun = function(s, t) {
let sMap = new Map();
for(let i = 0; i < s.length; i++) {
sMap.set(s[i], sMap.has(s[i]) ? sMap.get(s[i]) + 1 : 1);
}
let tMap = new Map();
for(let i = 0; i < t.length; i++) {
tMap.set(t[i], tMap.has(t[i]) ? tMap.get(t[i]) + 1 : 1);
}
let sm = sMap.get("m"), sh = sMap.get("h"), sy = sMap.get("y");
let smini = Math.min(sm, sh, sy);
sm -= smini;
sh -= smini;
sy -= smini;
let tm = tMap.get("m"), th = tMap.get("h"), ty = tMap.get("y");
let tmini = Math.min(tm, th, ty);
tm -= tmini;
th -= tmini;
ty -= tmini;
if(sm !== tm || sh !== th || sy !== ty) return "No";
let sArr = s.split("");
let tArr = t.split("");
let left = 0, right = 0;
while(right < sArr.length) {
if(!['m', 'h', 'y'].includes(sArr[right])) {
sArr[left] = sArr[right];
left++;
}
right++;
}
sArr.length = left;
left = 0; right = 0;
while(right < tArr.length) {
if(!['m', 'h', 'y'].includes(tArr[right])) {
tArr[left] = tArr[right];
left++;
}
right++;
}
tArr.length = left;
if(sArr.join("") === tArr.join("")) return "Yes";
else return "No";
}
let s = "mhybd";
let t = "bd";
console.log(myfun(s, t));
心得
- 做题之前需要仔细想想题目的解法。不能通过全部案例是有一定原因的
- 这里判断剩下的字符是否属于mhy中的一种时,使用数组的
includes
函数
- 加油!