624. 数组列表中的最大距离
给定 m 个数组,每个数组都已经按照升序排好序了。现在你需要从两个不同的数组中选择两个整数(每个数组选一个)并且计算它们的距离。两个整数 a 和 b 之间的距离定义为它们差的绝对值 ∣ a − b ∣ |a-b| ∣a−b∣ 。你的任务就是去找到最大距离。
示例 1:
输入:
[[1,2,3],
[4,5],
[1,2,3]]
输出: 4
解释:
一种得到答案 4 的方法是从第一个数组或者第三个数组中选择 1,同时从第二个数组中选择 5 。
解法一:暴力(TLE)
思路
很容易想到。在第 i
行选最大元素,在除 i
行外的一行选最小元素;或在第 i
行选最小元素,在除 i
行外的一行选最大元素,两者相减就是最大距离。
又因为每个数组都是升序排列,所以最大距离与每个数组的第一个元素和最后一个元素有关。于是就有两层循环暴力的求最大值。
复杂度
时间复杂度: O ( N 2 ) O(N^2) O(N2), N N N 二维数组中数组的个数。
空间复杂度: O ( 1 ) O(1) O(1)
代码
class Solution {
public:
int maxDistance(vector<vector<int>>& a) {
int res = 0;
for (int i = 0; i < a.size(); i++) {
for (int j = i; j < a[i].size(); j++) {
int x = abs(a[i][0] - a[j][a[j].size() - 1]);
int y = abs(a[i][a[i].size() - 1] - a[j][0]);
res = max(res, max(x, y));
}
}
return res;
}
};`
解法二:线性扫描
思路
由方法一得知,最大距离由每一行最大值和最小值决定。如果 a 在第 i
行中选,则 b 只能在前 i - 1
行中选,若把前 i - 1
个行合并起来看为一个大行,那么只有这个大行中的最大值和最小值有效(必须拉自不同的行)和第 i
行中的最大值和最小值有效。
因为每一行升序排列,第 i
行最小值和最大值很容易得到。关键在于如何取得大行的最大值和最小值。
大行由前面的小行所构成,所以在循环到第 i
前 i - 1
的最大和最小值元素已经确定。
复杂度
时间复杂度: O ( N ) O(N) O(N)
空间复杂度: O ( 1 ) O(1) O(1)
代码
class Solution {
public:
int maxDistance(vector<vector<int>>& a) {
int n = a.size(), res = 0;
int pre_max = a[0][a[0].size() - 1], pre_min = a[0][0];
for (int i = 1; i < n; i++) {
int j = a[i].size() - 1;
int x = abs(pre_max - a[i][0]), y = abs(pre_min - a[i][j]);
res = max(res, max(x, y));
pre_max = max(pre_max, a[i][j]), pre_min = min(pre_min, a[i][0]);
}
return res;
}
};
给个 java 版本,get 我头疼。。。
class Solution {
public int maxDistance(List<List<Integer>> a) {
int n = a.size(), res = 0;
int pre_max = a.get(0).get(a.get(0).size() - 1), pre_min = a.get(0).get(0);
for (int i = 1; i < n; i++) {
int j = a.get(i).size() - 1;
int x = Math.abs(pre_max - a.get(i).get(0));
int y = Math.abs(pre_min - a.get(i).get(j));
res = Math.max(res, Math.max(x, y));
pre_max = Math.max(pre_max, a.get(i).get(j));
pre_min = Math.min(pre_min, a.get(i).get(0));
}
return res;
}
}