刷leetCode算法題+解析(六)

最大子序和

題目:給定一個(gè)整數(shù)數(shù)組 nums 乔外,找到一個(gè)具有最大和的連續(xù)子數(shù)組(子數(shù)組最少包含一個(gè)元素)拧揽,返回其最大和。

示例:
輸入: [-2,1,-3,4,-1,2,1,-5,4],
輸出: 6
解釋: 連續(xù)子數(shù)組 [4,-1,2,1] 的和最大憋沿,為 6逛揩。

思路:額,這個(gè)題目很簡(jiǎn)單馋嗜,但是一開(kāi)始我思路差了齐板,所以越想越復(fù)雜,最后還是直接看了大神的思路才理明白這個(gè)要怎么做。定義兩個(gè)值甘磨,一個(gè)是目前子序和的最大值橡羞,另一個(gè)是子序慢慢相加的當(dāng)前和。而這個(gè)當(dāng)前和的特性就是如果和為負(fù)值就把之前的都舍去济舆,從頭開(kāi)始加卿泽。然后當(dāng)前值不斷和最大值相比較,取較大的那個(gè)滋觉。這樣一遍下來(lái)签夭,最大值就是這個(gè)數(shù)組的最大子序和

反正我代碼的特點(diǎn)就是墨跡不行的注釋?zhuān)约嚎窗伞5俏铱傆X(jué)得這個(gè)題不僅僅是簡(jiǎn)單的椎侠。第租。。哈哈

    public int maxSubArray(int[] nums) {
        //為什么這個(gè)res是第一個(gè)元素而不是0呢我纪,因?yàn)槿f(wàn)一只有一個(gè)元素慎宾,而這個(gè)元素是負(fù)數(shù),那么結(jié)果就不對(duì)了浅悉!
        int res = nums[0];
        int sum = 0;
        for(int i:nums){
           //從頭開(kāi)始加
           if(sum<0){
               sum = i;              
           }else{//累加
              sum += i; 
           }
           //這樣res總會(huì)是較大的那個(gè)值趟据!
           res = res>=sum?res:sum;
        }
        return res;

    }

因?yàn)槲疫@個(gè)是直接看了大神解題的,所以思路是一樣的术健,就不多說(shuō)了汹碱。

最后一個(gè)單詞的長(zhǎng)度

題目:給定一個(gè)僅包含大小寫(xiě)字母和空格 ' ' 的字符串,返回其最后一個(gè)單詞的長(zhǎng)度苛坚。如果不存在最后一個(gè)單詞比被,請(qǐng)返回 0 。說(shuō)明:一個(gè)單詞是指由字母組成泼舱,但不包含任何空格的字符串等缀。

示例:
輸入: "Hello World"
輸出: 5

思路:這個(gè)題,尤其是跟上道題一對(duì)比我都懷疑是不是有什么我不知道的限制了娇昙,反正兩行代碼的事尺迂。一看題就有兩種思路:一種按照“ ”拆成數(shù)組,取最后一個(gè)的長(zhǎng)度冒掌,一種是按照最后一個(gè)“ ”往后截取噪裕,取最后一個(gè)長(zhǎng)度。

 public int lengthOfLastWord(String s) {
        String [] strs = s.split(" ");
        return strs.length!=0?strs[strs.length-1].length():0;       
    }

我選了一種簡(jiǎn)單又常用的股毫,然后接下來(lái)大神思路(我上面的代碼審核通過(guò)膳音,但是性能和執(zhí)行時(shí)間并不好):大神思路就是獲取最后一個(gè)“ ”后面的,但是存在一種“a ”這樣的情況铃诬,所以要先去掉末尾的“ ”祭陷。但是這個(gè)有現(xiàn)成的api苍凛,我也不知道這個(gè)題要考啥。反正就這樣吧兵志。

class Solution {
    public int lengthOfLastWord(String s) {
        //去掉首尾空格    
        s = s.trim();
        //字符串沒(méi)出現(xiàn)“ ”則返回-1
        int last = s.lastIndexOf(" ");
        //因?yàn)橄聵?biāo)從0開(kāi)始醇蝴,所以這個(gè)last是下標(biāo)位置,如果按實(shí)際元素位置算應(yīng)該是下標(biāo)+1.所以這里是s.length()-1-last
        return last==-1?s.length():s.length()-1-last;
    }
}

上面的是另一個(gè)思路的代碼想罕。

加一

