“人活着就是为了贪心”——贪心算法日

406. 根据身高重建队列

假设有打乱顺序的一群人站成一个队列。 每个人由一个整数对(h, k)表示,其中h是这个人的身高,k是排在这个人前面且身高大于或等于h的人数。 编写一个算法来重建这个队列。

注意:
总人数少于1100人。

示例

输入:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]

输出:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]

由于身高矮的人对于身高高的人是不可见的,我们可以从高到矮依次按下标位置插入数据

vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(),people.end(),[](vector<int>& a,vector<int>& b){
            if(a[0]==b[0])return a[1]<b[1];
            return a[0]>b[0];
        });
        vector<vector<int>> arr;
        for(auto& p:people){
            arr.insert(arr.begin()+p[1],p);
        }
        return arr;
    }

402. 移掉K位数字

给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。

注意:

·num 的长度小于 10002 且 ≥ k。
·num 不会包含任何前导零。

若有一个三位数abc,去掉一位

·a<b>c时 显然应该去掉b

·a<b<c时 显然要去掉c

·a>b<c时 ab ac bc 中显然bc最小

所以我们每次要去掉字符串从头开始升序的最后一个字符

方法一:直接对字符串遍历k次,在原字符串的基础上修改:

void cut(string& num){
        int i=1;
        for(i=1;i<num.size();i++){
            if(num[i]>=num[i-1])continue;
            else break;
        }
        num.erase(num.begin()+i-1);
        i=0;
        while(i<num.length()&&num[i]=='0'){num.erase(num.begin());}
    }
    string removeKdigits(string num, int k) {
        string res="";
        if(num.length()<=k)return "0";
        while(k--){
            cut(num);
            if(num.length()==0)return "0";
        }
        return num;
    }

方法二:维护一个最小栈

class Solution {
public:
    string removeKdigits(string num, int k) {
        stack<char> st;
        for(int i=0;i<num.length();i++){
            if(st.empty()||k==0){
                if(!(st.empty()&&num[i]=='0'))
                    st.push(num[i]);
            }
            else{
                if(num[i]>=st.top())st.push(num[i]);
                else{
                    while(k&&!st.empty()&&num[i]<st.top()){
                        st.pop();k--;
                    }
                    i--;
                }
            }
        }
        while(k--&&!st.empty())st.pop();
        if(st.empty())return "0";
        string res="";
        while(!st.empty()){
            res+=st.top();st.pop();
        }
        reverse(res.begin(),res.end());
        return res;
    }
};

1282. 用户分组

有 n 位用户参加活动,他们的 ID 从 0 到 n - 1,每位用户都 恰好 属于某一用户组。给你一个长度为 n 的数组 groupSizes,其中包含每位用户所处的用户组的大小,请你返回用户分组情况(存在的用户组以及每个组中用户的 ID)。

你可以任何顺序返回解决方案,ID 的顺序也不受限制。此外,题目给出的数据保证至少存在一种解决方案。

按组内人数分组编号,组内人数相同的都放在一组,直到这个组满,然后放下一组

class Solution {
public:
    vector<vector<int>> groupThePeople(vector<int>& groupSizes) {
        unordered_map<int, int> sizeToId;
        int id=0;
        vector<vector<int>> ans;
        for(int i=0;i<groupSizes.size();i++){
            int num=groupSizes[i];
            if(sizeToId.count(num)==0||ans[sizeToId[num]].size()==num){
                sizeToId[num]=id++;
                ans.push_back({i});
            }
            else{
                ans[sizeToId[num]].push_back(i);
            }
        }
        return ans;
    }
};

*map的insert方法不会去除重复元素

原文地址:https://www.cnblogs.com/Dancing-Fairy/p/12793548.html