领导带我刷leetcode(3)

我一直在拖着  实在是拖不下去了   我实在是不好意思  

之前跟领导狗叫了  说我一天一题...

其实这之前  领导已经打电话催我一次了  但是我搪塞过去了   这次实在是说不过去了  

没办法  赶紧回去找了题.

领导看后会利用上班时间跟我review我的题目


①无重叠区间:给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
注意:

可以认为区间的终点总是大于它的起点。
区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。
示例 1:

输入: [ [1,2], [2,3], [3,4], [1,3] ]

输出: 1

解释: 移除 [1,3] 后,剩下的区间没有重叠。
示例 2:

输入: [ [1,2], [1,2], [1,2] ]

输出: 2

解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。
示例 3:

输入: [ [1,2], [2,3] ]

输出: 0

解释: 你不需要移除任何区间,因为它们已经是无重叠的了。

:首先对区间数组按照结束位置进行升序排序  遍历后续的区间,如果当前区间的开始位置小于或等于前一个保留区间的结束位置,说明有重叠,则跳过当前区间。如果当前区间与前一个保留的区间没有重叠,则将其计入保留的区间中,并更新当前保留的区间的结束位置  最后返回需要移除的区间数量,即总区间数量减去保留的区间数量。

import java.util.*;  
  
class Solution {  
    // 给定一个Interval数组,返回移除重叠区间后剩余区间的数量  
    public int eraseOverlapIntervals(Interval[] intervals) {  
        int len = intervals.length;  
        // 如果区间数量小于等于1,则不存在重叠区间,直接返回0  
        if (len <= 1) return 0;  
  
        // 按照区间的结束位置进行升序排序  
        // 这样排序的目的是为了优先保留结束位置较早的区间,以便后续的区间有更多的空间不被重叠  
        Arrays.sort(intervals, (a, b) -> a.end - b.end);  
  
        int count = 1; // 保留的区间数量,初始化为1,因为至少有一个区间不需要被移除  
        int end = intervals[0].end; // 当前保留的区间的结束位置  
  
        // 从第二个区间开始遍历  
        for (int i = 1; i < intervals.length; i++) {  
            // 如果当前区间的开始位置小于或等于前一个保留区间的结束位置,说明有重叠  
            // 则跳过当前区间,不将其计入保留的区间中  
            if (intervals[i].start < end) {  
                continue;  
            }  
            // 如果当前区间与前一个保留的区间没有重叠,则将其计入保留的区间中  
            count++;  
            // 更新当前保留的区间的结束位置  
            end = intervals[i].end;  
        }  
  
        // 返回需要移除的区间数量,即总区间数量减去保留的区间数量  
        return len - count;  
    }  
}  
   
class Interval {  
    int start;  
    int end;  
    Interval() { start = 0; end = 0; }  
    Interval(int s, int e) { start = s; end = e; }  
}

用最少数量的箭引爆气球
在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以y坐标并不重要,因此只要知道开始和结束的x坐标就足够了。开始坐标总是小于结束坐标。平面内最多存在104个气球。
一支弓箭可以沿着x轴从不同点完全垂直地射出。在坐标x处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足 xstart ≤ x ≤ xend,则该气球会被引爆。可以射出的弓箭的数量没有限制。 弓箭一旦被射出之后,可以无限地前进。我们想找到使得所有气球全部被引爆,所需的弓箭的最小数量。
Example:
输入:
[[10,16], [2,8], [1,6], [7,12]]
输出:
2解释:
对于该样例,我们可以在x = 6(射爆[2,8],[1,6]两个气球)和 x = 11(射爆另外两个气球)。


:
本题是求不重叠区域的个数,上一题是求要删除重叠区域的个数。题中[1,2][2,3]也算是重叠区域

import java.util.Arrays;  
  
class Solution {  
    public int findMinArrowShots(int[][] points) {  
        // 如果气球数组为空或只有一个气球,则不需要射箭  
        if (points.length <= 1) {  
            return points.length;  
        }  
          
        // 按照气球的结束坐标进行排序  
        Arrays.sort(points, (a, b) -> a[1] - b[1]);  
          
        int end = points[0][1]; // 当前箭能够覆盖的最远结束坐标  
        int cnt = 1; // 箭的数量  
          
        for (int i = 1; i < points.length; i++) {  
            // 如果下一个气球的开始坐标在当前箭的覆盖范围内  
            // 则这个气球可以被当前箭引爆,不需要额外的箭  
            if (points[i][0] <= end) {  
                continue;  
            }  
            // 否则,需要额外的箭来引爆这个气球  
            end = points[i][1]; // 更新当前箭能够覆盖的最远结束坐标  
            cnt++; // 增加箭的数量  
        }  
        return cnt;  
    }  
}


455.分发饼干:
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

注意:

你可以假设胃口值为正。
一个小朋友最多只能拥有一块饼干。

示例 1:

输入: [1,2,3], [1,1]

输出: 1

解释:
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。
示例 2:

输入: [1,2], [1,2,3]

输出: 2

解释:
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.


先用量小的饼干满足胃口小的:
计数器 count 为0,用于记录可以满足的数量
两个数组都未遍历完的情况下,当前的食物可以满足当前胃口时,两个数组都向前移动,并增加计数器;如果不能满足,则只移动食物数组的指针

public int findContentChildren(int[] g, int[] s) {
        int count = 0;
        Arrays.sort(g);
        Arrays.sort(s);
        int i = 0,j = 0;
        while (i < g.length && j < s.length) {
            if (g[i] <= s[j]) {
                i ++;
                j ++;
                count ++;
            }else {
                j ++;
            }
        }
        return count;
    }