題目:給定一個(gè)由整數(shù)組成的非空數(shù)組所表示的非負(fù)整數(shù)悠栓,在該數(shù)的基礎(chǔ)上加一。最高位數(shù)字存放在數(shù)組的首位按价, 數(shù)組中每個(gè)元素只存儲(chǔ)單個(gè)數(shù)字惭适。你可以假設(shè)除了整數(shù) 0 之外,這個(gè)整數(shù)不會(huì)以零開(kāi)頭俘枫。

示例 1:
輸入: [1,2,3]
輸出: [1,2,4]
解釋: 輸入數(shù)組表示數(shù)字 123腥沽。
示例 2:
輸入: [4,3,2,1]
輸出: [4,3,2,2]
解釋: 輸入數(shù)組表示數(shù)字 4321。

思路:這個(gè)題其實(shí)也挺簡(jiǎn)單的鸠蚪,就是加1嘛。唯一需要注意的點(diǎn)應(yīng)該就是進(jìn)位了师溅。其實(shí)可以把這個(gè)數(shù)組看成一整個(gè)數(shù)茅信,我雖然還沒(méi)做,但是覺(jué)得思路是沒(méi)問(wèn)題的墓臭,等我做完回來(lái)貼代碼
好吧蘸鲸,這個(gè)題啪啪的打臉,他說(shuō)是可以看做非負(fù)整數(shù)酌摇,結(jié)果恨不得二十多位的數(shù)組,什么整數(shù)這么長(zhǎng)拔嗽亍窑多!然后推到重開(kāi),我換了個(gè)思路,開(kāi)始正常判斷,末尾不是9則正常加1颠毙,是9才需要進(jìn)位,一步步往上增蹭,下面是代碼(速度不錯(cuò)滴某,消耗性能較高):

    public int[] plusOne(int[] digits) {
        for(int n =digits.length-1;n>=0;n-- ){
            //不是9正常加1
            if(digits[n]!=9){
                digits[n]=digits[n]+1;
                return digits;
            }else{
                //是9進(jìn)位,末尾變0滋迈,下一個(gè)循環(huán)中n減一霎奢,也就是這位數(shù)的上一位
                digits[n]=0;
            }
        }
        //for循環(huán)里都沒(méi)return的話(huà),說(shuō)明要進(jìn)位了,所以選擇數(shù)組擴(kuò)充
        int[] arr=new int[digits.length+1];
        System.arraycopy(digits,0,arr,1,digits.length);
        //進(jìn)位只可能進(jìn)1饼灿,所以這里直接首位變成1
        arr[0] = 1;
        return arr;      
    }

接下來(lái)去看看大神的解析:
大神解析和我差不多幕侠,不多說(shuō)這個(gè),說(shuō)一個(gè)挺好玩的事:這個(gè)數(shù)組最后的復(fù)制碍彭,其實(shí)因?yàn)閕nt數(shù)組晤硕,默認(rèn)就是0,既然整體進(jìn)位了庇忌,所以肯定每一位都是0這個(gè)沒(méi)話(huà)說(shuō)舞箍,所以這個(gè)其實(shí)沒(méi)有復(fù)制的過(guò)程結(jié)果也是對(duì)的。



但是皆疹,有意思的是疏橄,如果沒(méi)這句話(huà),反而消耗內(nèi)存越多略就!很穩(wěn)定捎迫,紅色框起來(lái)的是有這句代碼的,綠色框起來(lái)的是沒(méi)有的表牢。所以說(shuō)讓系統(tǒng)自動(dòng)賦值還不如自己手動(dòng)復(fù)制來(lái)的快窄绒!


image.png

二進(jìn)制求和

題目:給定兩個(gè)二進(jìn)制字符串,返回他們的和(用二進(jìn)制表示)初茶。輸入為非空字符串且只包含數(shù)字 1 和 0颗祝。

示例 1:
輸入: a = "11", b = "1"
輸出: "100"
示例 2:
輸入: a = "1010", b = "1011"
輸出: "10101"

思路:審?fù)觐}我覺(jué)得這個(gè)題有兩個(gè)思路可解:1.直接二進(jìn)制計(jì)算。逢二進(jìn)一嘛2.二進(jìn)制轉(zhuǎn)化數(shù)字恼布,數(shù)字相加再轉(zhuǎn)回二進(jìn)制螺戳。
因?yàn)槲疫€沒(méi)做,但是我記得已經(jīng)有線(xiàn)程的api可以二進(jìn)制轉(zhuǎn)換成十進(jìn)制折汞。但是我估計(jì)這道題應(yīng)該不是想要調(diào)用現(xiàn)成的api倔幼。所以我這采用二進(jìn)制計(jì)算吧(做的多了還是對(duì)LeetCode出題有一定的了解了,哈哈)爽待。
其實(shí)這個(gè)題如果是二進(jìn)制直接相加的話(huà)损同,跟上一道題有一定的相似之處翩腐。
續(xù):不得不說(shuō)這個(gè)出題人可以,剛剛沒(méi)禁住誘惑打算先直接調(diào)用api完成一次再說(shuō)膏燃,結(jié)果茂卦。。

