Easy

题目描述

给你两个字符串 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 * 10⁴
  • s 和 goal 由小写英文字母组成

解题思路

这道题需要判断通过交换字符串 s 中的两个字符是否能得到 goal。我们需要分情况讨论:

核心思路:

  1. 首先检查两个字符串长度是否相等,不等则直接返回 false
  2. 找出所有不同位置的字符对
  3. 根据不同位置的数量进行分类处理

情况分析:

  • 完全相同:如果 s 和 goal 完全相同,需要检查是否存在重复字符。如果有重复字符,可以交换这两个相同的字符;如果没有重复字符,则无法进行有效交换
  • 恰好两处不同:检查这两处不同是否互为交换关系,即 s[i] == goal[j] && s[j] == goal[i]
  • 其他情况:超过两处不同或只有一处不同,都无法通过一次交换达到目标

算法步骤:

  1. 遍历字符串,记录所有不同的位置
  2. 如果不同位置为0,检查是否有重复字符
  3. 如果不同位置为2,检查是否满足交换条件
  4. 其他情况返回 false

时间复杂度为 O(n),空间复杂度为 O(1)。

代码实现

class Solution {
public:
    bool buddyStrings(string s, string goal) {
        if (s.length() != goal.length()) {
            return false;
        }
        
        vector<int> diff;
        for (int i = 0; i < s.length(); i++) {
            if (s[i] != goal[i]) {
                diff.push_back(i);
            }
        }
        
        if (diff.size() == 0) {
            // 两个字符串相同,需要检查是否有重复字符
            vector<int> count(26, 0);
            for (char c : s) {
                count[c - 'a']++;
                if (count[c - 'a'] > 1) {
                    return true;
                }
            }
            return false;
        } else if (diff.size() == 2) {
            // 恰好两处不同,检查是否可以交换
            return s[diff[0]] == goal[diff[1]] && s[diff[1]] == goal[diff[0]];
        }
        
        return false;
    }
};
class Solution:
    def buddyStrings(self, s: str, goal: str) -> bool:
        if len(s) != len(goal):
            return False
        
        diff = []
        for i in range(len(s)):
            if s[i] != goal[i]:
                diff.append(i)
        
        if len(diff) == 0:
            # 两个字符串相同,需要检查是否有重复字符
            return len(set(s)) < len(s)
        elif len(diff) == 2:
            # 恰好两处不同,检查是否可以交换
            return s[diff[0]] == goal[diff[1]] and s[diff[1]] == goal[diff[0]]
        
        return False
public class Solution {
    public bool BuddyStrings(string s, string goal) {
        if (s.Length != goal.Length) {
            return false;
        }
        
        List<int> diff = new List<int>();
        for (int i = 0; i < s.Length; i++) {
            if (s[i] != goal[i]) {
                diff.Add(i);
            }
        }
        
        if (diff.Count == 0) {
            // 两个字符串相同,需要检查是否有重复字符
            int[] count = new int[26];
            foreach (char c in s) {
                count[c - 'a']++;
                if (count[c - 'a'] > 1) {
                    return true;
                }
            }
            return false;
        } else if (diff.Count == 2) {
            // 恰好两处不同,检查是否可以交换
            return s[diff[0]] == goal[diff[1]] && s[diff[1]] == goal[diff[0]];
        }
        
        return false;
    }
}
var buddyStrings = function(s, goal) {
    if (s.length !== goal.length) return false;
    
    if (s === goal) {
        const charCount = new Set(s);
        return charCount.size < s.length;
    }
    
    const diff = [];
    for (let i = 0; i < s.length; i++) {
        if (s[i] !== goal[i]) {
            diff.push(i);
        }
    }
    
    return diff.length === 2 && s[diff[0]] === goal[diff[1]] && s[diff[1]] === goal[diff[0]];
};

复杂度分析

复杂度类型复杂度说明
时间复杂度O(n)需要遍历整个字符串一次,n为字符串长度
空间复杂度O(1)只使用常数额外空间存储不同位置和字符计数

相关题目