首页 > 其他分享 >【LeetCode贪心#08】根据身高重建队列(还是涉及处理两个维度的信息)

【LeetCode贪心#08】根据身高重建队列(还是涉及处理两个维度的信息)

时间:2023-03-17 23:00:39浏览次数:67  
标签:people 08 list 插入 vector que 身高 LeetCode 贪心

根据身高重建队列

力扣题目链接(opens new window)

假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。

请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。

示例 1:

  • 输入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
  • 输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
  • 解释:
    • 编号为 0 的人身高为 5 ,没有身高更高或者相同的人排在他前面。
    • 编号为 1 的人身高为 7 ,没有身高更高或者相同的人排在他前面。
    • 编号为 2 的人身高为 5 ,有 2 个身高更高或者相同的人排在他前面,即编号为 0 和 1 的人。
    • 编号为 3 的人身高为 6 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。
    • 编号为 4 的人身高为 4 ,有 4 个身高更高或者相同的人排在他前面,即编号为 0、1、2、3 的人。
    • 编号为 5 的人身高为 7 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。
    • 因此 [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] 是重新构造后的队列。

示例 2:

  • 输入:people = [[6,0],[5,0],[4,0],[3,2],[2,2],[1,4]]
  • 输出:[[4,0],[5,0],[2,2],[3,2],[1,4],[6,0]]

提示:

  • 1 <= people.length <= 2000
  • 0 <= hi <= 10^6
  • 0 <= ki < people.length

题目数据确保队列可以被重建

思路

乍一看题目没看懂,感觉需要考虑的要素很多

举个例子:[7,0]

意思就是当前这个人身高是7,前面有0个身高更高或者相同的人

然后题目要求我们对people数组进行排序,并满足对应要求,即上面这个[7,0]在排序后的位置必须满足:当前这个人身高是7,前面有0个身高更高或者相同的人

此时有两个元素需要考虑,即**当前的身高 h 前面有几个相同身高的人 k **

参考发糖果,涉及两个维度时,需要分别处理

以 示例1 来讲

  • 输入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
  • 输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]

可以先针对身高进行排序,结果如下:

[[7,0], [7,1], [6,1], [5,0], [5,2],[4,4]]

这里需要自定义sort的排序规则,详见

排序逻辑:显然,我们希望先比较身高h,如果身高相同就比较k

然后使用 k 作为下标,将数组插入到对应位置,模拟过程如下:

定义一个新数组(后续会改用链表)

  • 插入[7,0]:[[7,0]]

  • 插入[7,1]:[[7,0],[7,1]]

  • 插入[6,1]:[[7,0],[6,1],[7,1]]

    (身高为6,前面只能有1个大于等于6的,所以它可以插在当前位置,该位置也恰好是1)

  • 插入[5,0]:[[5,0],[7,0],[6,1],[7,1]](身高为5,前面只能有0个大于等于5的,只能插在最开始,即0处)

  • 插入[5,2]:[[5,0],[7,0],[5,2],[6,1],[7,1]]

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

此时完成插入的数组,与 示例1 输出一致

题外话:std::list<vector>

什么时候用std::list<vector<int>>,什么时候用list<vector<int>>

std::list<vector<int>>list<vector<int>> 都是 STL 容器,只是前者在使用时需要加上 std:: 命名空间限定符,后者需要引入 using namespace std 或使用 std::list。它们的本质是相同的,都是双向链表容器,存储的元素类型都是 vector<int>
一般情况下,建议使用 list<vector<int>>,因为 std:: 命名空间限定符的使用会增加代码的可读性复杂度。但是如果你的代码中使用了 using namespace std,那么就可以使用 std::list<vector<int>>,或者在函数内使用 using std::list
需要注意的是,使用链表容器时需要注意在频繁的插入、删除操作时,链表的效率要比 vector 容器高。如果你的应用场景需要频繁进行元素的插入、删除操作,那么链表容器会更适合。但是,如果需要随机访问元素,则应使用 vector 容器。

代码

题外话:容器list

插入和删除

#include <list>

void printList(const list<int>& L) {
	for (list<int>::const_iterator it = L.begin(); it != L.end(); it++) {
		cout << *it << " ";
	}
	cout << endl;
}
//插入和删除
void test01(){
	list<int> L;
	//尾插
	L.push_back(30);
	//头插
	L.push_front(300);

	printList(L);
	//尾删
	L.pop_back();
	printList(L);

	//头删
	L.pop_front();
	printList(L);

	//插入
	list<int>::iterator it = L.begin();
	L.insert(++it, 1000);
	printList(L);

	//删除
	it = L.begin();
	L.erase(++it);
	printList(L);

	//移除
	L.push_back(10000);
	printList(L);
	L.remove(10000);
	printList(L);
    
    //清空
	L.clear();
	printList(L);
}

int main() {
	test01();
	system("pause");
	return 0;
}
完整代码