image.png

錯(cuò)誤原因组哩,該二進(jìn)制數(shù)字超出long范圍等龙,我還是老老實(shí)實(shí)的去直接加吧。就當(dāng)復(fù)習(xí)復(fù)習(xí)包裝類(lèi)api的知識(shí)了伶贰。
繼續(xù)說(shuō)這個(gè)題蛛砰,乍一看很簡(jiǎn)單,但是真做起來(lái)可能是我思路沒(méi)理清楚黍衙,這叫一個(gè)墨跡泥畅。用了一個(gè)小時(shí)的第一版本:
image.png

先看執(zhí)行用時(shí),超過(guò)百分之5的用戶(hù)琅翻,心都碎了位仁,然后上代碼:

class Solution {
    public String addBinary(String a, String b) {
        String[] arr = a.split("");
        String[] brr = b.split("");
        int[] arrs = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            arrs[i] = Integer.parseInt(arr[i]);
        }
        int[] brrs = new int[brr.length];
        for (int i = 0; i < brr.length; i++) {
            brrs[i] = Integer.parseInt(brr[i]);
        }
        int alen = arrs.length - 1;
        int blen = brrs.length - 1;
        //作為結(jié)果集的數(shù)組,因?yàn)榭赡軙?huì)進(jìn)位所以直接預(yù)留出一個(gè)位數(shù)
        int[] result = new int[alen > blen?alen+2:blen+2];
        int r = result.length-1;
        while(alen>=0 || blen>=0) {
            //判斷a是否遍歷完了望迎,是則補(bǔ)0障癌,不是則該是多少是多少
            int aNum = alen>=0?arrs[alen]:0;
            int bNum = blen>=0?brrs[blen]:0;
            //大于等于2則進(jìn)位,否則不進(jìn)位
            if(aNum+bNum>=2) {
                //這個(gè)位數(shù)加上ab合并應(yīng)該加的數(shù)辩尊,累加是因?yàn)榭赡鼙旧碛羞M(jìn)位的1
                result[r] += aNum+bNum-2;
                if(alen>=1) {
                    arrs[alen-1] = arrs[alen-1]+1;
                }else if (blen>=1) {
                    brrs[blen-1] = brrs[blen-1]+1;
                }else {
                    result[r-1] = 1;
                }               
            }else {
                result[r] += aNum+bNum;
            }
            alen--;
            blen--;
            r--;
        }
        String res = "";
        for(int i : result) {
            res += i;
        }
        if(res.charAt(0)=='0') {
            res = res.substring(1);
        }
        return res; 
    }
}

我覺(jué)得我這個(gè)性能主要消耗在字符串?dāng)?shù)組轉(zhuǎn)成int數(shù)組了,或者還有一些別的康辑,但是先實(shí)現(xiàn)再優(yōu)化嘛摄欲!接著開(kāi)始一點(diǎn)點(diǎn)優(yōu)化:

