合并两个有序链表、删除字符串 s1 中在字符串 s2 中出现的字符、求一个论坛一天的在线人数分布
- 一、合并两个有序链表
- 1.1、题目描述
- 1.2、思路
- 1.3、代码实现
- 1.4、小结
- 二、删除字符串 s1 中在字符串 s2 中出现的字符
- 2.1、题目描述
- 2.2、思路
- 2.3、代码实现
- 2.4、小结
- 三、求一个论坛一天的在线人数分布
- 3.1、题目
- 3.2、思路
- 3.3、代码实现
- 3.4、小结
- 总结
一、合并两个有序链表
1.1、题目描述
将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1:
输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]
示例 2:
输入:l1 = [], l2 = []
输出:[]
示例 3:
输入:l1 = [], l2 = [0]
输出:[0]
1.2、思路
可以如下递归地定义两个链表里的 merge 操作:
list1[0]+merge(list1[1:],list2) list1[0]<list2[0]
list2[0]+merge(list1,list2[1:]) otherwise
也就是说,两个链表头部值较小的一个节点与剩下元素的merge操作结果合并。
1.3、代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
if(list1==nullptr)
return list2;
else if(list2==nullptr)
return list1;
else{
if(list1->val<=list2->val)
{
list1->next=mergeTwoLists(list1->next,list2);
return list1;
}
else{
list2->next=mergeTwoLists(list1,list2->next);
return list2;
}
}
}
};
1.4、小结
两个链表头部值较小的一个节点与剩下元素的merge操作结果合并。
递归退出条件:哪个链表先空,返回第二个链表。
二、删除字符串 s1 中在字符串 s2 中出现的字符
2.1、题目描述
删除字符串 s1 中在字符串 s2 中出现的字符。
2.2、思路
把 s1 的字符存到一个 set 里面,然后遍历 s2,看是否出现过,出现过就erase 掉。但是直接输出 set 的元素这样会改变顺序,要想顺序不变,就顺序遍历一下 s1 看是否出现,出现就输出。
2.3、代码实现
类方式:
class Solution{
private:
set<char> s;
public:
string delstr(string &s1,string &s2)
{
int len1=s1.length();
int i=0;
for(i=0;i<len1;i++)
{
s.insert(s1[i]);
}
int len=s2.length();
for(i=0;i<le;i++)
{
if(s.count(s2[i]))
s.erase(s.find(s2[i]));
}
string res;
for(i=0;i<len1;i++)
{
if(s.count(s1[i]))
res+=s1[i];
}
return res;
}
}
直接终端输出的方式:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
#include <queue>
#include <map>
using namespace std;
typedef long long LL;
const int maxn=1005;
set<char>s;
int main()
{
string s1,s2;
cin>>s1>>s2;
int len=s1.length();
for (int i=0;i<len;i++)
s.insert(s1[i]);
len=s2.length();
for (int i=0;i<len;i++)
{
if (s.count(s2[i]))
s.erase(s.find(s2[i]));
}
len=s1.length();
for (int i=0;i<len;i++)
{
if (s.count(s1[i]))
cout<<s1[i];
}
cout<<endl;
return 0;
}
2.4、小结
利用hash的方式去除字符。
三、求一个论坛一天的在线人数分布
3.1、题目
求一个论坛的在线人数,假设有一个论坛,其注册 ID 有两个 亿个,每个 ID 从登陆到退出会向一个日志文件中记下登陆时间和退出时间,要求写一个算法统计一天中论坛的用户在线分布,取样粒度为秒。
3.2、思路
一天有3600*24=86400秒;定义一个长度为 86400 的整数数组 int delta[86400],每个整数对应这一秒的人数变化值,可能为正也可能为负。
开始时将数组元素都初始化为 0。
然后依次读入每个用户的登录时间和退出时间,将与登录时间对应的整数值加 1,将与退出时间对应的整数值减 1。这样处理一遍后数组中存储了每秒中的人数变化情况。
定义另外一个长度为 86400 的整数数组 int online_num[86400],每个整数对应这一秒的论坛在线人数。
假设一天开始时论坛在线人数为 0,则第 1 秒的人数 online_num[0]=delta[0]。第n+1 秒的人数 online_num[n]=online_num[n-1]+delta[n]。
这样我们就获得了一天中任意时间的在线人数。
3.3、代码实现
class Solution{
private:
int delta[86400]={0};
int online_num[86400]={0};
public:
void onlineCount(map<int,bool> users)
{
for(auto it=users.begin();it!=users,end();i++){
if(it->second)
delta[it->first]+=1;
else
delta[it->first]-=1;
}
online_num[0]=delta[0];
for(int i=1;i<86400;i++)
online_num[i]=online_num[i-1]+delta[i];
}
int getonlinesec(int sec)
{
return online_num[sec];
}
};
3.4、小结
利用当前结果与前一个结果相关的特性。
总结
一定要做好总结,特别是当没有解出题来,没有思路的时候,一定要通过结束阶段的总结来反思犯了什么错误。解出来了也一定要总结题目的特点,题目中哪些要素是解出该题的关键。不做总结的话,花掉的时间所得到的收获通常只有 50% 左右。
在题目完成后,要特别注意总结此题最后是归纳到哪种类型中,它在这种类型中的独特之处是什么。