2840. Check if Strings Can be Made Equal With Operations II

練習日期:2026-03-30

難度:Medium

類型:Hash Table、String、Sorting

📘 題目敘述

給定兩個字串 s1s2,它們長度都為 n,並且只包含小寫英文字母。

你可以對任一個字串做任意次以下操作:

  • 選兩個索引 ij
  • 滿足 i < j
  • j - i 是偶數
  • 然後交換這兩個位置的字元

請判斷是否可以透過這些操作,讓 s1s2 變成相同字串。 如果可以,回傳 true;否則回傳 false

條件限制

  • n == s1.length == s2.length
  • 1 <= n <= 10^5
  • s1s2 只包含小寫英文字母

🧠 解題思路

我這題的想法是把字串拆成:

  • 偶數位置那一組
  • 奇數位置那一組

因為題目只允許交換距離為偶數的兩個位置,這代表被交換的兩個位置一定同奇偶。 也就是說:

  • 偶數位置的字元只能和偶數位置互換
  • 奇數位置的字元只能和奇數位置互換

所以一個字串經過任意次操作之後,本質上只能做到:

  • 偶數位置那一組裡面的字元重新排列
  • 奇數位置那一組裡面的字元重新排列

因此我只要分別比較:

  • s1s2 的偶數位置字元 multiset 是否相同
  • s1s2 的奇數位置字元 multiset 是否相同

我這份寫法是直接把兩組字串拆出來後排序。 如果排序後都一樣,就代表可以透過交換把它們變成相同字串。

所有變數

  • es1s1 奇數位置的所有字元組成的字串
  • es2s2 奇數位置的所有字元組成的字串
  • os1s1 偶數位置的所有字元組成的字串
  • os2s2 偶數位置的所有字元組成的字串

🪜 主要流程步驟

1. 先檢查兩個字串長度是否相同

我先判斷:

if (s1.size() != s2.size()) {
    return false;
}

如果長度不同,那不可能透過題目允許的交換操作把它們變成同一個字串,所以直接回傳 false


2. 把兩個字串分成奇數位置和偶數位置兩組

接著我準備四個字串:

string es1 = "", es2 = ""; // 奇數位置
string os1 = "", os2 = ""; // 偶數位置

然後掃過每個索引位置:

  • 如果 i % 2 == 0,就把這個位置的字元放進偶數組
  • 否則就放進奇數組

意思就是把 s1s2 的字元各自拆成兩個部分。

這一步很重要,因為題目的操作不會改變字元所在位置的奇偶性。 所以最後能不能變一樣,關鍵就在於這兩組字元各自能不能配對起來。


3. 分別排序四個拆出來的字串

拆完之後,我就把這四個字串各自排序:

這樣做的目的,是把「能不能透過重排變成一樣」轉成「排序後是否相同」。

因為同一組內可以任意透過合法交換去調整順序, 所以真正要比的不是原本順序,而是:

  • 這一組裡有哪些字元
  • 每個字元各出現幾次

排序之後,如果兩個字串相同,就代表它們包含完全一樣的字元 multiset。


4. 最後同時比較偶數組和奇數組

最後我回傳:

return (os1 == os2 && es1 == es2) ? true : false;

也就是同時檢查:

  • 偶數位置這一組排序後是否相同
  • 奇數位置這一組排序後是否相同

只有兩組都相同,才代表:

  • 偶數位置可以靠重排對上
  • 奇數位置也可以靠重排對上

這樣整個字串才有可能透過合法操作變成一樣。

如果其中任一組不同,就代表至少有某些字元被困在錯誤的奇偶位置,無法透過操作修正,所以答案就是 false

⏱️ 複雜度

n = s1.length

  • 時間複雜度:O(n log n) 我先掃一次字串做分組,之後對奇數組和偶數組排序,整體是 O(n log n)
  • 空間複雜度:O(n) 我另外開了四個字串來存拆出來的奇數位置與偶數位置字元。

💻 程式碼實作

class Solution {
public:
    bool checkStrings(string s1, string s2) {
        if (s1.size() != s2.size()) {
            return false;
        }
        string es1 = "", es2 = ""; // 奇數位置
        string os1 = "", os2 = ""; // 偶數位置
        for (int i = 0; i < s1.size(); i++) {
            if (i % 2 == 0) {
                os1 += s1[i];
                os2 += s2[i];
            } else {
                es1 += s1[i];
                es2 += s2[i];
            }
        }
        sort(os1.begin(), os1.end());
        sort(os2.begin(), os2.end());
        sort(es1.begin(), es1.end());
        sort(es2.begin(), es2.end());
        return (os1 == os2 && es1 == es2) ? true : false;
    }
};

https://leetcode.com/problems/check-if-strings-can-be-made-equal-with-operations-ii/

作者: scottnick
撰寫日期: 2026-03-30
類別:
原文連結: https://scottnick.github.io/cpp-notes/all%20problems/2840-check-if-strings-can-be-made-equal-with-operations-ii.html