【數學】B080_LC_絕對值表達式的最大值(表達式的符號分類)

一、Problem

Given two arrays of integers with equal lengths, return the maximum value of:

|arr1[i] - arr1[j]| + |arr2[i] - arr2[j]| + |i - j|

where the maximum is taken over all 0 <= i, j < arr1.length.

Input: arr1 = [1,2,3,4], arr2 = [-1,4,5,6]
Output: 13

Constraints:

2 <= arr1.length == arr2.length <= 40000
-10^6 <= arr1[i], arr2[i] <= 10^6

二、Solution

方法一:枚舉

這題實際上是求兩個點之間的三維曼哈頓距離最大值:

xixj+yiyj+zizj=xixj+yiyj+ij|x_i - x_j| + |y_i - y_j| + |z_i - z_j| = |x_i - x_j| + |y_i - y_j| + |i - j|
而絕對值去掉之後,數字前的符號可歸納爲 8 種情況:

1. xi + yi + zi 
2. xi - yi + zi
3. xi - yi - zi
   ...
   ...
8.-xi - yi - zi

對於整個表示式子,我們肯定要取最大值,而對於下標爲 i,或者 j,我們是不能定 si 說,xix_i 最大,yiy_i 最小就能使整個式子最大,因爲 xix_i 爲負數,yiy_i 爲正數也可,所以我們需要對每一種符號情況都嘗試枚舉一遍數組 x、y,求出每一種符號下的最大值

class Solution {
    final static int d[][] = {{1,1,1}, {1,1,-1}, {1,-1,-1}, {1,-1,1}, {-1,1,-1}, {-1,-1,1}, {-1,1,1}, {-1,-1,-1}};
    public int maxAbsValExpr(int[] x, int[] y) {
        int n = x.length, INF = Integer.MIN_VALUE, mx[] = new int[8], mi[] = new int[8];
        Arrays.fill(mx, INF);
        Arrays.fill(mi, -(INF+1));
        
        for (int k = 0; k < 8; k++)
        for (int i = 0; i < n; i++) {
            mx[k] = Math.max(mx[k], d[k][0] * x[i] + d[k][1] * y[i] + d[k][2] * i);
        }
        
        for (int k = 0; k < 8; k++)
        for (int j = 0; j < n; j++) {
            mi[k] = Math.min(mi[k], d[k][0] * x[j] + d[k][1] * y[j] + d[k][2] * j);
        }

        int ans = INF;
        for (int i = 0; i < 8; i++)
            ans = Math.max(ans, mx[i] - mi[i]);
        return ans;
    }
}

iji、j 在兩個循環中的時機意義是一樣的,所以可以合併兩個循環。

class Solution {
    final static int d[][] = {{1,1,1}, {1,1,-1}, {1,-1,-1}, {1,-1,1}, {-1,1,-1}, {-1,-1,1}, {-1,1,1}, {-1,-1,-1}};
    public int maxAbsValExpr(int[] x, int[] y) {
        int n = x.length, INF = Integer.MIN_VALUE, mx[] = new int[8], mi[] = new int[8];
        Arrays.fill(mx, INF);
        Arrays.fill(mi, -(INF+1));
        
        for (int k = 0; k < 8; k++)
        for (int i = 0; i < n; i++) {
            mx[k] = Math.max(mx[k], d[k][0] * x[i] + d[k][1] * y[i] + d[k][2] * i);
            mi[k] = Math.min(mi[k], d[k][0] * x[i] + d[k][1] * y[i] + d[k][2] * i);
        }
        
        int ans = INF;
        for (int i = 0; i < 8; i++)
            ans = Math.max(ans, mx[i] - mi[i]);
        return ans;
    }
}

複雜度分析

  • 時間複雜度:O(n)O(n)
  • 空間複雜度:O(n)O(n)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章