class Solution {
    public String addBinary(String a, String b) {
        int [] arrs = new int[a.length()];
        int [] brrs = new int[b.length()];
        for(int i=0;i<a.length();i++){
             arrs[i]= a.charAt(i)-'0';
        }
         for(int i=0;i<b.length();i++){
             brrs[i]= b.charAt(i)-'0';
        }
        //這里直接減一是為了表示下標(biāo)
        int alen = arrs.length - 1;
        int blen = brrs.length - 1; 
        //作為結(jié)果集的數(shù)組,因?yàn)榭赡軙?huì)進(jìn)位所以直接預(yù)留出一個(gè)位數(shù)
        int[] result = new int[alen > blen?alen+2:blen+2];
        int r = result.length-1;
        //兩個(gè)字符串有沒(méi)遍歷完的
        while(alen>=0 || blen>=0) {
            //判斷a疮薇,b是否遍歷完了胸墙,是則補(bǔ)0,不是則該是多少是多少
            int aNum = alen>=0?arrs[alen]:0;
            int bNum = blen>=0?brrs[blen]:0;
            //大于等于2則進(jìn)位按咒,否則不進(jìn)位
            if(aNum+bNum>=2) {
                //這個(gè)位數(shù)加上ab合并應(yīng)該加的數(shù)迟隅,累加是因?yàn)榭赡鼙旧碛羞M(jìn)位的1
                result[r] += aNum+bNum-2;
                if(alen>=1) {//判斷a是否遍歷完,是則這個(gè)進(jìn)位加b上
                    arrs[alen-1] = arrs[alen-1]+1;
                }else if (blen>=1) {//判斷b是否遍歷完励七,因?yàn)閍在前智袭,走到這本身說(shuō)明a已經(jīng)遍歷完了
                    brrs[blen-1] = brrs[blen-1]+1;
                }else {
                    //走到這步只能是最后一位進(jìn)位了
                    result[0] = 1;
                }               
            }else {
                result[r] += aNum+bNum;
            }
            alen--;
            blen--;
            r--;
        }
        //這個(gè)之前用string來(lái)著,現(xiàn)在是優(yōu)化版掠抬,stringBufferuffer性能較好
        StringBuffer res = new StringBuffer();
        for(int i : result) {
            res.append(i);
        }
        //首位是0則說(shuō)明沒(méi)有進(jìn)位吼野,去掉首位就可以了,不是0則該是是多少是多少
        return res.charAt(0)=='0'?res.substring(1):res.toString(); 
    }
}

優(yōu)化后鳥(niǎo)槍換炮了

優(yōu)化后結(jié)果

其實(shí)主要優(yōu)化點(diǎn)就兩個(gè):一個(gè)是string換成了變長(zhǎng)字符串stringBuffer两波,還有一個(gè)就是我第一版本是字符串轉(zhuǎn)換成字符串?dāng)?shù)組瞳步,再遍歷轉(zhuǎn)化成int數(shù)組的闷哆。在優(yōu)化后就是字符串直接轉(zhuǎn)化成int數(shù)組,少了一步轉(zhuǎn)化過(guò)程单起,用時(shí)超過(guò)百分之98抱怔,我已經(jīng)相當(dāng)滿(mǎn)意了。接下來(lái)去看大神 的思路:
額嘀倒,大神思路大多也就這樣屈留,不過(guò)我是正向思維,從最后往前一個(gè)個(gè)遍歷的括儒,但是大神是從前往后绕沈,最后倒轉(zhuǎn)一下的。別的大同小異帮寻,就不多說(shuō)了乍狐。
用了一天半,這個(gè)帖子才算真正寫(xiě)完固逗,如果稍微幫到了你記得點(diǎn)個(gè)喜歡點(diǎn)個(gè)關(guān)注浅蚪!也祝大家工作順順利利!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末烫罩,一起剝皮案震驚了整個(gè)濱河市惜傲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌贝攒,老刑警劉巖盗誊,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異隘弊,居然都是意外死亡哈踱,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)梨熙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)开镣,“玉大人,你說(shuō)我怎么就攤上這事咽扇⌒安疲” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵质欲,是天一觀的道長(zhǎng)树埠。 經(jīng)常有香客問(wèn)我,道長(zhǎng)把敞,這世上最難降的妖魔是什么弥奸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮奋早,結(jié)果婚禮上盛霎,老公的妹妹穿的比我還像新娘赠橙。我一直安慰自己,他們只是感情好愤炸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布期揪。 她就那樣靜靜地躺著,像睡著了一般规个。 火紅的嫁衣襯著肌膚如雪凤薛。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天诞仓,我揣著相機(jī)與錄音缤苫,去河邊找鬼。 笑死墅拭,一個(gè)胖子當(dāng)著我的面吹牛活玲,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谍婉,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼舒憾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了穗熬?” 一聲冷哼從身側(cè)響起镀迂,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎唤蔗,沒(méi)想到半個(gè)月后探遵,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妓柜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年别凤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片领虹。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖求豫,靈堂內(nèi)的尸體忽然破棺而出塌衰,到底是詐尸還是另有隱情,我是刑警寧澤蝠嘉,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布最疆,位于F島的核電站,受9級(jí)特大地震影響蚤告,放射性物質(zhì)發(fā)生泄漏努酸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一杜恰、第九天 我趴在偏房一處隱蔽的房頂上張望获诈。 院中可真熱鬧仍源,春花似錦、人聲如沸舔涎。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)亡嫌。三九已至嚎于,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間挟冠,已是汗流浹背于购。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留知染,地道東北人肋僧。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像持舆,于是被迫代替她去往敵國(guó)和親色瘩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容