1763. 最长的美好子字符串

876 阅读3分钟

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

每日刷题第36天 2021.02.01

1763.最长的美好子字符串

题目

  • 当一个字符串 s 包含的每一种字母的大写和小写形式 同时 出现在 s 中,就称这个字符串 s 是 美好 字符串。比方说,"abABB" 是美好字符串,因为 'A' 和 'a' 同时出现了,且 'B' 和 'b' 也同时出现了。然而,"abA" 不是美好字符串因为 'b' 出现了,而 'B' 没有出现。
  • 给你一个字符串 s ,请你返回 s 最长的 美好子字符串 。如果有多个答案,请你返回 最早 出现的一个。如果不存在美好子字符串,请你返回一个空字符串。

示例

  • 示例1
输入:s = "YazaAay"
输出:"aAa"
解释:"aAa" 是一个美好字符串,因为这个子串中仅含一种字母,其小写形式 'a' 和大写形式 'A' 也同时出现了。
"aAa" 是最长的美好子字符串。
  • 示例2
输入: s = "Bb"
输出: "Bb"
解释: "Bb" 是美好字符串,因为 'B''b' 都出现了。整个字符串也是原字符串的子字符串。
  • 示例3
输入: s = "c"
输出: ""
解释: 没有美好子字符串。
  • 示例4
输入:s = "dDzeE"
输出:"dD"
解释:"dD""eE" 都是最长美好子字符串。
由于有多个美好子字符串,返回 "dD" ,因为它出现得最早。

提示

  • 1 <= s.length <= 100
  • s 只包含大写和小写英文字母。

解法

优化解法

  • 自己写的纯纯暴力,相当于使用js模拟了一个优先队列
  • 前缀和优化:在 check 中,我们不可避免的遍历整个子串,复杂度为 O(n)
    • 该过程可以使用前缀和思想进行优化:构建二维数组 cnt 来记录子串的词频,cnt[i] 为一个长度为 128 的数组,用于记录字符串 s 中下标范围为 [0, i - 1]的词频。
    • cnt[i + 1][j] 所代表的含义为在子串 s[0...i] 中字符 j 的出现次数。
    • 那么利用「容斥原理」,对于 s 的任意连续段 [l, r] 所代表的子串中的任意字符 i 的词频,我们可以作差算得:
      • res[i] = cnt[r + 1][i] - cnt[l][i]
      • res[i]=cnt[r+1][i]−cnt[l][i]
  • 这样我们在 check 实现中,只要检查 26 个字母对应的大小写词频(ASCII 相差 32),是否同时为 0 或者同时不为 0 即可,复杂度为 O(C)
/**
* @param {string} s
* @return {string}
*/

var longestNiceSubstring = function(s) {
  // 记录数组 小写字母
  let lower = new Array(26);
  // 大写字母
  let upper = new Array(26);
  // console.log('u',upper,'l',lower);
  
  let n = s.length;
  
  if(n == 1) return "";
  let ansLen = 0;
  let index = [];
  for (let i = 0; i < n; i++) {
    //下次循环,需要提前置空
    lower.fill(0);
    upper.fill(0);
    for(let j = i; j < n; j++) {
      if('a' <= s[j] && s[j] <= 'z') {
      // 小写字母
      let temptL = (s[j].charCodeAt() - 'a'.charCodeAt());
      lower[temptL] = 1;
    }else {
      // 大写字母
      let temptU = (s[j].charCodeAt() - 'A'.charCodeAt());
      upper[temptU] = 1;
    }

    // 每次都需要判断一下当前是否完美,完美就跳出循环,len++,记录下标
    // (i,j) 这个子串是否为完美的
    if (lower.toString() == upper.toString()) {
      // 完全相等的是完美的
      if(ansLen < j - i + 1) {
        ansLen = j - i + 1;
        index = [i, j];
      }
    }
  }
}
// console.log('shuchu','ansLen',ansLen,'index',index);
return s.slice(index[0], index[1] + 1);
};