1. 题目
给你两个 非递增 的整数数组 nums1 和 nums2 ,数组下标均 从 0 开始 计数。
下标对 (i, j) 中 0 <= i < nums1.length 且 0 <= j < nums2.length 。如果该下标对同时满足 i <= j 且 nums1[i] <= nums2[j] ,则称之为 有效 下标对,该下标对的 距离 为 j - i 。
返回所有 有效 下标对 (i, j) 中的 最大距离 。如果不存在有效下标对,返回 0 。
一个数组 arr ,如果每个 1 <= i < arr.length 均有 arr[i-1] >= arr[i] 成立,那么该数组是一个 非递增 数组。
例1:
输入:nums1 = [55,30,5,4,2], nums2 = [100,20,10,10,5]
输出:2
解释:有效下标对是 (0,0), (2,2), (2,3), (2,4), (3,3), (3,4) 和 (4,4) 。
最大距离是 2 ,对应下标对 (2,4) 。例2:
输入:nums1 = [2,2,2], nums2 = [10,10,1]
输出:1
解释:有效下标对是 (0,0), (0,1) 和 (1,1) 。
最大距离是 1 ,对应下标对 (0,1) 。
2. 3种解题方法:
(1)暴力解法
直接使用双重循环去进行最大值的寻找,但使用此方法时,要考虑时间复杂度问题,单纯的使用双从循环会超出时间限制,因此此处nums2出的判断就进行了简化。代码展示:
class Solution {
public int maxDistance(int[] nums1, int[] nums2) {
int max=0;
for(int i=0;i<nums1.length;i++){
for(int j=i+max;j<nums2.length;j++){
if(nums1[i]<=nums2[j]){
int cha=j-i;
if(cha>max){
max=cha;
}
}else{
break;
}
}
}
return max;
}
}
(2)双指针解法
此题还可进行双指针处理,通过遍历nums1每一位与nums2的对应位进行比较,遍历长度更短,例如i为0时,nums1显示的是下标为0的第一位,分别与nums2的每位比较,当比到nums1大于nums2的之时,后续将不再进行比较,直接让nums1的第二位即下标为1的数字跟nums2的第二位及之后的每一位进行比较,过程你与第一位数字比较方式相似。代码展示:
class Solution {
public int maxDistance(int[] nums1, int[] nums2) {
int i=0,j=0,maxDistance=0;
while(i<nums1.length){
if(j>nums2.length-1 || nums1[i]>nums2[j]){
i++;
j=i+maxDistance;
}else{
if(maxDistance<(j-i)){
maxDistance=j-i;
}
j++;
}
}
return maxDistance;
}
}
(3)二分查找解法
使用二分查找将left与nums1下标数进行绑定,right与nums2的范围绑定,使用两者的中间值进行最后一位大于nums1的下标数查找,然后进行最大距离的计算。代码展示:
class Solution {
public int maxDistance(int[] nums1, int[] nums2) {
int maxDistance=0;
for(int i=0;i<nums1.length;i++){
int left=i;
int right=nums2.length-1;
if(nums2.length-i<maxDistance){
break;
}
while(left<=right){
int mid=(left+right)>>1;
if(nums2[mid]>=nums1[i]){
left=mid+1;
if(maxDistance<(mid-i)){
maxDistance=mid-i;
}
}else{
right=mid-1;
}
}
}
return maxDistance;
}
}