problem:https://leetcode.com/problems/maximum-of-absolute-value-expression/
这道题让我想到了leetcode上另一个题目:https://leetcode.com/problems/best-sightseeing-pair/, 两题都是和下标以及下标对应的数字同时有关的。
sightseeing这道题一开始并没有想到答案,最后是去评论区白嫖了一个,思路非常巧妙,原题要求的是:
求数组A中,A[ i ] + A[ j ] + i - j (i < j ) 的最大值。
可以将其转换为求 (A[ i ] + i ) + (A[ j ] - j) (i < j)的最大值。
也就是说,我们将其视为两个部分来求解。在遍历数组A的时候,我们每一轮都更新当前A[ j ] - j 的值,并同时维护A[ i ] + i 的最大值。每一轮我们都计算当前轮中 A[ j ] - j 的值加上最大值的A[ i ] + i,在所有的N(数组长度)个结果中取得最大值。
多亏了之前做过这一题,才想到周赛这题的思路,也就是拆成两部分计算。
比较麻烦的是这里有绝对值,根据高中数学,有绝对值就意味着要分类讨论,去除绝对值后就有多种可能的符号结果了。
将绝对值去掉后,要做的事情就是合并同类项,也就是把和 i 有关的放在一起,和 j 有关的放到另一边。
最终得到 S( i ) - S( j ) 形式的公式,其中S( i ) 根据绝对值去掉后有4种可能的结果。那么问题就转换为求S( i ) - S( j )的最大值了,也就是S( i ) (最大)和 S( j ) (最小)。
class Solution { public: int maxAbsValExpr(vector<int>& arr1, vector<int>& arr2) { int n = arr1.size(); vector<vector<int>> v(4, vector<int>(n)); vector<int> minnum(4, INT_MAX); vector<int> maxnum(4, INT_MIN); for(int i = 0;i < n;i++) { v[0][i] = arr1[i] + arr2[i] + i; v[1][i] = arr1[i] - arr2[i] + i; v[2][i] = -arr1[i] + arr2[i] + i; v[3][i] = -arr1[i] - arr2[i] + i; for(int j = 0;j < 4;j++) { minnum[j] = min(minnum[j], v[j][i]); maxnum[j] = max(maxnum[j], v[j][i]); } } int res = INT_MIN; for(int i = 0;i < 4;i++) { res = max(maxnum[i] - minnum[i], res); } return res; } };