zoukankan      html  css  js  c++  java
  • LeetCode406 queue-reconstruction-by-height详解

    题目详情

    假设有打乱顺序的一群人站成一个队列。 每个人由一个整数对(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]]
    

    解题思路

    此题放在贪心算法中, 是用贪心的思想来解题

    首先对数组 按照第一个元素height 降序排列
    此时 数组前面的元素的height 大于后面元素的height

    然后 以每个元素的k值 插入到返回数组里, 比如元素的k为 2, 就插到 返回数组的下标为2的位置。

    以题目的例子来进行操作

    这是原来的数组
    people = [[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]
    
    按照height进行降序排序之后
    people = [[7,0], [7,1], [6,1], [5,0], [5,2], [4,4]] 
    
    对降序后的people数组  从第一个元素开始 把每个元素加入到返回数组
    加入的策略是, 按照每个元素的k 来插入到下表为k的位置上
    
    1. 
    插入  [7,0] 
    插入到离开始位置偏移了0个距离的位置。 
    result = [[7,0]] 
    2. 
    插入  [7,1] 
    插入到离开始位置偏移了1个距离的位置,即插入到[7,0]的后面。 
    result = [[7,0], [7,1]] 
    3. 
    插入  [6,1] 
    插入到离开始位置偏移了1个距离的位置,即插入到[7,0]的后面。 
    result = [[7,0], [6,1], [7,1]] 
    4. 
    插入  [5,0] 
    插入到离开始位置偏移了0个距离的位置,即插入到[7,0]的前面。 
    result = [[5,0], [7,0], [6,1], [7,1]] 
    5. 
    插入  [5,2] 
    插入到离开始位置偏移了2个距离的位置,即插入到[7,0]的后面。 
    result = [[5,0], [7,0], [5,2], [6,1], [7,1]] 
    6. 
    插入  [4,4] 
    插入到离开始位置偏移了4个距离的位置,即插入到[6,1]的后面。 
    result = [[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]
    
    得到最终结果
    result: [[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]
    
    

    贪心证明

    把每个元素以k 插进去, 因为是按照height 来由大到小插进去的, 把元素插进第k位置, 插入后前面的height 是比当前插入元素大(因为已经插入的元素height大或者相等), 这就满足了排在前面身高大于或等于的人数为k, 但是要注意 我现在说的数组 并不是最终结果的数组, 而是插入这个元素形成的中间数组。 是相对于 中间数组来说的。

    那么有一个问题了, 最终结果里 [6,1] 前面有[5,0], [5,1], 这些height是小于6的, 但是排在[6,1]前面, 这些元素是在[6,1]加进去之后加进去的, 这些加进去的元素对 [6,1] 满足的条件(排在前面身高大于或等于的人数为k) 会有影响吗? 答案是不会的,因为在[6,1]加进去的元素的height 是小于6的 无论加在哪个地方对 [6,1]的 k 不会改变。

    综上, 此算法能求出结果

    AC代码

    class Solution {
    public:
        vector<pair<int, int>> reconstructQueue(vector<pair<int, int>>& people) {
            vector<pair<int, int>> result;
    
            //  lambda 表达式
            sort(people.begin(), people.end(), [](pair<int, int> a, pair<int, int> b){
                return a.first > b.first || (a.first == b.first && a.second < b.second);
            });
    
            for (auto i: people) {
                result.insert(result.begin() + i.second, i);
            }
            return result;
        }
    };
    
    

    总结

    因为在前面贪心的过程中 插入的元素不会对前面已经插入元素的k造成印象, 所以才能贪心, 否则 就可能用到其他的方法来解题了。

  • 相关阅读:
    Github进不去解决方法
    微信小程序中使用iconfont的方法
    curl实现SFTP上传下载文件
    curl实现SFTP上传下载文件
    curl不支持sftp的解决方法
    sscanf遇到回车换行认为字符串结束,怎样让它忽略这些回车换行继续搜索整个字符串?
    史上最全阿里 Java 面试题总结及答案
    VS Code的Error: Running the contributed command: ‘_workbench.downloadResource‘ failed解决
    云锵投资 2021 年 07 月简报
    看完段永平的100条思考,我终于悟出他为何这么牛…(转载)
  • 原文地址:https://www.cnblogs.com/qq874455953/p/9901047.html
Copyright © 2011-2022 走看看