貪心算法

貪心算法:是指在對問題進(jìn)行求解的時候貌矿,總是做出在當(dāng)前看來最好的選擇呐伞,即不易整體為考慮仿粹,而是局部最優(yōu)解。

  • 貪心算法并不能對所有問題都得出整體最優(yōu)解各聘,關(guān)鍵是貪心策略的選擇。
  • 無后效性:某個狀態(tài)以前的過程不會影響以后的狀態(tài)抡医,只與當(dāng)前狀態(tài)有關(guān)躲因。
  • 一般能用貪心算法解決的問題是:在有一個限定值的情況下,使某個期望值能達(dá)到最高或者最低忌傻。
  • 無需嘗試去證明貪心算法的正確性大脉,貪心策略一般是顯而易見的。

貪心是一種思想水孩,要參透它镰矿,還是要以刷題為主。

1俘种、買賣股票的最佳時機(簡單)-122


題目

這道題的給出了連續(xù)好多天一直股票的價格秤标,讓我們能制訂買賣策略獲取最大收益,但是在現(xiàn)實中肯定是不行的宙刘。貪心的策略是不要放過任何一次漲苍姜,跌之前就賣掉(要真這樣我就去炒股好了,我的手就可以拿來彈鋼琴了)悬包。

class Solution {
    public int maxProfit(int[] prices) {
        int profit = 0;
        for(int i = 1; i < prices.length; i++) {
            if(prices[i] > prices[i - 1]) {
                profit += prices[i] - prices[i - 1];
            }
        }
        return profit;
    }
}

2衙猪、跳躍游戲(中等)-55


題目

這道題說實話我沒做出來,我一開始想的是從0開始每次我都跳最大布近,實在不行我退回來垫释,但是無法通過,后來想想這樣做吊输,當(dāng)跳一躍的時候饶号,必定會影響到后面的一躍。
其實思想應(yīng)該是:要跳躍到最后一個位置季蚂,中間的每個位置一定都能到達(dá)茫船,如果把能到達(dá)終點的點成為好坐標(biāo)琅束,就可以從倒數(shù)第二個位置開始向前遍歷,每個點要能到達(dá)終點算谈,必須能夠到達(dá)離他最近的好坐標(biāo)涩禀,而后它就成了前面點的最近好坐標(biāo)。最后只要判斷0的位置是不是好坐標(biāo)然眼,就能解決問題了艾船。

class Solution {
    public boolean canJump(int[] nums) {
        int len = nums.length;
        int lastPos = len - 1;
        for(int i = len - 1; i >= 0; i--) {
            if(i + nums[i] >= lastPos) {
                lastPos = i;
            }
        }
        if(lastPos == 0) {
            return true;

        } else {
            return false;
        }
    }
}

3、加油站 -134


題目

一開始我是想從開到下個加油站能剩余最多油的站開始走高每,但是這樣是會出現(xiàn)到了某段路程開不過的情況屿岂。我又想,那就不要錯過每一個增量鲸匿,也是行不通的爷怀。
其實,因為答案是唯一的带欢,想走完路程运授,只要總油量比總油耗多,肯定是能走完的乔煞。從第一個油站開始吁朦,若出現(xiàn)油耗不夠,那么起點必須在這個加油站的后面渡贾,只要某個點能走到最后一個站逗宜,那它必須能走一圈。

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int start = 0;
        int total = 0;
        int sum = 0;
        for(int i = 0; i < gas.length; i++) {
            int rest = gas[i] - cost[i];
            total += rest;
            sum += rest;
            if(sum < 0) {
                start = i + 1;
                sum = 0;
            }
        }
        return total >= 0 ? start : -1;
    }
}

4剥啤、判斷子序列 -392


題目

一開始沒理解輕觸題目锦溪,哦,這不是灑灑水府怯,我用個26長度的數(shù)組統(tǒng)計一下,你來10億個我也能判斷防楷,后來才發(fā)現(xiàn)忽略了順序牺丙。還是得乖乖地去遍歷字符串,但是比對了別人的答案复局,相形見絀冲簿,別人都是用字符串的方法,而我對api都不熟悉亿昏,方法實在不高明啊峦剔。力扣歸類的是貪心,我沒悟到角钩。