步骤:

1、自定义排序规则cmp

2、对people数组进行排序

3、创建一个list用于存放插入后的数组(初始化迭代器)

4、for循环遍历people数组,获取K作为位置值并保存

5、使用位置值不断修改迭代器it,找到插入位置。然后插入对应的people中的vector

class Solution {
public:
    static bool cmp(const vector<int>& a, const vector<int>& b){
        //身高从大到小排.如果身高相等,就比较前面有几个相同身高的人(身高相同k小的站前面)
        if(a[0] == b[0]) return a[1] < b[1];//比较k值(从小到大)
        return a[0] > b[0];//比较身高(从大到小)
    }
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(), people.end(), cmp);//对people进行排序
        list<vector<int>> que;//创建一个list用于存放插入后的数组
        for(int i = 0; i < people.size(); ++i){
            int pos = people[i][1];//获取k值作为位置值
            list<vector<int>>::iterator it = que.begin();//初始化迭代器
            while(pos--){//使用pos位置变量确认需要插入的位置
                it++;//修改迭代器指向的位置
            }
            que.insert(it, people[i]);
        }//因为要返回的是一个vector,所以还要以que的范围来创建一个新的vector
        return vector<vector<int>>(que.begin(), que.end());
    }
};
题外话:范围构造函数(Range Constructor)

上面代码中,因为题目要求返回类型是vector,所以需要将 que (STL 容器,list)中的元素转换为一个二维向量 vector<vector<int>>

具体来说,que.begin()que.end() 分别返回指向容器 que 中第一个和最后一个元素的迭代器。这个代码片段使用这两个迭代器作为参数传递给 vector 的构造函数,这样就可以创建一个新的二维向量,其中包含了容器 que 中的所有元素。每个元素都被转换为一个 vector<int>,并作为二维向量中的一行。

这种创建 vector 的方式叫做范围构造函数(Range Constructor)。范围构造函数允许我们使用一个迭代器范围(例如 beginend)来创建一个 vector,从而将另一个容器(或者是一段数组)中的元素复制到新的 vector 中。

使用范围构造函数可以方便地将一个容器或数组中的元素快速转换为一个 vector 对象,并且不需要手动逐个插入元素。

标签:people,08,list,插入,vector,que,身高,LeetCode,贪心
From: https://www.cnblogs.com/DAYceng/p/17228559.html

相关文章

  • LeetCode.144 二叉树的前序遍历
    1.题目给你二叉树的根节点 ​​root​​ ,返回它节点值的 前序 遍历。 示例1:给你二叉树的根节点 ​​​root​​ ,返回它节点值的 前序 遍历。 ​输入:root=[1,nu......
  • 爬虫学习08之scrapy框架
    为什么要学习scrapy爬虫框架安装scrapy1.安装pywin32--MicrosoftWindows的Python扩展提供对大部分Win32API的访问,创建和使用COM对象的能力以及Pythonwin环境;--不......
  • LeetCode454. 四数相加 II
    题目描述:给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i,j,k,l) 能满足:0<=i,j,k,l<nnums1[i]+nums2[j]......
  • LeetCode 1005.K 次取反后最大化的数组和
    题目描述:给你一个整数数组nums和一个整数k,按以下方法修改该数组:选择某个下标i并将nums[i]替换为-nums[i]。重复这个过程恰好k次。可以多次选择同一个下......
  • 【LeetCode贪心#07】分糖果
    发糖果力扣题目链接(opensnewwindow)老师想给孩子们分发糖果,有N个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。你需要按照以下要求,帮助老师给这些......
  • xv6 page fault —— MIT6.S081操作系统工程
    当硬件对用户使用的虚拟地址进行翻译时,若该虚拟地址不正确,比如尚未映射、权限不足等,硬件会产生一个pagefault陷阱给操作系统,就是这样一个看似简单平常的机制,却给了操作系......
  • LeetCode|412. Fizz Buzz
    题目链接:412.FizzBuzz给你一个整数n,找出从1到n各个整数的FizzBuzz表示,并用字符串数组answer(下标从1开始)返回结果,其中:answer[i]=="FizzBuzz"如果i......
  • LeetCode|1672. 最富有客户的资产总量
    题目链接:1672.最富有客户的资产总量难度简单173收藏分享切换为英文接收动态反馈给你一个mxn的整数网格accounts,其中accounts[i][j]是第i位客户在第j家银......
  • 【LeetCode贪心#06】加油站(股票买卖变种)
    加油站力扣题目链接(opensnewwindow)在一条环路上有N个加油站,其中第i个加油站有汽油gas[i]升。你有一辆油箱容量无限的的汽车,从第i个加油站开往第i+1个加油......
  • 代码随想录Day2-Leetcode977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II
    977.有序数组的平方题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/最初想法是用二分找到恰好大于0的数;然后数组切片,负的一方反转,然后按照合并......