Leetcode Weekly Contest 107

壓哨做完4道首懈。
總結(jié)下思路吧暇唾。

925. Long Pressed Name

https://leetcode.com/problems/long-pressed-name/description/
這道題很快就秒了进统。一開(kāi)始字符一定要一樣乖寒。隨后如果出現(xiàn)不一樣,我們就看是不是長(zhǎng)按造成的蓬网,一直去掉重復(fù)字符窒所。重復(fù)字符都去完了,應(yīng)該一樣了帆锋,如果還不一樣就FALSE墩新。

public boolean isLongPressedName(String name, String typed) {
        if(name.equals(typed)) return true;
        char[] ns = name.toCharArray();
        char[] ts = typed.toCharArray();
        int j = 0;
        for(int i = 0; i < ns.length; ) {
            if(j == ts.length) return false;
            if(ns[i] != ts[j]) return false;
            else{
                j++;
                i++;
                if(i == ns.length){
                    while(j < ts.length && ts[j] == ts[j-1]) j++;
                    return j == ts.length;
                }
                while(j < ts.length && ts[j] != ns[i] && ts[j] == ts[j-1]) j++;
            }
            
        }
        return true;
    }

926. Flip String to Monotone Increasing

https://leetcode.com/problems/flip-string-to-monotone-increasing/description/
這道題是一維數(shù)組加狀態(tài)機(jī)的動(dòng)態(tài)規(guī)劃。

我們假定DP J窟坐,是到J位符合遞增的序列. 那么根據(jù)J位是0或1海渊,我們會(huì)有2個(gè)狀態(tài)。
如果J位是0哲鸳,我們只能從J-1位是0得過(guò)來(lái)臣疑。同時(shí)如果這個(gè)是字符串的第J個(gè)和最后的狀態(tài)要求不同,需要翻成對(duì)應(yīng)字符而需要+1徙菠。

如果J位是1讯沈,我們可以從J-1位是0 或者J-1位是1得過(guò)來(lái)。同時(shí)如果這個(gè)是字符串的第J個(gè)和最后的狀態(tài)要求不同婿奔,需要翻成對(duì)應(yīng)字符而需要+1缺狠。

public int minFlipsMonoIncr(String S) {
        char[] A = S.toCharArray();
        int n = A.length;
        int[] one = new int[n + 1];
        int[] zero = new int[n + 1];

        zero[0] = one[0] = 0;
        
        int i;
        for (i = 1; i <= n; i++) {
            one[i] = A[i - 1] == '1' ? Math.min(one[i - 1], zero[i - 1]) : 
                                      Math.min(one[i - 1], zero[i - 1]) + 1;
            zero[i] = A[i - 1] == '0' ? zero[i - 1] : zero[i - 1] + 1;
        }
        return Math.min(zero[n], one[n]);
    }

927. Three Equal Parts

這道題思考過(guò)程是這樣问慎,看了數(shù)據(jù)規(guī)模得出 解的時(shí)間復(fù)雜度應(yīng)該是ON,那么暴力解法肯定不行挤茄。
O N + 分成3段如叼,就想到2個(gè)指針。那么2個(gè)指針就很容易想到雙向指針穷劈。
那么我就把第一個(gè)指針?lè)旁陬^部笼恰,后一個(gè)指針?lè)旁谖膊浚_(kāi)始找能不能指針只會(huì)往中間走而不回退的方法歇终。
我發(fā)現(xiàn)社证,如果一開(kāi)始頭尾指針構(gòu)成的二進(jìn)制數(shù),如果是一樣的评凝。那么只要中間的部分和他們也是一樣的就找到答案了追葡。
如果不一樣,分為2個(gè)情況
如果前面的 比 后面的 小
可以通過(guò)右移左指針而起到增大前面的本事奕短。因?yàn)?個(gè)區(qū)間要相等宜肉。我們最開(kāi)始已經(jīng)貪心的把前后都?jí)嚎s到最小,所以要補(bǔ)救勢(shì)必是通過(guò)增大的方式篡诽。

如果后面比前面小崖飘。我們肯定要通過(guò)左移右指針去把中間的元素拿到右面榴捡,來(lái)增大右面杈女。道理同上