我的:
class Solution {
    public boolean isSubsequence(String s, String t) {
        if("".equals(s)) {
            return true;
        }
        if("".equals(t)) {
            return false;
        }
        char[] a = s.toCharArray();
        char[] b = t.toCharArray();
        int j = 0;
        int len = a.length;
        for(int i = 0; i < b.length; i++) {
            if(b[i] == a[j]) {
                j++;
                if(j == len) {
                    return true;
                }
            }
        }
        return false;
    }
}

別人的:
class Solution {
    public boolean isSubsequence(String s, String t) {
        int i = -1;
        for(char c : s.toCharArray()){
           i =  t.indexOf(c,i+1);
            System.out.println(i);
           if(i == -1){
                return  false;
           }
        }
        return true;
    }
}
作者:shu-pi-2
鏈接:https://dev.lingkou.xyz/problems/two-sum/solution/chong-fen-li-yong-indexofmark-by-shu-pi-2/
來源:力扣(LeetCode)

5吝沫、分發(fā)糖果 -135


題目

之前做的分糖果題目是孔融讓梨一樣小吃小大吃大來分大小不同的題目呻澜,所以一開始切入的時候我還是在找最低分的孩子,但是這道題每個孩子要比較的只是他相鄰的孩子惨险,所以解決不了羹幸。那么,一個孩子可能有兩個相鄰的孩子辫愉,所以既要跟左邊的相比也要跟右邊的相比栅受,就會有兩條規(guī)矩:最先給每個孩子都發(fā)上一個,先從左邊開始遍歷恭朗,只要我比我左邊的人分?jǐn)?shù)高屏镊,我就要分到比他的糖果,不然我就不開心痰腮,再從右邊開始遍歷而芥,每個人與他右邊的孩子相比(沒有就不用),最終糖果數(shù)分別用兩個數(shù)組存儲诽嘉,每個孩子都要滿足這兩個約束蔚出,那當(dāng)然是取多的發(fā)。

class Solution {
    public int candy(int[] ratings) {
        int count = 0;
        int n = ratings.length;
        int[] l = new int[n];
        int[] r = new int[n];
        //初始時每個學(xué)生都分配1個糖果
        for(int i = 0; i <= n - 1; i++) {
            l[i] = 1;
            r[i] = 1;
        }
        //從左邊遍歷得到分配數(shù)組
        for(int i = 1; i <= n - 1; i++) {
            if(ratings[i] > ratings[i - 1]) {
                l[i] = l[i - 1] + 1;
            }
        }
        //在從右邊遍歷得到分配數(shù)組
        for(int i = n - 2; i >= 0; i--) {
            if(ratings[i] > ratings[i + 1]) {
                r[i] = r[i + 1] + 1;
            }
        }
        for(int i = 0; i < n; i++) {
            count += l[i] > r[i] ? l[i] : r[i];
        }
        return count;
    }
}

6骄酗、按要求補齊數(shù)組 -330


題目

欸踏烙,這道題就比較有難度了寒屯。一開始我想的居然是從n開始去減最大的數(shù)处面,然后再n-1繼續(xù),然后就沒有然后了,怎么可能嘛醉顽,真是愚蠢的雷霆球迷通熄。
這道題講究的是一個覆蓋,要覆蓋[1, n]的區(qū)間饿幅,當(dāng)然使用比n的數(shù)來相加,子區(qū)間也是同樣的道理,所以從1開始蒙兰,用一個miss來表示1開始的區(qū)間覆蓋不到的第一個,如果miss>=某個元素nums[i]就證明區(qū)間連上了梭伐,覆蓋不到的就是nums[i]+miss了痹雅,并檢查下個元素nums[i+1];如果miss<nums糊识,那肯定就要補充數(shù)了绩社,貪心就體現(xiàn)在這里了摔蓝,補充比miss大的數(shù),那miss不能被覆蓋到愉耙,補上比miss小的數(shù)贮尉,就有點吃虧了,那miss得變?yōu)槎嗌倌仄友兀勘緛砬懊嫠袛?shù)加上最多是miss-1猜谚,又加上了miss,那miss就等于2miss了赌渣。

class Solution {
    public int minPatches(int[] nums, int n) {
        int patches = 0;
        //miss找不到的時候是要翻倍的魏铅,用Int可能會發(fā)生溢出
        long miss = 1;
        int i = 0;
        while(miss <= n) {
            if(i < nums.length && miss >= nums[i]) {
                //兩個區(qū)間重疊,區(qū)間能覆蓋到num[i]+miss-1坚芜,去一個區(qū)間從i+1開始
                miss += nums[i++];

            } else {
                //補上miss這個數(shù)览芳,加上前面的數(shù)剛好能覆蓋到2miss-1
                miss += miss;
                patches ++;
            }
        }
        return patches;
    }
}

