LeetCode - 859 - 亲密字符串(buddy-strings)

一 目录

不折腾的前端,和咸鱼有什么区别

目录
一 目录
二 前言
三 解题及测试
四 LeetCode Submit
五 解题思路
六 进一步思考

二 前言

  • 难度:简单

  • 涉及知识:字符串

  • 题目地址:https://leetcode-cn.com/problems/buddy-strings/

  • 题目内容

给定两个由小写字母构成的字符串 A 和 B,
只要我们可以通过交换 A 中的两个字母得到与 B 相等的结果,
就返回 true;否则返回 false。

示例 1:

输入:A = "ab", B = "ba"
输出:true

示例 2:

输入:A = "ab", B = "ab"
输出:false

示例 3:

输入:A = "aa", B = "aa"
输出:true

示例 4:

输入:A = "aaaaaaabc", B = "aaaaaaacb"
输出:true

示例 5:

输入:A = "", B = "aa"
输出:false

提示:

0 <= A.length <= 20000
0 <= B.length <= 20000
A 和 B 仅由小写字母构成。

三 解题及测试

小伙伴可以先自己在本地尝试解题,再回来看看 jsliang 的解题思路。

  • LeetCode 给定函数体

/**
 * @param {string} A
 * @param {string} B
 * @return {boolean}
 */
var buddyStrings = function(A, B) {
    
};

根据上面的已知函数,尝试破解本题吧~

确定了自己的答案再看下面代码哈~

index.js

/**
 * @name 亲密字符串
 * @param {string} A
 * @param {string} B
 * @return {boolean}
 */
const buddyStrings = (A, B) => {
  // A 和 B 长度相等
  if (A.length !== B.length) {
    return false;
  }
  // A 和 B 不匹配的地方不能超过 3 处
  const misMatch = [];
  for (let i = 0; i < A.length; i++) {
    if (A[i] !== B[i]) {
      misMatch.push(i);
      if (misMatch.length > 2) {
        return false;
      }
    }
  }
  if (misMatch.length === 0) {
    // 如果 A 和 B 相等,去重判断
    return [...new Set(A)].length < A.length;
  } else if (misMatch.length === 2) {
    // 如果 misMatch 长度为 2,判断 A[0] = B[1] && A[1] = B[0]
    return A[misMatch[0]] === B[misMatch[1]] && A[misMatch[1]] === B[misMatch[0]];
  }
  return false;
};

console.log(buddyStrings('ab', 'ba')); // true
console.log(buddyStrings('ab', 'ab')); // false
console.log(buddyStrings('aa', 'aa')); // true
console.log(buddyStrings('aaaaaaabc', 'aaaaaaacb')); // true
console.log(buddyStrings('', 'aa')); // false

node index.js 返回:

true
false
true
true
false

四 LeetCode Submit

Accepted
* 23/23 cases passed (72 ms)
* Your runtime beats 78.38 % of javascript submissions
* Your memory usage beats 11.43 % of javascript submissions (36.6 MB)

五 解题思路

分析题目意思:

  1. 交换 A 中 2 个字母后,A = B;

  2. 【必须】A = 'ab'B = 'ab',返回 false

  3. A 和 B 可以全部字母相等且两者由单个元素构成。例如:A = 'aa'B = 'aa',返回 true

  4. A 和 B 可以有两个位置不同,这样调转这两个位置的顺序后有可能相同。例如:A = 'aaaaaaabc'B = 'aaaaaaacb',返回 true

然后,然后就得出了:

面向用例编程(不可取)

const buddyStrings = (A, B) => {
  if (A.length !== B.length || !A.length || !B.length) {
    return false;
  }
  const map = new Map();
  let flag1 = false;
  for (let i = 0; i < A.length; i++) {
    if (map.get(A[i])) {
      flag1 = true;
      map.set(A[i], map.get(A[i]) + 1);
    } else {
      map.set(A[i], 1);
    }
  }
  if (A === B && flag1) {
    return true;
  } else if (A === B && !flag1) {
    return false;
  }
  const newA = A.split('');
  const newB = B.split('');
  let flag2 = -1;
  for (let i = 0; i < newA.length; i++) {
    if (newA[i] !== newB[i] && flag2 === -1) {
      flag2 = i;
    } else if (newA[i] !== newB[i] && flag2 !== -1) {
      const temp = newA[flag2];
      newA[flag2] = newA[i];
      newA[i] = temp;
      break;
    }
  }
  return newA.join('') === newB.join('');
};

