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

 

posted on 2021-10-25 17:24  yuluoxingkong  阅读(69)  评论(0编辑  收藏  举报