美文网首页
Leetcode-Java(三十一)

Leetcode-Java(三十一)

作者: 文哥的学习日记 | 来源:发表于2018-07-07 23:28 被阅读100次

    303. Range Sum Query - Immutable

    用一个数组保存从0到当前位置的和。

    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题的思路,同样构造一个求和的矩阵,行列关系共分为四种,需要仔细分析每种情况下的计算:

    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题,用另一个数组保存了原数组中每个元素的值,每次更新的时候,不要忘记将该位置对应元素的值进行更新。

    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

    使用回溯法,超时。。

    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);
                }
            }
        }
    }
    

    此题需要维护三个一维数组buy, sell,和rest。其中:
    buy[i]表示在第i天之前最后一个操作是买,此时的最大收益。
    sell[i]表示在第i天之前最后一个操作是卖,此时的最大收益。
    rest[i]表示在第i天之前最后一个操作是冷冻期,此时的最大收益。

    我们写出递推式为:

    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])
    

    解读一下,第一个公式buy[i],如果第i天可以买,那么i-1天会是冷冻期,否则,不能进行购买,因此比较rest[i-1] - price和 buy[i-1]的大小。第二个公式sell[i],可以卖的条件是,i-1天之前最后一个操作时买入股票,否则,不能卖出,因此比较buy[i-1] + price和sell[i-1]。第三个式子,冷冻期的可能性有两个,一个是昨天刚进行卖的交易,另一个是继续冷冻期。

    上述递推式很好的表示了在买之前有冷冻期,买之前要卖掉之前的股票。一个小技巧是如何保证[buy, rest, buy]的情况不会出现,这是由于buy[i] <= rest[i], 即rest[i] = max(sell[i-1], rest[i-1]),这保证了[buy, rest, buy]不会出现。

    另外,由于冷冻期的存在,我们可以得出rest[i] = sell[i-1],这样,我们可以将上面三个递推式精简到两个:

    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

    答案只可能有一个或两个节点。思路为依次删除叶子节点,剩下的1/2个节点即为解。
    速度问题:如果每次遍历选出叶子节点,速度比较慢,可以每次删除当前叶子节点时,将新的叶子节点记录下来。

    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;
        }
    }
    

    相关文章

      网友评论

          本文标题:Leetcode-Java(三十一)

          本文链接:https://www.haomeiwen.com/subject/jdcsuftx.html