Leetcode-Java(三十一)

303. Range Sum Query - Immutable

用一個(gè)數(shù)組保存從0到當(dāng)前位置的和。

class NumArray {
    int[] sumnums;
    public NumArray(int[] nums) {
        
        if(nums.length==0)
            return;
        sumnums = new int[nums.length];
        sumnums[0] = nums[0];
        for(int i=1;i<nums.length;i++){
            sumnums[i] = sumnums[i-1] + nums[I];
        }
    }
    
    public int sumRange(int i, int j) {
        if(i==0)
            return sumnums[j];
        return sumnums[j] - sumnums[i-1];
    }
}

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray obj = new NumArray(nums);
 * int param_1 = obj.sumRange(i,j);
 */

304. Range Sum Query 2D - Immutable

借鑒303題的思路,同樣構(gòu)造一個(gè)求和的矩陣,行列關(guān)系共分為四種寞忿,需要仔細(xì)分析每種情況下的計(jì)算:

class NumMatrix {
    int[][] summatrix;
    public NumMatrix(int[][] matrix) {
        if(matrix==null || matrix.length==0)
            return;   
        summatrix = new int[matrix.length][matrix[0].length];
        for(int i=0;i<matrix.length;i++){
            for(int j=0;j<matrix[i].length;j++){
                if(i==0 && j==0)
                    summatrix[i][j] = matrix[i][j];
                else if(i==0)
                    summatrix[i][j] = summatrix[i][j-1] + matrix[i][j];
                else if(j==0)
                    summatrix[i][j] = summatrix[i-1][j] + matrix[i][j];
                else
                    summatrix[i][j] = summatrix[i-1][j] + summatrix[i][j-1] - summatrix[i-1][j-1] + matrix[i][j];
            }
        }
    }
    
    public int sumRegion(int row1, int col1, int row2, int col2) {
        if(row1==0 && col1==0)
            return summatrix[row2][col2];
        else if(row1==0)
            return summatrix[row2][col2] - summatrix[row2][col1-1];  
        else if(col1==0)
            return summatrix[row2][col2] - summatrix[row1-1][col2];
        else
            return summatrix[row2][col2] - summatrix[row1-1][col2] - summatrix[row2][col1-1] + summatrix[row1-1][col1-1];
    }
}

/**
 * Your NumMatrix object will be instantiated and called as such:
 * NumMatrix obj = new NumMatrix(matrix);
 * int param_1 = obj.sumRegion(row1,col1,row2,col2);
 */

307. Range Sum Query - Mutable

這里同303題,用另一個(gè)數(shù)組保存了原數(shù)組中每個(gè)元素的值,每次更新的時(shí)候驾讲,不要忘記將該位置對(duì)應(yīng)元素的值進(jìn)行更新。

class NumArray {
    int[] sumnums;
    int[] orgnums;
    public NumArray(int[] nums) {
        if(nums==null || nums.length==0)
            return;
        sumnums = new int[nums.length];
        sumnums[0] = nums[0];
        orgnums = new int[nums.length];
        orgnums[0] = nums[0];
        for(int i=1;i<nums.length;i++){
            sumnums[i] = sumnums[i-1] + nums[I];
            orgnums[i] = nums[I];
        }
    }
    
    public void update(int i, int val) {
        for(int j=i;j<sumnums.length;j++){
            sumnums[j] += (val - orgnums[I]);
        }
        orgnums[i] = val;
    }
    
    public int sumRange(int i, int j) {
        if(i==0)
            return sumnums[j];
        return sumnums[j] - sumnums[i-1];
    }
}

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray obj = new NumArray(nums);
 * obj.update(i,val);
 * int param_2 = obj.sumRange(i,j);
 */

309. Best Time to Buy and Sell Stock with Cooldown

使用回溯法席赂,超時(shí)吮铭。。

class Solution {
    int maxProfit = 0;
    public int maxProfit(int[] prices) {
        backprop(prices,0,0,0,0);
        return maxProfit;
    }
    public void backprop(int[] prices,int start,int profit,int buyPrice,int type){
        if(start >= prices.length){
            maxProfit = Math.max(maxProfit,profit);
        }
        if(type==0){
            for(int i=start;i<prices.length;i++){
                backprop(prices,i+1,profit,prices[i],1);
            }
        }
        else if(type==1){
            for(int i=start;i<prices.length;i++){
                backprop(prices,i+2,profit + (prices[i]-buyPrice),0,0);
            }
        }
    }
}

此題需要維護(hù)三個(gè)一維數(shù)組buy, sell颅停,和rest谓晌。其中:
buy[i]表示在第i天之前最后一個(gè)操作是買,此時(shí)的最大收益癞揉。
sell[i]表示在第i天之前最后一個(gè)操作是賣纸肉,此時(shí)的最大收益。
rest[i]表示在第i天之前最后一個(gè)操作是冷凍期喊熟,此時(shí)的最大收益柏肪。

我們寫出遞推式為:

buy[i]  = max(rest[i-1] - price, buy[i-1]) 
sell[i] = max(buy[i-1] + price, sell[i-1])
rest[i] = max(sell[i-1], rest[i-1])

