LeetCode——每個元音包含偶數次的最長子字符串


Q:給你一個字符串 s ,請你返回滿足以下條件的最長子字符串的長度:每個元音字母,即 'a','e','i','o','u' ,在子字符串中都恰好出現了偶數次。

示例 1:

輸入:s = "eleetminicoworoep"
輸出:13
解釋:最長子字符串是 "leetminicowor" ,它包含 e,i,o 各 2 個,以及 0 個 a,u 。
示例 2:

輸入:s = "leetcodeisgreat"
輸出:5
解釋:最長子字符串是 "leetc" ,其中包含 2 個 e 。
示例 3:

輸入:s = "bcbcbc"
輸出:6
解釋:這個示例中,字符串 "bcbcbc" 本身就是最長的,因為所有的元音 a,e,i,o,u 都出現了 0 次。

A:前綴和 + 狀態壓縮
首先題目中要求子字符串中每個元音字母恰好出現偶數次,我們就可以使用 0 和 1 來標識每個字母的狀態(偶數次或奇數次),我們不需要知道每個字母出現的完整次數,只需要知道這個次數的奇偶性
那么我們可以注意到奇數次 + 1 = 偶數次,偶數次 + 1 = 奇數次,所以我們可以使用 異或 來參與運算: 比如 aba
初始時 status = 00000,然后到 a 的時候 00000 ^ 00001 = 00001,1 說明 a 出現奇數次
然后到 b 的時候 00001 ^ 00010 = 00011,兩個 1 說明 a、b 都出現奇數次
最后到 a 的時候 00011 ^ 00001 = 00010,說明只有 b 出現奇數次了。
以上也說明我們確實是可以使用狀態碼去標識每個元音字母出現次數的奇偶性。
那么我們怎么去統計最長子串的長度呢?
首先我們先盤盤哪些子串符合要求,因為現在每個下標對應的狀態碼其實也就只有 0 和 1
如果坐標 i 對應的狀態碼是 00011,坐標 j 對應的狀態碼是 00011,那么他們倆中間的元音字母數一定是偶數,如果某一位不相同,那么絕對不可能是偶數,因為偶數-奇數=奇數,奇數-偶數=奇數
所以我們每次求出一個坐標的狀態碼的時候就去瞅瞅這個狀態碼前面是否存在,如果存在,那么就計算一下之間子字符串的長度就 ok 了,那么我們還需要啥?明顯需要一個hash表,存儲每個狀態碼對應的下標!當然因為我們狀態碼最長也就是 11111 = 2^5 - 1 = 31,開一個 32 大小的數組就好了。

    public int findTheLongestSubstring(String s) {
        int n = s.length();
        int[] pos = new int[1 << 5];
        Arrays.fill(pos, -1);
        int ans = 0, status = 0;
        pos[0] = 0;
        for (int i = 0; i < n; i++) {
            char ch = s.charAt(i);
            if (ch == 'a') {
                status ^= (1 << 0);
            } else if (ch == 'e') {
                status ^= (1 << 1);
            } else if (ch == 'i') {
                status ^= (1 << 2);
            } else if (ch == 'o') {
                status ^= (1 << 3);
            } else if (ch == 'u') {
                status ^= (1 << 4);
            }
            if (pos[status] >= 0) {
                ans = Math.max(ans, i + 1 - pos[status]);//后面每次遇到這種狀態我們就去求差,然后用一個中間變量去存儲最大的那個差,即為題目所求。
            } else {
                pos[status] = i + 1;//這種狀態是第一次出現的,我們把它的下標記錄下來。
            }
        }
        return ans;
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM