面试题57:
问题:
给定一个整数数组ums和两个正数k、t,请判断是否存在两个不同的下标和满足i和j之差的绝对值不大于给定的k,并且两个数值nums[i和nums[j]的差的绝对值不大于给定的t。
解决方案:
使用TreeSet作为数据容器,因为需要从一个大小为k的数据容器中找出小于或等于某个数字的最大值及大于或等于某个数字的最小值,逐一扫描数组中的每个数字,对于每个nums[i]来说,应该先从它前面k个数字中找出小于或者等于nums[i]的最大的数字,如果该数字与nums[i]的差的绝对值不大于t,则返回true,反之返回false。否则,先从它前面k个数字中找出大于或者等于nums[i]的最小的数字,如果该数字与nums[i]的差的绝对值不大于t,则返回true,反之返回false。
源代码:
class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int indexDiff, int valueDiff) {
TreeSet<Long> set = new TreeSet<>();
for(int i = 0;i < nums.length;i++){
Long lower = set.floor((long)nums[i]);
if(lower != null && lower >= (long)nums[i] - valueDiff){
return true;
}
Long upper = set.ceiling((long)nums[i]);
if(upper != null && upper <= (long)nums[i] + valueDiff){
return true;
}
set.add((long)nums[i]);
if(i >= indexDiff){
set.remove((long)nums[i-indexDiff]);
}
}
return false;
}
}
面试题58:
问题:
实现该类的book(int start, int end)在日程表中添加一个时间区域为[start,end)的事项(这是一个半开半闭区间)。
解决方案:
使用TreeMap作为数据容器。将时间区域的开始时间作为映射的键,把结束时间作为映射的值。
源代码:
class MyCalendar {
TreeMap<Integer,Integer> events;
public MyCalendar() {
events = new TreeMap<>();
}
public boolean book(int start, int end) {
Map.Entry<Integer,Integer> event = events.floorEntry(start);
if(event != null && event.getValue() > start){
return false;
}
event = events.ceilingEntry(start);
if(event != null && event.getKey() < end){
return false;
}
events.put(start,end);
return true;
}
}