leetcode 贪心系列

啊,找工作快要虐死我了啊,笔试都过不了要死惹,我好不容易把BFS、DFS弄会了,后面遇到的笔试题全都是贪心啊,是要整死我啊,哭唧唧。
为什么正经笔试的时候永远就A出不来啊,只能过百分之几十的这种。怕是要找不到工作惹。

452. Minimum Number of Arrows to Burst Balloons

There are a number of spherical balloons spread in two-dimensional space. For each balloon, provided input is the start and end coordinates of the horizontal diameter. Since it’s horizontal, y-coordinates don’t matter and hence the x-coordinates of start and end of the diameter suffice. Start is always smaller than end. There will be at most 104 balloons.

An arrow can be shot up exactly vertically from different points along the x-axis. A balloon with xstart and xend bursts by an arrow shot at x if xstart ≤ x ≤ xend. There is no limit to the number of arrows that can be shot. An arrow once shot keeps travelling up infinitely. The problem is to find the minimum number of arrows that must be shot to burst all balloons.
Example:

Input:
[[10,16], [2,8], [1,6], [7,12]]

Output:
2

Explanation:
One way is to shoot one arrow for example at x = 6 (bursting the balloons [2,8] and [1,6]) and another arrow at x = 11 (bursting the other two balloons).
题目大意:给出每个气球的直径,问要把所有气球都射穿,最少需要多少只箭。
解题思路:将箭的数目初始化为1,将区间按右边界从大到小排序,遍历所有区间,当区间有重叠的时候缩小边界,如果区间没有重叠,箭的数目+1
AC代码:

bool cmp(pair<int, int>a, pair<int, int>b){
        if(a.second == b.second)
            return a.first < b.first;
        return a.second > b.second;
    }
