前缀和和差分

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

 

上一篇:leetcode1094. 拼车「拼车」


下一篇:(转)Linux 文本对比 diff 命令详解(整理)