给出两个长度相等的整数数组,返回下面表达式的最大值:
|arr1[i] - arr1[j]| + |arr2[i] - arr2[j]| + |i - j|
其中下标 i,j 满足 0 <= i, j < arr1.length。
示例 1:
输入:arr1 = [1,2,3,4], arr2 = [-1,4,5,6]
输出:13
示例 2:
输入:arr1 = [1,-2,-5,0,10], arr2 = [0,-2,-1,-7,-4]
输出:20
提示:
2 <= arr1.length == arr2.length <= 40000
-10^6 <= arr1[i], arr2[i] <= 10^6
分析:
逐个遍历很耗时也复杂,那么就需要思考有没有更好的办法,已知要求 |arr1[i] - arr1[j]| + |arr2[i] - arr2[j]| + |i - j| 的最大值,我们可以先考虑一下子问题的求解:
子问题 1. 求 |arr1[i] - arr1[j]| 的最大值
这就可以直观地看出来答案,一个数组 arr1 里两个元素差的绝对值的最大值,应该等于 max(arr1) - min(arr1)
子问题 2. 求 |arr1[i] - arr1[j]| + |i - j| 的最大值
比上一题复杂了一点,观察并不能得出答案,因此,把表达式的绝对值符号去掉,看看展开后会得到怎样的结果:
abs( arr1[i] - arr1[j]) + abs(i - j)
= arr1[i] - arr1[j] + i - j = (arr1[i] + i) - (arr1[j] + j) // 式1
= arr1[i] - arr1[j] - i + j = (arr1[i] - i) - (arr1[j] - j) // 式2
= -arr1[i] + arr1[j] + i - j = -(arr1[i] - i) + (arr1[j] - j) // 式3
= -arr1[i] + arr1[j] - i + j = -(arr1[i] + i) + (arr1[j] + j) // 式4
因为 i 和 j 是可以互换的,所以式 1 等价于式 4, 式 2 等价于式 3,因此可以得到:
abs( arr1[i] - arr1[j]) + abs(i - j)
= (arr1[i] + i) - (arr1[j] + j) ----- 式1
= (arr1[i] - i) - (arr1[j] - j) ----- 式2
观察发现,原始表达式的值只取决于两个中间表达式:
中间表达式 X = arr1[i] + i
中间表达式 Y = arr1[i] - i
所以,有:
max(abs( arr1[i] - arr1[j]) + abs(i - j) )
= max((arr1[i] + i) - (arr1[j] + j),
(arr1[i] - i) - (arr1[j] - j))
= max( max(X) - min(X),
max(Y) - min(Y))
package com.loo;
public class MaxAbsValue {
public static void main(String[] args) {
int[] arr1 = {1,2,3,4}, arr2 = {-1,4,5,6};
int[] arr3 = {1,-2,-5,0,10}, arr4 = {0,-2,-1,-7,-4};
System.out.println(getMaxAbsValue(arr3 , arr4));
}
public static int getMaxAbsValue(int[] arr1 , int[] arr2) {
int max_a , max_b , max_c , max_d , min_a , min_b , min_c , min_d;
max_a = max_b = max_c = max_d = Integer.MIN_VALUE;
min_a = min_b = min_c = min_d = Integer.MAX_VALUE;
int a,b,c,d;
for (int i=0;i<arr1.length;i++) {
a = arr1[i] + arr2[i] + i;
b = arr1[i] + arr2[i] - i;
c = arr1[i] - arr2[i] + i;
d = arr1[i] - arr2[i] - i;
min_a = Math.min(min_a, a);
min_b = Math.min(min_b, b);
min_c = Math.min(min_c, c);
min_d = Math.min(min_d, d);
max_a = Math.max(max_a, a);
max_b = Math.max(max_b, b);
max_c = Math.max(max_c, c);
max_d = Math.max(max_d, d);
}
a = max_a - min_a;
b = max_b - min_b;
c = max_c - min_c;
d = max_d - min_d;
return Math.max(Math.max(a, b), Math.max(c, d));
}
}