public class Solution {
public ArrayList<Interval> merge(ArrayList<Interval> intervals) {
ArrayList<Interval> res = new ArrayList<>();
if(intervals.size() == 0)
return res;
//重载比较,按照区间首排序
Collections.sort(intervals, new Comparator<Interval>(){
public int compare(Interval o1, Interval o2){
if(o1.start != o2.start)
return o1.start - o2.start;
else
return o1.end - o2.end;
}
});
for(int i = 1; i < intervals.size(); i++){
if(intervals.get(i).start <= intervals.get(i - 1).end){
intervals.get(i).start = Math.min(intervals.get(i - 1).start,intervals.get(i).start);
intervals.get(i).end = Math.max(intervals.get(i - 1).end,intervals.get(i).end);
}else
res.add(intervals.get(i - 1));
}
res.add(intervals.get(intervals.size() -1));
return res;
}
1,解法一
我们使用两个指针,一个i一个j,最开始的时候i和j指向第一个元素,然后i往后移,把扫描过的元素都放到map中,如果i扫描过的元素没有重复的就一直往后移,顺便记录一下最大值max,如果i扫描过的元素有重复的,就改变j的位置,我们就以pwwkew(这是之前画的图,求的是字符串,不是数字,这里就拿来用了,原理都是一样的)为例画个图看一下
public int maxLength(int[] arr) {
if (arr.length == 0)
return 0;
HashMap<Integer, Integer> map = new HashMap<>();
int max = 0;
for (int i = 0, j = 0; i < arr.length; ++i) {
if (map.containsKey(arr[i])) {
j = Math.max(j, map.get(arr[i]) + 1);
}
map.put(arr[i], i);
max = Math.max(max, i - j + 1);
}
return max;
}
2,解法二
我们还可以用一个队列,把元素不停的加入到队列中,如果有相同的元素,就把队首的元素移除,这样我们就可以保证队列中永远都没有重复的元素
public int maxLength(int[] arr) {
//用链表实现队列,队列是先进先出的
Queue<Integer> queue = new LinkedList<>();
int res = 0;
for (int c : arr) {
while (queue.contains(c)) {
//如果有重复的,队头出队
queue.poll();
}
//添加到队尾
queue.add(c);
res = Math.max(res, queue.size());
}
return res;
}
解法3,使用set来模仿队列解法
public int maxLength(int[] arr) {
int left = 0, right = 0, max = 0;
Set<Integer> set = new HashSet<>();
while (right < arr.length) {
if (set.contains(arr[right])) {
set.remove(arr[left++]);
} else {
set.add(arr[right++]);
max = Math.max(max, set.size());
}
}
return max;
}
class Solution {
public int maxArea(int[] height) {
int max = 0;
/*暴力枚举:超时
for(int i = 0; i < height.length - 1; i++){
for(int j = i + 1; j < height.length; j++){
int h = Math.min(height[i],height[j]);
max = Math.max(max,h * (j - i));
}
}
*/
//双指针 面积由两指针高度最小的那个和两指针间的距离决定,所以可将高度最小的往内部移动
//(如果移动最大的那个指针,他面积一定是缩小,所以选择移动高度矮的指针)
int l = 0,r = height.length - 1;
while(l < r){
int h = Math.min(height[l],height[r]);
max = Math.max(max,h * (r - l));
if(height[l] < height[r]) l++;
else r--;
}
return max;
}
}
public static long maxWater(int[] arr) {
if (arr == null || arr.length <= 2) {
return 0;
}
int left = 0, right = arr.length - 1;
long sum = 0;
// 找出左右边界的最小值作为水位高度
int mark = Math.min(arr[left], arr[right]);
while (left < right) {
// 如果左边较低,则左边界向右遍历, 否则右边界向左移动
if (arr[left] < arr[right]) {
left++;
// 如果当前标尺小于水位,则水量累加
if (arr[left] < mark) {
sum += mark - arr[left];
} else { // 否则,将此标尺和右边边界高度进行比较,找出剩下数组中的新水位
mark = Math.min(arr[left], arr[right]);
}
} else {
right--;
// 同理,如果当前标尺小于水位,则水量累加
if (arr[right] < mark) {
sum += mark - arr[right];
} else { // 否则,将此标尺和左边界的高度进行比较,找出剩余数组中的新水位
mark = Math.min(arr[right], arr[left]);
}
}
}
return sum;
}