Easy

题目描述

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

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 1 <= s1.length, s2.length <= 100
  • s1.length == s2.length
  • s1s2 仅由小写英文字母组成

解题思路

这道题的核心思路是分析两个字符串的不同位置数量:

情况分析:

  1. 完全相同:如果两字符串已经相等,直接返回 true
  2. 恰好2个不同位置:这是关键情况,需要检查这两个位置的字符是否可以通过交换变为相同
  3. 其他情况:如果不同位置数量为1个或超过2个,都无法通过一次交换解决

算法步骤:

  1. 遍历两个字符串,找出所有不相同的位置
  2. 根据不同位置的数量进行判断:
    • 0个:已经相等,返回 true
    • 2个:检查位置i和j,是否满足 s1[i] == s2[j] && s1[j] == s2[i]
    • 其他:返回 false

这种方法时间复杂度为O(n),空间复杂度为O(1),是最优解法。

代码实现

class Solution {
public:
    bool areAlmostEqual(string s1, string s2) {
        vector<int> diff;
        for (int i = 0; i < s1.length(); i++) {
            if (s1[i] != s2[i]) {
                diff.push_back(i);
            }
        }
        
        if (diff.size() == 0) {
            return true;
        } else if (diff.size() == 2) {
            return s1[diff[0]] == s2[diff[1]] && s1[diff[1]] == s2[diff[0]];
        } else {
            return false;
        }
    }
};
class Solution:
    def areAlmostEqual(self, s1: str, s2: str) -> bool:
        diff = []
        for i in range(len(s1)):
            if s1[i] != s2[i]:
                diff.append(i)
        
        if len(diff) == 0:
            return True
        elif len(diff) == 2:
            return s1[diff[0]] == s2[diff[1]] and s1[diff[1]] == s2[diff[0]]
        else:
            return False
public class Solution {
    public bool AreAlmostEqual(string s1, string s2) {
        List<int> diff = new List<int>();
        for (int i = 0; i < s1.Length; i++) {
            if (s1[i] != s2[i]) {
                diff.Add(i);
            }
        }
        
        if (diff.Count == 0) {
            return true;
        } else if (diff.Count == 2) {
            return s1[diff[0]] == s2[diff[1]] && s1[diff[1]] == s2[diff[0]];
        } else {
            return false;
        }
    }
}
/**
 * @param {string} s1
 * @param {string} s2
 * @return {boolean}
 */
var areAlmostEqual = function(s1, s2) {
    let diff = [];
    
    for (let i = 0; i < s1.length; i++) {
        if (s1[i] !== s2[i]) {
            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]];
};

复杂度分析

复杂度类型说明
时间复杂度O(n)需要遍历一次字符串找出所有不同位置
空间复杂度O(1)最多存储2个不同位置的索引

相关题目