每日一题 -- leetCode1433

117 阅读4分钟

image.png 「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战

前言

每日一题,轻松解题

每日一题为刷题系列 每日刷一题LeetCode题,并且对题目进行分析,分享思路。

正文

:检查一个字符串是否可以打破另一个字符串

难度:中等

题目要求:

给你两个字符串 s1 和 s2 ,它们长度相等,请你检查是否存在一个 s1  的排列可以打破 s2 的一个排列,或者是否存在一个 s2 的排列可以打破 s1 的一个排列。

ps: 字符串 x 可以打破字符串 y (两者长度都为 n )需满足对于所有 i(在 0 到 n - 1 之间)都有 x[i] >= y[i](字典序意义下的顺序)。

分析题目:

两个一样长的字符串,改变顺序后,有一个字符串可以打破另一个字符串,“打破”在上面ps中解释了

举个例子

s1 = 'cba'  /  s2 = 'bdf'   这时候s1和s2无法相互打破,但是改变顺序后  
// 改变后
s1 = 'abc'  /  s2 = 'bdf'   这时候s2的每一个字符都大于等于s1,就表示s2可以打破s1  
// 这样改也行
s1 = 'cba'  /  s2 = 'fdb'   这时候s2的每一个字符都大于等于s1,就表示s2可以打破s1  

只要其中的每一项都大于另一个字符串的对应每一项就成立,

:解题

理清思路:

这种题目属于需要一个成立与否的结果,而没有一个固定解,所以我们没办法用运算得出结果,因为结果是多样的,这时候还是用到贪心算法。

分析:
先将s1中的字符出现的次数全部记录下来
分两次遍历s2,分别找到离s2[i]字典顺序最近的s1中字母(大于等于、小于等于两个方向);
如果某一侧所有arr中元素都为0,则说明没法达到条件。

编辑代码:

1.首先定义一个函数,传入两个相同长度的字符串。将s1中的字符出现的次数全部记录下来

function strBreak (s1, s2)  {
    let arr = new Array(26).fill(0);
    let str = 'abcdefghijklmnopqrstuvwxyz';
    for (let i of s1) {
        let index = str.indexOf(i);
        arr[index] += 1;
    }
    console.log(arr);
};
  • 定义一个数组arr 存放26个0,对应26个字母
  • 定义一个str字符串为26个字母,用于判断s1和s2各个字母的个数
  • for循环遍历s1,使用indexOf获取对应字母的索引,并且让数组arr中对应字母的数字加一,

扩展:

arr.fill()  //用一个固定值填充一个数组中从起始索引到终止索引内的全部元素
arr = [0,0,.....,0]   //26个0
arr.fill(1)  // 用1替换arr中全部内容
arr.fill(1,1,2)  //第二个1 是从索引1 开始 到索引2 结束  也就是把arr[1]---arr[2]替换成1  不包括arr[2]

str = '123'
str.indexOf(1)   // 返回1 在str 中的索引,也就是0 
这个for循环可以获得什么 -- 举个例子
let s1 = 'abcd'
for  ....  //for循环上面有,不写一遍了
console.log(arr) -->
[
  1, 1, 1, 1, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0,
  0, 0
]        //最后得到的arr
这样就知道s1中包含什么字母,并且知道各有几个,存放在arr中

2.分两次遍历s2,分别找到离s2[i]字典顺序最近的s1中字母(大于等于、小于等于两个方向)

    let arr1 = arr.slice();
    let c1 = true;
    for (let i of s2) {
        // s1 >= s2
        let startIndex = str.indexOf(i);
        let j = startIndex;
        for (; j < arr1.length; j++) {
            if (arr1[j] > 0) {
                arr1[j] -= 1;
                break;
            }
        }
        if (j === arr1.length) {
            c1 = false;
            break;
        }
    }
    let c2 = true;
    for (let i of s2) {
        // s1 <= s2
        let endIndex = str.indexOf(i);
        let j = endIndex;
        for (; j >= 0; j--) {
            if (arr[j] > 0) {
                arr[j] -= 1;
                break;
            }
        }
        if (j === -1) {
            c2 = false;
            break;
        }
    }
    return c1 || c2;
  • slice()的作用,复制一份arr给arr1
  • 定义一个值,来存放是否存在s1打破s2字符串
  • 循环判断是否s1总是大于s2,是则返回true,不是则返回false

3.合并代码,就完成了

总结

无论做什么分析最重要,其中我们分析了题目,分析了解题思路,其实在分析完解题思路后,代码其实就是很简单的事情了,养成习惯,无论做什么之前,都要进行分析,这样有助于你更快更好的完成这件事。