1131-绝对值表达式的最大值

Raphael Liu Lv10

给你两个长度相等的整数数组,返回下面表达式的最大值:

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

其中下标 ij 满足 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|,直接上双重循环的暴力解即可,然而数据规模较大,结果超时。

Python代码实现:

[-Python]
1
2
3
4
5
6
7
8
9
10
11
12
class Solution(object):
def maxAbsValExpr(self, arr1, arr2):
"""
:type arr1: List[int]
:type arr2: List[int]
:rtype: int
"""
res = 0
for i in range(len(arr1)):
for j in range(len(arr2)):
res = max(res, abs(arr1[i] - arr1[j]) + abs(arr2[i] - arr2[j]) + abs(i - j))
return res

复杂度分析:

时间复杂度:O(N^2)

空间复杂度:O(1)

第二种思路 - 数学解

分析:

既然暴力解不可行,那么我们就需要思考有没有更好的办法,已知要求 |arr1[i] - arr1[j]| + |arr2[i] - arr2[j]| + |i - j| 的最大值,我们可以先考虑一下子问题的求解:

  1. 子问题 1.|arr1[i] - arr1[j]| 的最大值

    这就比较简单了,可以直观地看出来答案,一个数组 arr1 里两个元素差的绝对值的最大值,应该等于 max(arr1) - min(arr1)

  2. 子问题 2.|arr1[i] - arr1[j]| + |i - j| 的最大值

    比上一题复杂了一点,观察并不能得出答案,因此,不妨把表达式的绝对值符号去掉,看看展开后会得到怎样的结果:

    1
    2
    3
    4
    5
    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

    因为 ij 是可以互换的,所以式 1 等价于式 4, 式 2 等价于式 3,因此可以得到:

    1
    2
    3
    4
    abs( arr1[i] - arr1[j]) + abs(i - j) 
    = (arr1[i] + i) - (arr1[j] + j) ------式1
    = (arr1[i] - i) - (arr1[j] - j) ------式2

    现在不难发现, 原始表达式的值只取决于两个中间表达式:

    中间表达式 A = arr1[i] + i

    中间表达式 B = arr1[i] - i

    所以有:

    1
    2
    3
    4
    5
    max(abs( arr1[i] - arr1[j]) + abs(i - j) )
    = max((arr1[i] + i) - (arr1[j] + j),
    (arr1[i] - i) - (arr1[j] - j))
    = max( max(A) - min(A),
    max(B) - min(B))

    因此,不难得到子问题的求解代码如下:

    [-Python]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Solution(object):
    def maxAbsValExpr(self, arr1, arr2):
    """
    :type arr1: List[int]
    :type arr2: List[int]
    :rtype: int
    """
    A = []
    B = []
    for i, x in enumerate(arr1):
    A.append(x + i)
    B.append(x - i)
    return max(max(A) - min(A), max(B) - min(B))

现在已经知道了子问题如何求解,那么本题也可以采用相同的解法,首先把绝对值符号去掉,展开表达式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|arr1[i] - arr1[j]| + |arr2[i] - arr2[j]| + |i - j|

= (arr1[i] + arr2[i] + i) - (arr1[j] + arr2[j] + j)
= (arr1[i] + arr2[i] - i) - (arr1[j] + arr2[j] - j)
= (arr1[i] - arr2[i] + i) - (arr1[j] - arr2[j] + j)
= (arr1[i] - arr2[i] - i) - (arr1[j] - arr2[j] - j)
= -(arr1[i] + arr2[i] + i) + (arr1[j] + arr2[j] + j)
= -(arr1[i] + arr2[i] - i) + (arr1[j] + arr2[j] - j)
= -(arr1[i] - arr2[i] + i) + (arr1[j] - arr2[j] + j)
= -(arr1[i] - arr2[i] - i) + (arr1[j] - arr2[j] - j)

因为存在四组两两等价的展开,所以可以优化为四个表达式:
A = arr1[i] + arr2[i] + i
B = arr1[i] + arr2[i] - i
C = arr1[i] - arr2[i] + i
D = arr1[i] - arr2[i] - i

max( |arr1[i] - arr1[j]| + |arr2[i] - arr2[j]| + |i - j|)
= max(max(A) - min(A),
max(B) - min(B),
max(C) - min(C),
max(D) - min(D))

Python代码实现:

[-Python]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution(object):
def maxAbsValExpr(self, arr1, arr2):
"""
:type arr1: List[int]
:type arr2: List[int]
:rtype: int
"""
A, B, C, D= [], [], [], []
for i in range(len(arr1)):
x, y = arr1[i], arr2[i]
A.append(x + y + i)
B.append(x + y - i)
C.append(x - y + i)
D.append(x - y - i)

a = max(A) - min(A)
b = max(B) - min(B)
c = max(C) - min(C)
d = max(D) - min(D)
return max(a, b, c, d)

复杂度分析:

时间复杂度:O(N)

空间复杂度:O(N)

优化分析:

其实,并没有必要储存所有的 ·A,B,C,D· 表达式的值,

因为我们需要的仅仅是 ·A,B,C,D· 表达式的最大值和最小值,

因此可以用八个变量替代四个数组,将空间优化到 O(1)。

 Comments
On this page
1131-绝对值表达式的最大值