算法-仅执行一次字符串交换能否使两个字符串相等

112 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情

题目

leetcode 1790. 仅执行一次字符串交换能否使两个字符串相等 难度:简单

给你长度相等的两个字符串 s1 和 s2 。一次 字符串交换 操作的步骤如下:选出某个字符串中的两个下标(不必不同),并交换这两个下标所对应的字符。

如果对 其中一个字符串 执行 最多一次字符串交换 就可以使两个字符串相等,返回 true ;否则,返回 false 。

示例 1:

输入:s1 = "bank", s2 = "kanb"
输出:true
解释:例如,交换 s2 中的第一个和最后一个字符可以得到 "bank"

示例 2:

输入:s1 = "attack", s2 = "defend"
输出:false
解释:一次字符串交换无法使两个字符串相等

示例 3:

输入:s1 = "kelb", s2 = "kelb"
输出:true
解释:两个字符串已经相等,所以不需要进行字符串交换

示例 4:

输入:s1 = "abcd", s2 = "dcba"
输出:false

提示:

1 <= s1.length, s2.length <= 100

s1.length == s2.length

s1 和 s2 仅由小写英文字母组成

题解

如果两个字符串相等那么我们就直接返回true即可

方法一:暴力解法,我们需要交换每一个字符串后将每种情况的字符串与目标字符串对比,最后即可得出。题目要求只需交换一次,所以比较简单。

方法二:抓住题目关键只交换一次,那么只需要找到仅有两次不同的字符串,如何再对比字符串交换后是否相等即可。

// 方法一
/**
 * @param {string} s1
 * @param {string} s2
 * @return {boolean}
 */
var areAlmostEqual = function(s1, s2) {
    if (s1 === s2) {
        return true;
    }
    const a2 = s2.split('');
    let tem = [...a2];
    for (let i = 0; i < s1.length - 1; i++) {
        for (let j = i + 1; j < s1.length; j++) {
            [tem[i], tem[j]] = [tem[j], tem[i]];
            if (s1 === tem.join('')) {
                return true;
            }
            tem = [...a2];
        }
    }
    return false;
};
// 方法二
var areAlmostEqual = function(s1, s2) {
    const n = s1.length;
    const diff = [];
    for (let i = 0; i < n; ++i) {
        if (s1[i] !== s2[i]) {
            if (diff.length >= 2) {
                return false;
            }
            diff.push(i);
        }
    }
    if (diff.length === 0) {
        return true;
    }
    if (diff.length !== 2) {
        return false;
    }
    return s1[diff[0]] === s2[diff[1]] && s1[diff[1]] === s2[diff[0]];
};

代码详解

方法一种写法上有些技巧性,首先temp需拷贝保证a2的值不会被更改。然后就是交换[tem[i], tem[j]] = [tem[j], tem[i]];,运用到了es6的结构写法。

方法二再进行了一些改进s1[diff[0]] === s2[diff[1]] && s1[diff[1]] === s2[diff[0]];只对比不交换,提升了运行效率。