算法题-交换字符使得字符串相同

133 阅读1分钟

LeetCode:交换字符使得字符串相同

有两个长度相同的字符串 s1 和 s2,且它们其中 只含有 字符 "x" 和 "y",你需要通过「交换字符」的方式使这两个字符串相同。

每次「交换字符」的时候,你都可以在两个字符串中各选一个字符进行交换。

交换只能发生在两个不同的字符串之间,绝对不能发生在同一个字符串内部。也就是说,我们可以交换 s1[i] 和 s2[j],但不能交换 s1[i] 和 s1[j]

最后,请你返回使 s1 和 s2 相同的最小交换次数,如果没有方法能够使得这两个字符串相同,则返回 -1 。

示例 1:

输入: s1 = "xx", s2 = "yy"
输出: 1
解释: 交换 s1[0] 和 s2[1],得到 s1 = "yx",s2 = "yx"

示例 2:

输入: s1 = "xy", s2 = "yx"
输出: 2
解释: 交换 s1[0] 和 s2[0],得到 s1 = "yy",s2 = "xx" 。
交换 s1[0] 和 s2[1],得到 s1 = "xy",s2 = "xy" 。
注意,你不能交换 s1[0] 和 s1[1] 使得 s1 变成 "yx",因为我们只能交换属于两个不同字符串的字符。

示例 3:

输入: s1 = "xx", s2 = "xy"
输出: -1

提示:

  • 1 <= s1.length, s2.length <= 1000
  • s1.length == s2.length
  • s1, s2 只包含 'x' 或 'y'

解题思路

题目描述中的示例1和示例2,分别代表两种交换的情况,即 xx 和 yy,以及 xy 和 yx。 示例1可以用一次交换实现不同位数减2,示例2需要用两次交换实现不同位数减2. 明显示例1效率更高,因此应该尽量用示例一的方式。 s1和s2中的字符,如果同一位置相等,不影响最后结果,可忽略。 不同的情况,如果s1[i]为x,s2[i]为y,是一种情况,我们可记为xy;另一种情况可记为yx。 当xy和yx都为偶数时,可以组成几个xxx和几个yyy的形式,这是既可以用示例一的方式了; 如果为奇数,可以先把偶数的部分使用示例一进行交换,再把剩下的部分用示例而进行交换。

求奇数、偶数和除以2的部分,都可以用位运算加速。

要求出最小的使得两个字符串都相等的交换次数,两个字符串中都只含有 x 和 y, 两个字符串中字符不同的可能情况只有 s1[i] = 'x' , s2[i] ='y' 或 s1[i] = 'y' , s2[i] ='x' 两种情况,

  • 为了求得最小交换次数,优先将按示例一的情况,凑出连续不同的情况
  • 针对两种情况计数模2后的结果
    • 判断是否能够使得两个字符串通过交换获得相同字符顺序,进一步补齐示例二的情况

解题代码

public int minimumSwap(String s1, String s2) {
    int xy = 0, yx = 0;
    int n = s1.length();
    for (int i = 0; i < n; i++) {
        if (s1.charAt(i) == 'x' && s2.charAt(i) == 'y')
            xy++;
        else if (s1.charAt(i) == 'y' && s2.charAt(i) == 'x')
            yx++;
    }
    if (((xy + yx) & 1) == 1) return -1;
    return (xy >> 1) + (yx >> 1) + (xy & 1) + (yx & 1);
}

运行结果

Snipaste_2023-06-26_23-07-17.png

复杂度详情

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)一起进步,一起成长!