leetcode解题系列(六)
找到一点感觉了,每天坚持好三道题的量,多想想思路,自己动手再写一下代码,坚持就是胜利。
5750 人口最多的年份
题目描述:
给你一个二维整数数组 logs ,其中每个 logs[i] = [birthi, deathi] 表示第 i 个人的出生和死亡年份。
年份 x 的 人口 定义为这一年期间活着的人的数目。第 i 个人被计入年份 x 的人口需要满足:x 在闭区间 [birthi, deathi - 1] 内。注意,人不应当计入他们死亡当年的人口中。
返回 人口最多 且 最早 的年份。
解法:比较容易想到的就是朴素暴力解法,可以做一个一维数组,依次存放第i个人活着的年份,然后用count()函数求出每一年份出现的次数,然后求最大值就可以得到
只要能读懂题意,编写程序是不难的:
代码如下:
class Solution {
public:
int maximumPopulation(vector<vector<int>>& logs) {
int res=0;
vector<int> liveyear;
for(int i=0;i<logs.size();i++){//遍历搜索每个人
for(int n=logs[i][0];n<logs[i][1];n++){
liveyear.push_back(n);
}
}
int min_year=*min_element(liveyear.begin(),liveyear.end());
int max_year=*max_element(liveyear.begin(),liveyear.end());
res=max_year;
int po=count(liveyear.begin(),liveyear.end(),max_year-1);
for(int m=max_year;m>min_year-1;m--){
if(count(liveyear.begin(),liveyear.end(),m)>=po){
res=m;
po=count(liveyear.begin(),liveyear.end(),m);
}
}
return res;
}
};
但我这个做法毕竟是最简单的,官方给出了一种差分数组的方法,时间和空间上都更有优势:
class Solution {
private:
static constexpr int offset = 1950; // 起始年份与起始下标之差
public:
int maximumPopulation(vector<vector<int>>& logs) {
vector<int> delta(101, 0); // 变化量
for (auto&& log: logs) {
++delta[log[0]-offset];
--delta[log[1]-offset];
}
int mx = 0; // 人口数量最大值
int res = 0; // 最大值对应的最小下标
int curr = 0; // 每一年的人口数量
// 前缀和
for (int i = 0; i < 101; ++i){
curr += delta[i];
if (curr > mx){
mx = curr;
res = i;
}
}
return res + offset; // 转回对应的年份
}
};
delta数组是用来记录每一年的人口变化增量的,先遍历logs数组,将人口变化记录下来,然后再遍历delta数组,计算人口最多的年份。
1046、最后一块石头的重量
题目描述:
听上去也是一道比较有意思的。
想到的方法就是先对石头进行排序,然后编程实现粉碎后,若有新石头产生就加入原来的有序数组,接下来继续这个操作,即可实现。
代码如下:
class Solution {
public:
int lastStoneWeight(vector<int>& stones) {
sort(stones.begin(),stones.end());
int stone1=0;
int stone2=0;
int stones_differ=0;
while(stones.size()>=2){
stone1=stones.back();
stones.pop_back();
stone2=stones.back();
stones.pop_back();
if(stone1!=stone2){
stones_differ=stone1-stone2;
stones.insert(stones.begin(),stones_differ);
sort(stones.begin(),stones.end());
}
}
if(stones.size()==1){
return stones[0];
}
return 0;
}
};
代码的能力还要加强,一定不要老是依赖查资料,一些常识要熟练应用,还有不要老是出错,一些拼写方面还有括号,分号都要弄好,很浪费时间。
这是比较直接的算法,看看还有什么方法:
堆和优先队列,这块知识是我没有学过的,有时间看一下。
703、数据流中的第K大元素
题目描述:
用 最简单的方法写了一遍,但是发现时间要求不够。。
代码如下:
class KthLargest {
public:
int k1;
vector<int> st;
KthLargest(int k, vector<int>& nums) {
k1=k;
st=nums;
sort(st.begin(),st.end(),greater<int>());//降序排序
}
int add(int val) {
st.insert(st.begin(),val);
sort(st.begin(),st.end(),greater<int>());
return st[k1-1];
}
};
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest* obj = new KthLargest(k, nums);
* int param_1 = obj->add(val);
*/
因为当每一次add都要用到sort时就会比较慢,想到一个方法,当add的数字小于现在的第K大元素,我们就把它放在末尾不用排序了,因为这个元素并不会影响后面的输出,试一下这个方法。
还是超过了时间限制
官方有C++的版本:
class KthLargest {
public:
priority_queue<int, vector<int>, greater<int>> q;
int k;
KthLargest(int k, vector<int>& nums) {
this->k = k;
for (auto& x: nums) {
add(x);
}
}
int add(int val) {
q.push(val);
if (q.size() > k) {
q.pop();
}
return q.top();
}
};
运行速度比我的方法好太多了,但是要先学一下优先队列的相关方法;下次再学