zoukankan      html  css  js  c++  java
  • 前缀和和差分

    1.差分的基本概念:

    如果有一数列 a[1],a[2],.…a[n]
    且令 b[i]=a[i]-a[i-1],b[1]=a[1]
    
    那么就有
    a[i]=b[1]+b[2]+.…+b[i]
        =a[1]+a[2]-a[1]+a[3]-a[2]+.…+a[i]-a[i-1]
    此时b数组称作a数组的差分数组
    换句话来说a数组就是b数组的前缀和数组  例:
         原始数组a:9  3  6  2  6  8
         差分数组b:9 -6  3 -4  4  2
         可以看到a数组是b的前缀和

    那么现在有一个任务:

    在区间[left,right]上加一个常数c。
    我们可以利用原数组就是差分数组的前缀和这个特性,来解决这个问题。显然可得出公式:b[left]+=c,b[right+1]−=c

    同样如果通过以上问题让求某一区间的和,那么前缀和也同样能够完成,但是如果操作的次数过大
    那么前缀和显然会超时,但是同样有解决的方式例如 树状数组,线段树。
    相对于代码长度而言,使用差分的思想求解会变得异常简单。

    1.1.1 代表题目:1094. 拼车

     public boolean carPooling(int[][] trips, int capacity) {
            int N = 1010, maxId = 0;
            int[] diff = new int[N];
            int[] cap = new int[N];
            for (int[] t : trips) {
                maxId = Math.max(maxId, t[1]);
                diff[t[1]] += t[0];
                diff[t[2]] -= t[0];
            }
            if (diff[0] > capacity) return false;
            cap[0] = diff[0];
            for (int i = 1; i <= maxId; i++) {
                cap[i] = cap[i - 1] + diff[i];
                if (cap[i] > capacity) return false;
            }
            return true;
        }

    买卖股票的最佳时机 II

    方法一:动态规划

    public class MaxStockProfit {
        public static int maxProfit(int[] prices) {
            int len = prices.length;
            int[][] dp = new int[len][2];
            dp[0][0] = 0;
            dp[0][1] = -prices[0];
            for(int i=1; i<len; i++){
               dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]);
               dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] - prices[i]);
            }
    
            return dp[len-1][0];
        }
    
        public static int maxProfit2(int[] prices) {
            int len = prices.length;
            int dp0 = 0;
            int dp1 = -prices[0];
            for(int i=1; i<len; i++){
                dp0 = Math.max(dp0, dp1 + prices[i]);
                dp1 = Math.max(dp1, dp0 - prices[i]);
            }
    
            return dp0;
        }
    
        public static void main(String[] args) {
            int[] prices = {7,1,5,3,6};
            System.out.println(maxProfit(prices));
            System.out.println(maxProfit2(prices));
    
        }
    }

     方法二:贪心

    public static int maxProfit3(int[] prices) {
    int len = prices.length;
    int ans = 0;
    for(int i=1; i<len; i++){
    ans += Math.max(0, prices[i] - prices[i-1]);
    }
    return ans;
    }

    LeetCode 253. 会议室 II(贪心+优先队列)

    1. 题目

    给定一个会议时间安排的数组,每个会议时间都会包括开始和结束的时间 [[s1,e1],[s2,e2],…] (si < ei), 为避免会议冲突,同时要考虑充分利用会议室资源,请你计算至少需要多少间会议室,才能满足这些会议安排。

    示例 1:
    输入: [[0, 30],[5, 10],[15, 20]]
    输出: 2
    
    示例 2:
    输入: [[7,10],[2,4]]
    输出: 1

    来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/meeting-rooms-ii 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    2. 解题

    类似题目:LeetCode 252. 会议室(排序)

    • 开始时间一样,先结束的在前;开始早的在前
    • 优先队列存储会议结束的时间,堆顶是结束时间早的
    • 下一个会议开始时间早于堆顶的房间结束时间,该会议新开一个room,push进队列
    • 最后返回队列的size
  • 相关阅读:
    查找——图文翔解HashTree(哈希树)
    比較JS合并数组的各种方法及其优劣
    PTA 是否同一棵二叉搜索树(25 分)
    PTA 最大子列和问题(10 分)
    PTA PAT排名汇总(25 分)
    PTA PAT排名汇总(25 分)
    PTA 说反话-加强版(20 分)(字符串处理)
    PTA 说反话-加强版(20 分)(字符串处理)
    Tarjan模版(链式向前星表示方法)
    Tarjan模版(链式向前星表示方法)
  • 原文地址:https://www.cnblogs.com/yuluoxingkong/p/15459530.html
Copyright © 2011-2022 走看看