【算法题】合并两个有序链表、删除字符串 s1 中在字符串 s2 中出现的字符、求一个论坛一天的在线人数分布

文章介绍了如何合并两个有序链表,采用比较头部节点值并递归合并的方法;删除字符串s1中在字符串s2中出现的字符,使用set存储s1字符并遍历s2删除;以及求论坛一天在线人数分布问题,通过数组记录登录退出信息来计算每秒在线人数。
摘要由CSDN通过智能技术生成

一、合并两个有序链表

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% 左右。

在题目完成后,要特别注意总结此题最后是归纳到哪种类型中,它在这种类型中的独特之处是什么。
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lion Long

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值