解讀一下,第一個(gè)公式buy[i]逊移,如果第i天可以買预吆,那么i-1天會(huì)是冷凍期,否則胳泉,不能進(jìn)行購買拐叉,因此比較rest[i-1] - price和 buy[i-1]的大小。第二個(gè)公式sell[i]扇商,可以賣的條件是凤瘦,i-1天之前最后一個(gè)操作時(shí)買入股票,否則案铺,不能賣出蔬芥,因此比較buy[i-1] + price和sell[i-1]。第三個(gè)式子,冷凍期的可能性有兩個(gè)笔诵,一個(gè)是昨天剛進(jìn)行賣的交易返吻,另一個(gè)是繼續(xù)冷凍期。

上述遞推式很好的表示了在買之前有冷凍期乎婿,買之前要賣掉之前的股票测僵。一個(gè)小技巧是如何保證[buy, rest, buy]的情況不會(huì)出現(xiàn),這是由于buy[i] <= rest[i]谢翎, 即rest[i] = max(sell[i-1], rest[i-1])捍靠,這保證了[buy, rest, buy]不會(huì)出現(xiàn)。

另外森逮,由于冷凍期的存在榨婆,我們可以得出rest[i] = sell[i-1],這樣褒侧,我們可以將上面三個(gè)遞推式精簡(jiǎn)到兩個(gè):

buy[i]  = max(sell[i-2] - price, buy[i-1]) 
sell[i] = max(buy[i-1] + price, sell[i-1]) 

因此良风,代碼如下:

class Solution {
    public int maxProfit(int[] prices) {
        if(prices==null || prices.length <2)
            return 0;
        int[] buy = new int[prices.length];
        int[] sell = new int[prices.length];
        buy[0] = -prices[0];
        buy[1] = Math.max(-prices[0],-prices[1]);
        sell[0] = 0;
        sell[1] = Math.max(0,prices[1]-prices[0]);
        for(int i=2;i<prices.length;i++){
            buy[i] = Math.max(sell[i-2] - prices[i],buy[i-1]);
            sell[i] = Math.max(buy[i-1] + prices[i],sell[i-1]);
        }
        return sell[prices.length-1];
    }
}

310. Minimum Height Trees

答案只可能有一個(gè)或兩個(gè)節(jié)點(diǎn)。思路為依次刪除葉子節(jié)點(diǎn)璃搜,剩下的1/2個(gè)節(jié)點(diǎn)即為解拖吼。
速度問題:如果每次遍歷選出葉子節(jié)點(diǎn),速度比較慢这吻,可以每次刪除當(dāng)前葉子節(jié)點(diǎn)時(shí),將新的葉子節(jié)點(diǎn)記錄下來篙议。

class Solution {
    public List<Integer> findMinHeightTrees(int n, int[][] edges) {
        List<Integer> leaves = new ArrayList<>();
        if(n <= 1) {
            return Collections.singletonList(0);
        }
        Map<Integer, Set<Integer>> graph = new HashMap<>();     // list of edges to  Ajacency Lists
        
        for(int i = 0; i < n; i++) {
            graph.put(i, new HashSet<Integer>());
        }
        for(int[] edge : edges) {
            graph.get(edge[0]).add(edge[1]);
            graph.get(edge[1]).add(edge[0]);
        }
        
        for(int i = 0; i < n; i++) {
            if(graph.get(i).size() == 1) {
                leaves.add(i);
            }
        }
        
        while(n > 2) {
            n -= leaves.size();
            List<Integer> newLeaves = new ArrayList<>();
            for(int leaf : leaves) {
                for(int newLeaf : graph.get(leaf)) {
                    graph.get(leaf).remove(newLeaf);
                    graph.get(newLeaf).remove(leaf);
                    if(graph.get(newLeaf).size() == 1) {
                        newLeaves.add(newLeaf);
                    }
                }
            }
            leaves = newLeaves;
        }
        
        return leaves;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末唾糯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子鬼贱,更是在濱河造成了極大的恐慌移怯,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件这难,死亡現(xiàn)場(chǎng)離奇詭異舟误,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)姻乓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門嵌溢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蹋岩,你說我怎么就攤上這事赖草。” “怎么了剪个?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵秧骑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng)乎折,這世上最難降的妖魔是什么绒疗? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮骂澄,結(jié)果婚禮上忌堂,老公的妹妹穿的比我還像新娘。我一直安慰自己酗洒,他們只是感情好士修,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著樱衷,像睡著了一般棋嘲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上矩桂,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天沸移,我揣著相機(jī)與錄音,去河邊找鬼侄榴。 笑死雹锣,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的癞蚕。 我是一名探鬼主播蕊爵,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼桦山!你這毒婦竟也來了攒射?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤恒水,失蹤者是張志新(化名)和其女友劉穎会放,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體钉凌,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡咧最,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了御雕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片矢沿。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖饮笛,靈堂內(nèi)的尸體忽然破棺而出咨察,到底是詐尸還是另有隱情,我是刑警寧澤福青,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布摄狱,位于F島的核電站脓诡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏媒役。R本人自食惡果不足惜祝谚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望酣衷。 院中可真熱鬧交惯,春花似錦、人聲如沸穿仪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽啊片。三九已至只锻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間紫谷,已是汗流浹背齐饮。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留笤昨,地道東北人祖驱。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像瞒窒,于是被迫代替她去往敵國和親捺僻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

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