种花问题
假设你有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花卉不能种植在相邻的地块上,它们会争夺水源,两者都会死去。
给定一个花坛(表示为一个数组包含0和1,其中0表示没种植花,1表示种植了花),和一个数 n 。能否在不打破种植规则的情况下种入 n 朵花?能则返回True,不能则返回False。

示例 1:

输入: flowerbed = [1,0,0,0,1], n = 1
输出: True
示例 2:

输入: flowerbed = [1,0,0,0,1], n = 2
输出: False
注意:

数组内已种好的花不会违反种植规则。
输入的数组长度范围为 [1, 20000]。
n 是非负整数,且不会超过输入数组的大小。

思路:算出花坛中一共有几个空位,看看是否大于等于花的数量  从头到尾找到符合0 0 0情况的个数  数组两边的特殊情况处理 0 0  当长度大于1时处理即可       

class Solution {  
    public boolean canPlaceFlowers(int[] flowerbed, int n) {  
        int cnt = 0; // 计数器,记录已经放置的花的数量  
  
        // 处理特殊情况:如果花坛只有一个位置  
        if (flowerbed.length == 1 && flowerbed[0] == 0) {  
            // 如果这个位置是空的,并且只需要放置一朵或不需要花,则返回true  
            return n <= 1;  
        }  
  
        // 处理首尾位置(花坛长度大于等于2时)  
        if (flowerbed.length >= 2) {  
            // 如果花坛的第一个位置和第二个位置都是空的,可以在第一个位置放置一朵花  
            if (flowerbed[0] == 0 && flowerbed[1] == 0) {  
                flowerbed[0] = 1; // 修改花坛状态(但实际上这个修改不影响最终结果)  
                cnt++; // 计数器加1  
            }  
  
            // 如果花坛的最后一个位置和倒数第二个位置都是空的,可以在最后一个位置放置一朵花  
            if (flowerbed[flowerbed.length - 1] == 0 && flowerbed[flowerbed.length - 2] == 0) {  
                flowerbed[flowerbed.length - 1] = 1; // 修改花坛状态(但实际上这个修改不影响最终结果)  
                cnt++; // 计数器加1  
            }  
        }  
  
        // 从第二个位置开始到倒数第二个位置遍历花坛  
        for (int i = 1; i < flowerbed.length - 1; ) {  
            // 如果当前位置的前一个、当前位置和后一个位置都是空的  
            if (flowerbed[i - 1] == 0 && flowerbed[i] == 0 && flowerbed[i + 1] == 0) {  
                flowerbed[i] = 1; // 在当前位置放置一朵花(但实际上这个修改不影响最终结果)  
                cnt++; // 计数器加1  
  
                // 跳过下一个位置,因为下一个位置已经作为当前位置的后一个位置被检查过  
                i = i + 2;  
            } else {  
                // 如果当前位置不满足条件,则检查下一个位置  
                i++;  
            }  
        }  
  
        // 返回结果:如果已经放置的花的数量大于或等于需要放置的花的数量,则返回true,否则返回false  
        return cnt >= n;  
    }  
}

分类颜色
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

注意:
不能使用代码库中的排序函数来解决这道题。

进阶:

一个直观的解决方案是使用计数排序的两趟扫描算法。
首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
你能想出一个仅使用常数空间的一趟扫描算法吗?

分类颜色
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

注意:
不能使用代码库中的排序函数来解决这道题。

进阶:

一个直观的解决方案是使用计数排序的两趟扫描算法。
首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
你能想出一个仅使用常数空间的一趟扫描算法吗?:

使用三个指针:low、mid 和 high。low 指针指向当前红色区域的末尾(即下一个0应该放置的位置),mid 指针用于遍历数组,high 指针指向当前蓝色区域的开始(即下一个2应该放置的位置)。

当 nums[mid] == 0 时,我们将 nums[mid] 与 nums[low] 交换,并将 low 和 mid 都向前移动一位。
当 nums[mid] == 1 时,不需要任何操作,因为1已经在正确的位置(即红色和蓝色之间),只需要将 mid 向前移动一位。
当 nums[mid] == 2 时,我们将 nums[mid] 与 nums[high] 交换,但只将 high 向前移动一位,因为 mid 指向的元素可能是0或1,需要再次检查。

我查到的 这个解法网上说叫荷兰国旗解法   : 荷兰国旗问题(Dutch National Flag problem)的解法,这是一种仅使用常数空间的一趟扫描算法
 

public class Solution {  
    public void sortColors(int[] nums) {  
        if (nums == null || nums.length <= 1) {  
            return;  
        }  
          
        int low = 0; // 指向红色区域的末尾  
        int mid = 0; // 当前遍历的指针  
        int high = nums.length - 1; // 指向蓝色区域的开始  
          
        while (mid <= high) {  
            if (nums[mid] == 0) {  
                // 交换low和mid,并将两个指针都向前移动  
                swap(nums, low++, mid++);  
            } else if (nums[mid] == 1) {  
                // 当前元素是白色,不需要交换,mid指针向前移动  
                mid++;  
            } else {  
                // 交换mid和high,但只移动high指针  
                swap(nums, mid, high--);  
                // 这里不移动mid指针,因为交换过来的元素可能是0或1,需要再次检查  
            }  
        }  
    }  
      
    private void swap(int[] nums, int i, int j) {  
        int temp = nums[i];  
        nums[i] = nums[j];  
        nums[j] = temp;  
    }  
}


 

  • 11
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值