1. 程式人生 > 其它 >828. 統計子串中的唯一字元

828. 統計子串中的唯一字元

難度 hard
我們定義了一個函式 countUniqueChars(s) 來統計字串 s 中的唯一字元,並返回唯一字元的個數。

例如:s = "LEETCODE" ,則其中 "L", "T","C","O","D" 都是唯一字元,因為它們只出現一次,所以 countUniqueChars(s) = 5 。

本題將會給你一個字串 s ,我們需要返回 countUniqueChars(t) 的總和,其中 t 是 s 的子字串。注意,某些子字串可能是重複的,但你統計時也必須算上這些重複的子字串(也就是說,你必須統計 s 的所有子字串中的唯一字元)。

由於答案可能非常大,請將結果 mod 10 ^ 9 + 7 後再返回。

示例 1:

輸入: s = "ABC"
輸出: 10
解釋: 所有可能的子串為:"A","B","C","AB","BC" 和 "ABC"。
其中,每一個子串都由獨特字元構成。
所以其長度總和為:1 + 1 + 1 + 2 + 2 + 3 = 10
示例 2:

輸入: s = "ABA"
輸出: 8
解釋: 除了 countUniqueChars("ABA") = 1 之外,其餘與示例 1 相同。
示例 3:

輸入:s = "LEETCODE"
輸出:92

提示:

0 <= s.length <= 10^4
s 只包含大寫英文字元

解題思路:這道題看了leetcode上的題解,思路還是很巧妙的,簡單地說下,先找出某個字母僅出現一次的區間,以"LEETCODE"中的"T"為例,其出現的區間為[0,7],然後開始統計這個區間內"T"在多少子串中出現過,以左邊字元"L","E","E","T"開頭的情況有4種,以右邊字元"T","C","O","D","E"結尾的情況有5種,因此"T"在45總共20個子串中出現過,對最後總次數的貢獻也即是20。而已第二個字元"E"為例,其僅出現一次的區間為[0,1],這個區間以"L","E"開頭的情況有2種,以"E"結尾的情況有1種,因此"E"總共在2

1共2個子串中出現過。知道以上技巧後,下面就是要找到每個字母僅出現一次的區間了,這裡用兩個陣列left和right表示字母僅出現一次的區間的左右端點,然後我們用一個數組mem來記錄每個字母出現的位置。先從左到右遍歷字串,索引為i,mem初始化為-1,表示最左的端點,算出某個字元的下標t後,我們先將left[i]賦為mem[t],然後再將mem[t]賦為i,這是為了保證i處的字元先把之前記錄下來的與本身相等的位置確定為左端點,然後再把新的位置賦給mem[i],作為下次出現相同字元時的右端點,以"LEETCODE"為例,遍歷到第二個字元"E"的時候,left[1]=-1,而隨後mem['E'-'A']被賦為1,因此遍歷到第三個字元的時候,left[2]=1,這樣才能保證左端點正確更新。right陣列的賦值同理,但此時要把mem陣列先初始化為字串長度len,表示預設的右端點是len。最後,統計結果時,把i距離左右端點的距離相乘,加到res中即可,記得對1000000007取模即可。

程式碼 t75 s74 java

class Solution {
    public int uniqueLetterString(String s) {
        int res = 0, len = s.length(), M = 1000000007;
        int[] mem = new int[26];
        int[] left = new int[len];
        int[] right = new int[len];
        
        Arrays.fill(mem, -1);
        for(int i=0; i<len; i++){
            int t = s.charAt(i) - 'A';
            left[i] = mem[t];
            mem[t] = i;
        }

        Arrays.fill(mem, len);
        for(int i=len-1; i>=0; i--){
            int t = s.charAt(i) - 'A';
            right[i] = mem[t];
            mem[t] = i;
        }

        for(int i=0; i<len; i++){
            res = (res + (i-left[i])*(right[i]-i)) % M;
        }
        return res % M;
    }
}

參考資料
https://leetcode-cn.com/problems/count-unique-characters-of-all-substrings-of-a-given-string/solution/c-you-li-zi-yi-dong-by-smilyt_/