如果配平了左右2面,此時(shí)一定是前綴和后綴長(zhǎng)度最小的配平吊圾。根據(jù)貪心的思想达椰。
我們就看這個(gè)最小的配平下,中間是不是也能配平项乒。配平就找到解了啰劲。

如果中間的比右面的大,我們可以通過(guò)左移右指針檀何,來(lái)試圖讓中間的區(qū)間減少蝇裤。當(dāng)然右移左指針也是可以的。為什么要選擇左移右指針呢频鉴?
通過(guò)觀察栓辜,右移左指針必然會(huì)使得前半部分增大。而左移右指針垛孔,可能因?yàn)槭?藕甩,加了前綴0等于沒(méi)加。而依然保持左半和右半配平周荐。
如果中間的區(qū)間的值比右面的小狭莱,肯定無(wú)解了僵娃。因?yàn)槲覀円呀?jīng)為了配平左右而用了最小的長(zhǎng)度。一旦要去從左右拿出元素腋妙,肯定就無(wú)法配平左右了默怨。
分析到這里,思路就有了辉阶。

落實(shí)到代碼先壕,我決定用DQ,因?yàn)榉奖?頭進(jìn)出谆甜。
同時(shí)為了在做DQ compare的時(shí)候垃僚,加速。
我決定忽略所有前綴0规辱,這增加了編碼難度谆棺,但是加快了時(shí)間。
所有忽略前綴0的DQ罕袋,在比較的時(shí)候改淑,
如果長(zhǎng)度不同,可以直接比出大小浴讯。
如果長(zhǎng)度相同朵夏,就依次遍歷每一個(gè)值,如果全相同就同榆纽,如果一旦不同仰猖,直接比較這2個(gè)不同的值。

為了達(dá)到上述效果奈籽,我在發(fā)現(xiàn)每個(gè)DQ的前綴是0的情況下饥侵,就不插進(jìn)去了。只有1做前綴的時(shí)候再插進(jìn)去衣屏,同時(shí)需要補(bǔ)之前沒(méi)插的0.

public int[] threeEqualParts(int[] A) {
        int i = 0, j = A.length-1;
        Deque<Integer> pre = new ArrayDeque<>();
        Deque<Integer> mid = new ArrayDeque<>();
        Deque<Integer> last = new ArrayDeque<>();
        if(A[0]!=0) pre.offerLast(1);
        if(A[j]!=0) last.offerLast(1);
        for(int k = 1; k < j; k++){
            if(mid.isEmpty() && A[k] == 0) continue;
            mid.offerLast(A[k]);
        } 
        while(i < j){
            int cp = compare(pre,last);
            if(cp<0){
                i++;
                if(A[i] == 0){
                    if(!pre.isEmpty()) pre.offerLast(0);
                } 
                else{
                    if(mid.isEmpty()) break;
                    pre.offerLast(mid.pollFirst());
                    while(!mid.isEmpty() && mid.peekFirst()==0) mid.pollFirst();
                }
            }else if(cp>0){
                j--;
                if(mid.isEmpty()) break;
                if(A[j] == 0) mid.pollLast();
                else moveMidToLast(A,mid,last,j);
            }else{
                int cp2 = compare(mid,last);
                
                if(cp2 == 0) return new int[]{i,j};
                if(cp2<0) break;
                else{
                    j--;
                    if(mid.isEmpty()) break;
                    if(A[j] == 0) mid.pollLast();
                    else moveMidToLast(A,mid,last,j);
                }
            }
        }
        return new int[]{-1,-1};
    }
    private void moveMidToLast(int[] A,Deque<Integer> mid,Deque<Integer> last,int j){
        int idx = j+1;
        while(idx<A.length && A[idx++]==0)
            last.offerFirst(0);
        last.offerFirst(mid.pollLast());
    }
    
    private int compare(Deque<Integer> a, Deque<Integer> b){
        if(a.size() < b.size()) return -1;
        if(a.size() == b.size()){
            Iterator<Integer> itr = a.iterator();
            Iterator<Integer> itr2 = b.iterator();
            while(itr.hasNext()){
                int fa = itr.next();
                int fb = itr2.next();
                if(fa == fb) continue;
                return fa-fb;
            }

            return 0;
        }
        return 1;
    }

