代码随想录算法训练营Day33|452. 用最少数量的箭引爆气球,435. 无重叠区间 , 763.划分字母区间

452. 用最少数量的箭引爆气球:代码随想录

这道题目的意思就是你可以垂直的射箭,让你用最少的箭数射完所有的气球,这样其实我们可以很容易的就想到,我们尽可能的去射重叠的气球,这样我们一支箭就可以射多支,所以这里我们可以先对数组进行一个排序,就是可以先考虑到那些重叠在一起的,这题其实题目的要求跟数组元素的顺序无关,排完序后,这里我犯了一个错误就是,我的思路都是对的,就是在判断他们两个气球是不是重叠的时候,其实只要考虑右边界end和下一个气球的左边界就可以了,因为你已经排好序了,这里我将两个气球的左右边界都考虑进去了,所以就写的很复杂,在判断完之后,记得要更新右边界,来看具体的代码的实现

class Solution {
public:
    static bool cmp(pair<int, int> a, pair<int, int> b) {
        return a.first < b.first;
    }
    int findMinArrowShots(vector<vector<int>>& points) {
        int n = points.size();
        pair<int, int> nums[n];
        for (int i = 0; i < n; i++) {
            nums[i].first = points[i][0];
            nums[i].second = points[i][1];
        }
        sort(nums, nums + n, cmp);
        int result = 1; int end = nums[0].second;
        for (int i = 1; i < n; i++) {
            if (nums[i].first <= end) {
                end = min(end, nums[i].second);
            }
            else {
                result++;
                end = nums[i].second;
            }
        }
        return result;
    }
};

在这里我用了一个pair数组,其实你也可以不用,直接用vector也可以,首先就是sort排序,然后就是一开始初始化有边界right,和结果result,只要我当前遍历的这个气球的左边界小于等于我的right,就代表我们是重叠的这样就让right=我们两个右边界的最小值,这样才是判断后面的气球是不是和前面两个重叠,如果不是重叠的,那就直接将result++,然后让我的右边界等于我下一个结点的右边界,就可以了,因为此时我肯定需要另一支箭,这就是这道题目的解答,来看下一道题目

435. 无重叠区间:代码随想录

这道题目的意思就是给你很多个区间,让你求出要去除多少个区间才能保证所有的区间都是不重叠的,其实这道题目和上一道题非常的像,只要你上一道题目弄懂了,这道题稍微改一下就可以了,我们来看具体的代码的实现,

class Solution {
public:
    static bool cmp1(vector<int> a, vector<int> b){
        return a[0] < b[0];
    }
    int eraseOverlapIntervals(vector<vector<int>>& points) {
        int n = points.size();
        sort(points.begin(),points.end(),cmp1);
        int result = 0; int end = points[0][1];
        for (int i = 1; i < n; i++) {
            if (nums[i].first < end) {
                result++;
                end=min(end,points[i][1]);
            }
            else {
                end = points[i][1];
            }
        }
        return result;
    }
};

主体的代码并没有什么变化,就是if条件判断那里有些细节需要改一下,当重叠的的时候,我们需要将结果加一,然后同样的就是将右边界与这个区间的右边界取一个最小值,那么为什么要取最小值呢,你稍微想想就知道,如果我取大的话,那么后面的是不是更容易发生重叠啊,所以这里我们就是要选取更小的那个,同样的如果说不重叠的话,那就是直接让右边界等于下一个的右边界就可以了,直到数组遍历完,再返回结果即可。下面来看第三题

763.划分字母区间:代码随想录

这道题目的意思就是给你一个字符串,让你划分一下这个字符串,你需要保证这个划分是按顺序来划分的,并且你划分的每一个子串里出现的字符只能在这个子串里出现,也就是说一个字符只能出现在一个子串里,那么,这道题目我们如何来思考呢,这里的思路比较难想,我们要确定这个子串的边界,是不是要知道这个子串里的字符最远的位置在哪里,因为可能有多个相同的字符,你需要保证他们都在同一个子串里,所以我们可以首先考虑先遍历一遍数组,将出现的每个字符的最远的位置都给记录下来,然后再遍历一遍数组,动态的来判断,当我的最远的边界等于我现在的for循环里的i时,代表这就是一个子串,然后就让left也就是左边界等于i+1,直到数组里的所有的元素全部都遍历完之后,就返回我们的结果,下面来看具体的代码的实现。

class Solution {
public:
    vector<int> partitionLabels(string s) {
        vector<int> result; int n = s.size();
        int hash[27];
        for (int i = 0; i < s.size(); i++) {
            hash[s[i] - 'a'] = i;
        }
        int left = 0; int right = 0;
        for (int i = 0; i < n; i++) {
            right = max(right, hash[s[i] - 'a']);
            if (i == right) {
                result.push_back(right - left + 1);
                left = i + 1;
            }
        }
        return result;
    }
};

这里首先就是一个哈希数组,用来记录最远的距离,然后就是定义一个子串的左右边界left,right,每次都让我的right,也就是我的右边界动态的更新,直到我的遍历的位置达到right时,就代表前面的所有字符,都只在这一个子串里面出现过。最后将(right-left+1)的值加入到结果集数组中,最后等到循环结束之后返回,数组即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值