针对条件进行了多重筛选,不管你懵不懵逼,反正写完我都不想去整理(跟我写业务代码,写烂了的时候一样~)

Submit 提交如下:

Accepted
* 23/23 cases passed (80 ms)
* Your runtime beats 39.19 % of javascript submissions
* Your memory usage beats 11.43 % of javascript submissions (36.6 MB)

六 进一步思考

然后,去【题解区】和【评论区】逛逛,发现一个思路非常清晰的解法:

  • ☆≡═ 亲密字符串:https://leetcode-cn.com/problems/buddy-strings/solution/-qin-mi-zi-fu-chuan-by-hareyukai/

下面是原说法:

  1. 统计字符串 A,B 中字符不匹配的下标。

  2. 不匹配的下标个数不等于 0 或 2 时,不能由 A 得到 B。

  3. 不匹配的下标个数等于 0 时,A 与 B 中字符完全相同,还需要 A 中有重复字符。

  4. 不匹配的下标个数等于 2 时,判断交换两对字符后是否匹配。

class Solution {
public:
  bool buddyStrings(const string & a, const string & b) {
    if (a.size() != b.size()) return false;
    vector < int > index_of_mismatch;
    for (int i = 0; i < a.size(); i++)
      if (a[i] != b[i]) {
        index_of_mismatch.push_back(i);
        if (2 < index_of_mismatch.size()) return false;
      }
    if (index_of_mismatch.size() == 0) {
      return set < char > (a.begin(), a.end()).size() < a.size();
    } else if (index_of_mismatch.size() == 2) {
      return a[index_of_mismatch[0]] == b[index_of_mismatch[1]] &&
        a[index_of_mismatch[1]] == b[index_of_mismatch[0]];
    }
    return false;
  }
};

这是原 C++ 题解,稍微整理了下:

const buddyStrings = (A, B) => {
  // A 和 B 长度相等
  if (A.length !== B.length) {
    return false;
  }
  // A 和 B 不匹配的地方不能超过 3 处
  const misMatch = [];
  for (let i = 0; i < A.length; i++) {
    if (A[i] !== B[i]) {
      misMatch.push(i);
      if (misMatch.length > 2) {
        return false;
      }
    }
  }
  if (misMatch.length === 0) {
    // 如果 A 和 B 相等,去重判断
    return [...new Set(A)].length < A.length;
  } else if (misMatch.length === 2) {
    // 如果 misMatch 长度为 2,判断 A[0] = B[1] && A[1] = B[0]
    return A[misMatch[0]] === B[misMatch[1]] && A[misMatch[1]] === B[misMatch[0]];
  }
  return false;
};

Submit 提交:

Accepted
* 23/23 cases passed (80 ms)
* Your runtime beats 39.19 % of javascript submissions
* Your memory usage beats 11.43 % of javascript submissions (36.6 MB)

还是挺不错的,膜拜大佬~

如果小伙伴有更好的思路想法,欢迎评论留言或者私聊 jsliang~


不折腾的前端,和咸鱼有什么区别!

jsliang 会每天更新一道 LeetCode 题解,从而帮助小伙伴们夯实原生 JS 基础,了解与学习算法与数据结构。

浪子神剑 会每天更新面试题,以面试题为驱动来带动大家学习,坚持每天学习与思考,每天进步一点!

扫描上方二维码,关注 jsliang 的公众号(左)和 浪子神剑 的公众号(右),让我们一起折腾!

jsliang 的文档库 由 梁峻荣 采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议进行许可。
基于https://github.com/LiangJunrong/document-library上的作品创作。
本许可协议授权之外的使用权限可以从 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 处获得。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值