928. Minimize Malware Spread II

最后這道題的思考過(guò)程躏升,需要從上周比賽Minimize Malware Spread來(lái)。
區(qū)別就在于抹掉一個(gè)點(diǎn)狼忱,就抹掉了所有的連邊膨疏。
1連2,2連3. 病毒有1,2. 直接這個(gè)局面是沒(méi)救的。但是再這道題里钻弄,通過(guò)抹掉JOINT POINT 2佃却,就能盤(pán)活局面。
但是并查集不是很好處理斷開(kāi)的情況斧蜕。
那我就想既然如果双霍,我索引遍歷所有的病毒,依次抹掉這個(gè)病毒的情況下,重新生成一個(gè)圖洒闸,然后算INFECTS的點(diǎn)的數(shù)量染坯。
隨后取最小值就可以了。
那么構(gòu)成圖的時(shí)候丘逸,其實(shí)就是在UNION单鹿,發(fā)現(xiàn)有一個(gè)點(diǎn)是抹除的病毒點(diǎn),就CONTINUE就好深纲。

int[] par;
    int[] cnt;
    int find(int i){
        if(i == par[i]) return i;
        return par[i] = find(par[i]);
    }
    boolean union(int i,int j){
        int pi = find(i);
        int pj = find(j);
        if(pi == pj) return false;
        par[pi] = pj;
        cnt[pj] += cnt[pi];
        return true;
    }
    public int minMalwareSpread(int[][] graph, int[] initial) {
        Arrays.sort(initial);
        int res = initial[0];
        int min = Integer.MAX_VALUE;
        for(int i = 0; i < initial.length; i++){
            int tmp = initial[i];
            initial[i] = -1;
            int infects = minMalwareSpread2(graph,initial,tmp);
            if(infects < min){
                min = infects;
                res = tmp;
            }
            initial[i] = tmp;
        }
        return res;
    }
    public int minMalwareSpread2(int[][] graph, int[] initial,int tar) {
        int l = graph.length;
        par = new int[l];
        cnt = new int[l];
        Arrays.fill(cnt,1);
        for(int i = 0; i < l; i++) par[i] = i;
        
        for(int i = l-2; i >= 0; i--){
            for(int j = i+1; j < l; j++){
                if(graph[i][j] == 0 || i==tar || j==tar) continue;
                union(i,j);
            }
        }
        int infects = 0;
        boolean[] seen = new boolean[l];
        for(int i : initial){
            if(i == -1) continue;
            int pi = find(i);
            if(seen[pi]) continue;
            seen[pi] = true;
            infects += cnt[pi];
        }
        
        return infects;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末仲锄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子湃鹊,更是在濱河造成了極大的恐慌儒喊,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件币呵,死亡現(xiàn)場(chǎng)離奇詭異怀愧,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)余赢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)芯义,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人妻柒,你說(shuō)我怎么就攤上這事扛拨。” “怎么了举塔?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵绑警,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我啤贩,道長(zhǎng)待秃,這世上最難降的妖魔是什么拜秧? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任痹屹,我火速辦了婚禮,結(jié)果婚禮上枉氮,老公的妹妹穿的比我還像新娘志衍。我一直安慰自己,他們只是感情好聊替,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布楼肪。 她就那樣靜靜地躺著惹悄,像睡著了一般春叫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,610評(píng)論 1 305
  • 那天暂殖,我揣著相機(jī)與錄音价匠,去河邊找鬼。 笑死呛每,一個(gè)胖子當(dāng)著我的面吹牛踩窖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晨横,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼洋腮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了手形?” 一聲冷哼從身側(cè)響起啥供,我...
    開(kāi)封第一講書(shū)人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎库糠,沒(méi)想到半個(gè)月后滤灯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡曼玩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年鳞骤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片黍判。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡豫尽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出顷帖,到底是詐尸還是另有隱情美旧,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布贬墩,位于F島的核電站榴嗅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏陶舞。R本人自食惡果不足惜嗽测,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望肿孵。 院中可真熱鬧唠粥,春花似錦、人聲如沸停做。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蛉腌。三九已至官份,卻和暖如春只厘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舅巷。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工懈凹, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人悄谐。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓介评,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親爬舰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子们陆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355