7、跳躍游戲Ⅱ -45


題目

因為做過之前跳躍游戲那道題鸿竖,在解這題的時候我還是用了相同的方法沧竟,就是由后往前來遍歷,只要能到達(dá)終點的就是好坐標(biāo)缚忧,然后遍歷某個點能到達(dá)的所有好坐標(biāo)悟泵,選出最短的跳數(shù)。

class Solution {
    public int jump(int[] nums) {
        int n = nums.length;
        int[] steps = new int[n];
        for(int i = 0; i < n; i++) {
            steps[i] = -1;
        }
        steps[n - 1] = 0;
        for(int i = n - 2; i >= 0; i--) {
            int least = -1;
            for(int j = i + nums[i]; j >= i; j--) {
                if(j <= n - 1 && steps[j] != -1) {
                    //選取跳數(shù)最少的
                    int step = steps[j] + 1;
                    if(least == -1) {
                        least = step;

                    } else if(least > step) {
                        least = step;
                    }
                }
            }
            steps[i] = least;
        }
        return steps[0];
    }
}
提交結(jié)果

很明顯這個耗時是非常不理想的搔谴,這個解法還是不夠高明魁袜。可以看到就是在代碼中是嵌套了兩層循環(huán)敦第,時間復(fù)雜度會達(dá)到O(n*n)峰弹。
其實這個題目已經(jīng)明確告訴我們是能到達(dá)終點的,所以我們從起點開始遍歷芜果,每次都跳到可到達(dá)點中能跳最遠(yuǎn)距離的點鞠呈。

class Solution {
    public int jump(int[] nums) {
        int steps = 0;
        int end = 0;
        int maxPosition = 0;
        for(int i = 0; i < nums.length - 1; i++) {
            //maxPosition表示可達(dá)點能跳躍到的最遠(yuǎn)的距離
            maxPosition = Math.max(maxPosition, nums[i] + i);
            //end表示的是當(dāng)前點一步可達(dá)的范圍邊界
            if(i == end) {
                end = maxPosition;
                steps ++;
            }
        }
        return steps;
    }
}
提交結(jié)果

這次就快很多了,因為只需要遍歷一次數(shù)組右钾,時間復(fù)雜度減低到O(n)蚁吝。

其實像貪心、回溯舀射、動態(tài)規(guī)劃這些都是思想窘茁,主要是要從題目本身出發(fā),剖析它的要求脆烟,多做題多實踐山林。貪心主要的思想就是局部最優(yōu)解,但是前提要是不會影響到下一次的選擇邢羔。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末驼抹,一起剝皮案震驚了整個濱河市桑孩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌框冀,老刑警劉巖流椒,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異明也,居然都是意外死亡宣虾,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門诡右,熙熙樓的掌柜王于貴愁眉苦臉地迎上來安岂,“玉大人,你說我怎么就攤上這事帆吻∮蚰牵” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵猜煮,是天一觀的道長次员。 經(jīng)常有香客問我,道長王带,這世上最難降的妖魔是什么淑蔚? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮愕撰,結(jié)果婚禮上刹衫,老公的妹妹穿的比我還像新娘。我一直安慰自己搞挣,他們只是感情好带迟,可當(dāng)我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著囱桨,像睡著了一般仓犬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上舍肠,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天搀继,我揣著相機與錄音,去河邊找鬼翠语。 笑死叽躯,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的肌括。 我是一名探鬼主播险毁,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了畔况?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤慧库,失蹤者是張志新(化名)和其女友劉穎跷跪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體齐板,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡吵瞻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了甘磨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片橡羞。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖济舆,靈堂內(nèi)的尸體忽然破棺而出卿泽,到底是詐尸還是另有隱情,我是刑警寧澤滋觉,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布签夭,位于F島的核電站,受9級特大地震影響椎侠,放射性物質(zhì)發(fā)生泄漏第租。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一我纪、第九天 我趴在偏房一處隱蔽的房頂上張望慎宾。 院中可真熱鬧,春花似錦浅悉、人聲如沸趟据。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽之宿。三九已至,卻和暖如春苛坚,著一層夾襖步出監(jiān)牢的瞬間比被,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工泼舱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留等缀,地道東北人。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓娇昙,卻偏偏與公主長得像尺迂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,543評論 2 349

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