题目
给定一个有序数组arr,代表坐落在X轴上的点;给定一个正数K,代表绳子的长度;返回绳子最多压中几个点?即使绳子边缘处盖住点也算盖住
先贪心后优化思路
先假设每一个点都是绳子末尾点,也就是绳子的最右点,根据绳长往左推,查看绳子盖住了多少点。
所谓的贪心是指,绳子的末尾点不必盖住一个不存在的点,只需盖住实点的位置,继而往前推。
举例假设
假如给定一个有序数组,绳长100,绳子的末尾点来到了973,那么开头点最多来到873(误区:不是874,因为绳子前后边缘部分盖住的都算)。
那么查找有多少个实点是大于等于873,数量+1(因为973也是一个实点)就是答案。
时间复杂度
怎么查找呢?
二分查找
在一个有序数组里,查找大于等于873,用二分查找法。
把每一个实点都当作是绳子的末尾点,每一次查找都来一个二分,每一次的时间复杂度都是logN,那么总体的时间复杂度是
O(N*logN)
双指针
左右指针,类似滑动窗口,当left来到第1个位置,right指针根据绳长,依次向右滑动,直至到达绳子的尾端。
left和right指针一直往前走,不会后退,那么时间复杂度是O(N)
package demo;
public class One {
public int maxPoints(int[] arr,int L) {
int left=0;
int right=0;
int max=0;
// 用while循环,每一次都要比较max
while(left<arr.length) {
// 当右指针小于数组长度,且,左右指针间隔距离《=L,右指针才能继续移动
while(right<arr.length&&arr[right]-arr[left]<=L) {
right++;
}
// 当移动到不能再移动的时候,这一次的移动和上一次的移动距离作比较
// 左指针移动一位
// max=Math.max(max, right-(left++));
max=Math.max(max, right-left);
left++;
// System.out.println("right"+right);
}
return max;
}
public static void main(String[] args) {
One one=new One();
int[] arrs= {2,4,5,8,9,12,14,15,16,17,18,20};
// 长度为4的可以盖住5个连续的点
int l=4;
System.out.println(one.maxPoints(arrs, l));
}
}