雙周賽78。有點像是kadane的變形版,難度算高,比賽當時還真沒想到是dp。

題目

字串的變異值指的是字串中出現的任意2字元出現次數的最大差值。兩個字元可能相同也可能不同。
輸入小寫字串s,回傳s所有子字串中的最大變異值

解法

又是霸凌python的一天,同樣的演算法,python會超時,java卻勝過100%提交。難怪都說至少要學兩種語言。

題目說在某子字串中,找兩個字元出現次數的最大差值,而且兩個字元可以相同。
但是相同的話差值一定是0,所以只要找枚舉25*26種字元組合就可以。

枚舉不同的字元a和b,各遍歷一次字串s,如果碰到a則+1,碰到b則-1,問題就簡化成最大子陣列了。
維護變數score代表最大子陣列的和,初始為0。
變數v代表實際的變異值,但因為至少要有一個字元b,所以變異值要先初始化為-inf,在第一個b出現之後才以score去更新。

遍歷s中的字元c,當a出現時,子陣列和+1,變異值也+1。
當b出現時,有兩種可能:

  • 使用新的子陣列,加上當前的b,變異值=子陣列和-1
  • 沿用原本的變異值,變異值-1

因為子陣列已經合併到最大的變異值裡面去了,所以要將子陣列和歸0。

class Solution {
    public int largestVariance(String s) {
        char[] cs=s.toCharArray();
        int ans=0;
        for(int i=97;i<123;i++){
            for(int j=97;j<123;j++){
                if(i==j)continue;
                char a=(char)i;
                char b=(char)j;
                int score=0;
                int v=-1000000000;
                for(char c:cs){
                    if(c==a){
                        score++;
                        v++;
                    }else if(c==b){
                        v=Math.max(score-1,v-1);
                        score=0;
                    }
                    if(v>ans)ans=v;
                }
            }
        }
        return ans;
    }
}

如果先遍歷一次s,找到有出現過的字元集合cs,只遍歷cs裡面的字元,就能勉強通過了。
值得注意的是,如果用max函數更新ans,時間會大幅上升,所以要用if減少賦值次數。

class Solution:
    def largestVariance(self, s: str) -> int:
        ans=0
        cs=set(s)
        for a in cs:
            for b in cs:
                if a==b:
                    continue
                score=0
                v=-math.inf
                for c in s:
                    if c==a:
                        score+=1
                        v+=1
                    elif c==b:
                        v=max(score,v)-1
                        score=0                
                    if v>ans:
                        ans=v
                    
        return ans