LeetCode 859 亲密字符串

120 阅读1分钟

参加了 kkb 的门徒培训,想要记录下自己的成长过程。每天一篇,坚持不断更 --- 2022.3.17

题目描述

给你两个字符串 s 和 goal ,只要我们可以通过交换 s 中的两个字母得到与 goal 相等的结果,就返回 true ;否则返回 false 。

交换字母的定义是:取两个下标 i 和 j (下标从 0 开始)且满足 i != j ,接着交换 s[i] 和 s[j] 处的字符。

  • 例如,在 "abcd" 中交换下标 0 和下标 2 的元素可以生成 "cbad" 。

 

示例 1:

输入: s = "ab", goal = "ba"
输出: true
解释: 你可以交换 s[0] = 'a' 和 s[1] = 'b' 生成 "ba",此时 s 和 goal 相等。

示例 2:

输入: s = "ab", goal = "ab"
输出: false
解释: 你只能交换 s[0] = 'a' 和 s[1] = 'b' 生成 "ba",此时 s 和 goal 不相等。

示例 3:

输入: s = "aa", goal = "aa"
输出: true
解释: 你可以交换 s[0] = 'a' 和 s[1] = 'a' 生成 "aa",此时 s 和 goal 相等。

 

提示:

  • 1 <= s.length, goal.length <= 2 * 104
  • s 和 goal 由小写英文字母组成

解题思路

这题需要考虑到,有两个以上的差异的可能。

/**
 * @param {string} a
 * @param {string} b
 * @return {boolean}
 */
const isRepeat = (a) => {
  const count = {};
  for (let item of a) {
    // 计数法判断是否有重复字符
    count[item] = count[item] ? count[item] + 1 : 1;
    if (count[item] === 2) return true;
  }
  return false;
};
var buddyStrings = function (a, b) {
  if (a.length !== b.length) return false;

  // 相等较为简单,但不一定满足可交换,判断下
  if (a === b) return isRepeat(a);

  // 找两处不同的地方,然后看是否只有两处,且这两处是字母交换位置
  let i = 0,
    j;
  while (a[i] === b[i]) {
    i++; // 第一处差异点
  }
  j = i + 1;
  if (j > a.length) return false; // 差异为 false
  while (j < a.length && a[j] == b[j]) {
    j++;
  }
  // 只有一处差异
  if (j == a.length) return false;
  // 发现两处不相等
  if (a[i] !== b[j] || a[j] !== b[i]) return false;
  j++;
  // 有三个以上的差异
  while (j < a.length) {
    if (a[j] != b[j]) return false;
    j++;
  }
  return true;
};