class Solution {

public:
    int findMinArrowShots(vectorint, int>>& points) {
        int count = 1;//表示箭的数目
        int n = points.size();
        if(n==0)
            return 0;
        sort(points.begin(), points.end(), cmp);
        int tmpl = points[0].first;
        int tmpr = points[0].second;
        int m = INT_MIN;
        for(int i = 1; i < points.size(); i++){
            if(points[i].first >= tmpl && points[i].first <= tmpr){
                tmpl = points[i].first;
            }
            else if(points[i].second >= tmpl && points[i].second <= tmpr)
                tmpr = points[i].second;
            else {
                tmpl = points[i].first;
                tmpr = points[i].second;
                count++;
            }
 //       cout<<"tmpl = "<//  for(int i = 0; i < points.size(); i++)
   //     cout<
  //  cout<<"m = "<
        return count;
    }
};

435. Non-overlapping Intervals

Given a collection of intervals, find the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping.

Note:
You may assume the interval’s end point is always bigger than its start point.
Intervals like [1,2] and [2,3] have borders “touching” but they don’t overlap each other.
Example 1:
Input: [ [1,2], [2,3], [3,4], [1,3] ]

Output: 1

Explanation: [1,3] can be removed and the rest of intervals are non-overlapping.
Example 2:
Input: [ [1,2], [1,2], [1,2] ]

Output: 2

Explanation: You need to remove two [1,2] to make the rest of intervals non-overlapping.
Example 3:
Input: [ [1,2], [2,3] ]

Output: 0

Explanation: You don’t need to remove any of the intervals since they’re already non-overlapping
题目大意:求最少要移除几个间隔,使得剩下的间隔无重复。
解题思路:按end值从小到大排序,如果end值相同,start值大的在前,求最大无重复集合的个数,总元素个数-最大无重复个数即为所求
AC代码:

/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */

bool cmp(Interval a, Interval b){
    if(a.end == b.end)
        return a.start > b.start;
    return a.end < b.end;
}
class Solution {
public:
    int eraseOverlapIntervals(vector& intervals) {
        sort(intervals.begin(), intervals.end(), cmp);
        int n = intervals.size();
        if(n == 0)
            return 0;
        int tmps = intervals[0].start;
        int tmpe = intervals[0].end;
        int count = 1;
        for(int i = 1; i < intervals.size(); i++){
            if(intervals[i].start >= tmpe){
                count++;
                tmpe = intervals[i].end;
            }
        }
        return n-count;
    }
};

人不能立flag,立了之后真的分分钟打脸,前两道题每道题半小时之内就写完了,交个两三把就过了,现在这道题,卡死在输出上,知道怎么判断字符串是不是满足要求,不知道怎么输出,啊,生气

767. Reorganize String

Given a string S, check if the letters can be rearranged so that two characters that are adjacent to each other are not the same.

If possible, output any possible result. If not possible, return the empty string.

Example 1:

Input: S = “aab”
Output: “aba”
Example 2:

Input: S = “aaab”
Output: “”
题目大意:判断给出的字符串能否写成相同字符不相邻的字符串,如果不能,就输出空,否则就输出相同字符不相邻的字符串。
解题思路:统计每个字符出现的次数,找出字符出现最多的次数,如果出现最多的次数比剩下的所有字母出现次数的总和+1还要大,那么这个字符串无法使相同字母不相邻,输出空串,否则就把字符串变化成相同字母不相邻的字符串输出。
我就是卡在最后输出这部分,自己怎么也写不出来,最后借鉴了leetcode上其他人的解法,人家使用的是优先队列,AC了。
输出部分理解还不是很透彻,明天再仔细看看。
代码如下:

struct cmp {
    bool  operator()(pair<char, int >&x, pair<char, int>&y){
        return x.second < y.second;
    }
};
class Solution {
public:
    string reorganizeString(string S) {
        unordered_map<char, int> m;
        for(int i = 0;  i < S.size(); i++){
            m[S[i]]++;
        }
        priority_queuechar, int>, vectorchar, int>>,cmp> q;
        int max = INT_MIN,rest = 0;
        for(unordered_map<char, int>::iterator it = m.begin(); it != m.end(); ++it){
            q.push({it->first, it->second});
            if(it->second > max){
                max = it->second;
            }
            rest += it->second;
        }
        rest -= max;
        string res;
        if(max > rest + 1)
            return res;   
        pair<char, int> last;
        /*输出部分的思路:使用优先队列存储m的值,优先队列保证字母出现次数最多的在队首,先将出现次数最多的前两个字符放入结果字符串中,再将次数大于1的字符从新放入优先队列中,每次都将队首元素取出存入结果字符串*/
        for(int i = 0; i < S.size(); i++){
            auto now = q.top();
            res.push_back(now.first);
            q.pop();
            if(i) q.push(last);
                now.second--;
            last = now;
        }
        return res;
    }
};

392. Is Subsequence

Given a string s and a string t, check if s is subsequence of t.

You may assume that there is only lower case English letters in both s and t. t is potentially a very long (length ~= 500,000) string, and s is a short string (<=100).

A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, “ace” is a subsequence of “abcde” while “aec” is not).

Example 1:
s = “abc”, t = “ahbgdc”

Return true.

Example 2:
s = “axc”, t = “ahbgdc”

Return false.

Follow up:
If there are lots of incoming S, say S1, S2, … , Sk where k >= 1B, and you want to check one by one to see if T has its subsequence. In this scenario, how would you change your code?

Credits:
Special thanks to @pbrother for adding this problem and creating all test cases.
题目大意:判断s是不是t的子串,如果是返回true,否则返回false;
解题思路:一开始想的是把s和t分别排序,然后用find函数查找t中是否包含s,这个思路是错误的,比如s = acb, t = ahbgdc,s就不是t 的子串,因为子串每个字母出现的顺序是有影响的。
正确的思路是分别用两个索引指向s,t,如果当前s[i] = t[j], s和t的索引分别加1,否则就只有t的索引加一,如果最终s的索引值>=s.size(),表示s是t 的子串,返回true;否则返回false

class Solution {
public:
    bool isSubsequence(string s, string t) {
        int i = 0, j = 0;
        while( i < s.size() && j < t.size()){
            if(t[j] == s[i]){
       //         cout<<"t[j] = "<
                ++i;
                ++j;
            }
            else{
                ++j;
            }
        }
 //   cout<
        if(i < s.size())
            return false;
        return true;
    }
};

你可能感兴趣的:(leetcode,贪心)