刷题的日常-仅执行一次字符串交换能否使两个字符串相等

74 阅读2分钟

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

刷题的日常-2022年10月11号

一天一题,保持脑子清爽

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

来自leetcode的 1790 题,题意如下:

给你长度相等的两个字符串 s1 和 s2 。一次 字符串交换 操作的步骤如下:选出某个字符串中的两个下标(不必不同),并交换这两个下标所对应的字符。
如果对 其中一个字符串 执行 最多一次字符串交换 就可以使两个字符串相等,返回 true ;否则,返回 false 。

示例1:

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

示例2:

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

理解题意

通过题意,我们可以将信息整理如下:

  • 题目给出两个字符串
  • 要求我们判断是否能进行一次转换使两个字符串相等
  • 需要注意的是,没有转换的时候也是满足题意的,也应该返回true

做题思路

从题目可以看出,如果最多交换一次的话,那么至多只有两个字符的位置不匹配,或者是全部匹配的情况,我们可以将过程整理如下:

  • 用两个指针记录差异索引的位置
  • 循环两个字符串
  • 如果字符相等,继续
  • 如果不相等,则将差异的位置记录到指针当中
  • 如果超过两个位置不一致,则返回false
  • 最后判断下只有一个字符有差异,返回false
  • 然后判断交换之后字符是否匹配

代码实现

代码实现如下:

public class Solution {
    public boolean areAlmostEqual(String s1, String s2) {
        List<Integer> idx = new ArrayList<>(2);
        char c1, c2;
        for (int i = 0; i < s1.length(); i++) {
            c1 = s1.charAt(i);
            c2 = s2.charAt(i);
            if (c1 == c2) {
                continue;
            }
            idx.add(i);
            if (idx.size() > 2) {
                return false;
            }
        }
        if (idx.size() < 2) {
            return idx.size() == 0;
        }
        return s1.charAt(idx.get(0)) == s2.charAt(idx.get(1)) && s1.charAt(idx.get(1)) == s2.charAt(idx.get(0));
    }
}

image.png