LeetCode 1450 - 1453

在既定时间做作业的学生人数

 

给出两个数组表示开始时间和结束时间,给出一个整数 queryTime 表示要询问的时间

给出的整数 queryTime 在多少个闭区间内部,每个闭区间就是一个开始时间和结束时间

枚举所有区间,判断要询问的时间是不是在区间中即可

示例1:有 3 个区间,[ 1,3 ]  [ 2,2 ]  [ 3,7 ],要询问的时间是 4,看 4 在哪个区间中

                                       ×            ×           √

最终 4 只在一个区间中,答案返回 1

判断 4 是不是大于等于区间的开始时间,小于等于区间的结束时间,如果是的话,答案 + 1,时间复杂度为 O(n)

class Solution {
public:
    int busyStudent(vector<int>& startTime, vector<int>& endTime, int queryTime) {
        //记录答案
        int res = 0;
        //枚举所有区间
        for(int i = 0;i < startTime.size();i++ ) 
            //满足条件
            if(queryTime >= startTime[i] && queryTime <= endTime[i])
                res ++;
        return res;
         
    }
};

重新排列句子中的单词

 

定义了什么是句子: 一个用空格分隔单词的字符串,句子满足一定的条件,需要将句子中的所有单词按单词的长度升序排序,如果两个单词的长度相同,则保留其在原句中的相对位置

①如何在一个句子中找出所有用空格隔开的单词:stringstream

②如何排序:双关键字排序:一、字符串的长度   二、它在原序列中的相对下标(特殊)

stable_sort():稳定排序,只需要按照长度排序即可

先把所有单词从句子中拿出来,放到 vector 中,再用 stable_sort 根据每个单词的长度从小到大排序

首先需要将句首单词的首字母变成小写,再将最终句子的首字母变成大写

C++ stable_sort()用法详解

class Solution {
public:
    string arrangeWords(string text) {
        //用法和 cin 一样
        stringstream ssin(text);
        vector<string> words;
        string word;
        //把 ssin 的所有单词放到 words 中
        while(ssin >>  word) words.push_back(word);
        //把单词的首字母变成小写 tolower 把大写字母变成小写 如果是其他字符就不变 或者 +32
        words[0][0] = tolower(words[0][0]);
        //升序排序
        stable_sort(words.begin(),words.end(),[](string a,string b) {
            return a.size() < b.size();
        });
        //再把结果的首字母变成大写
        words[0][0] = toupper(words[0][0]);
        //把所有单词放到答案中
        string res;
        for(auto word : words) res += word + ' ';
        //把最后的空格删除
        res.pop_back();
        return res;
    }
};

收藏清单

 

 

 

给出一个数组 favoriteCompanies,其中 favoriteCompanies[ i ] 是第 i 名用户收藏的公司清单

favoriteCompanies[ i ] 是一个 string 的列表,看一下哪些列表不是其他任何一个列表的子集、哪些列表中包含的公司的名称没有被其他任何一个列表全部包含

示例1:先看第一个清单,后面的清单中都没有 LeetCode,所以第一个清单一定不是后面任何一个清单的子集,因此第一个清单需要输出,第三个清单可以被第一个清单完全包含,所以第三个清单不能输出,以此类推 . . .

列表的数量 ≤ 100,每个列表的长度 ≤ 500,每个字符串(公司)的长度 ≤ 20,一个用户收藏的列表中不会有重复的元素

给出两个列表,如何判断 A 是不是 B 的子集( A 是不是完全被 B 包含)?

先将所有列表中的单词排序,A 和 B 就是有序的,排序的时间复杂度 O( 100 × 500 × log500 × 20(每次比较、交换的都是两个字符串))   O( 10^7 )

为什么要排序?

一个列表中所有单词的顺序可以是乱序,同样一个集合,序列的个数为 n 的阶乘

为了避免处理冗余的情况:集合1:1  2  3  集合2:3  2  1,集合是一样的,但是列表不一样,排序后保证集合对应的序列只有一种

排序后再判断 A 是不是 B 的子集,从前往后扫描 B 中的每一个字符串,拿一个指针从 A 的每一个单词开始往后指,在扫描 B 的时候,如果 B 的字符串和 A 对应的字符串相同,把指针往后移动一位,当扫描完 B 之后,如果 A 中所有的单词都被扫描完,就说明 A 完全可以被 B 包含,反之不成立

枚举每一个串,再枚举其他所有串,当前串和其他串做比较 O(100 × 99 × (500 + 500))   O( 10^7 )

由于 A、B 已经按照字典序排序,如果 A 是 B 的子集,那么 A 一定是 B 的某个子序列;如果 A 不是 B 的子集,A 必然包含 B 中没有的字符串

class Solution {
public:
    vector<int> peopleIndexes(vector<vector<string>>& favoriteCompanies) {
        //用 n 来表示列表长度
        int n = favoriteCompanies.size();
        //从前往后枚举每一个列表并排序
        for(auto &l : favoriteCompanies) sort(l.begin(),l.end());
        //记录满足要求的列表-> 从前往后枚举每一个列表
        vector<int> res;
        for(int i = 0;i < n;i++ ) {
            //用于判断当前列表是不是其他列表的子集
            bool is_subset = false;
            //枚举其他所有的列表
            for(int j = 0;j < n;j++ )
                if(i != j) 
                {
                    //判断 favoriteCompanies[i] 是不是 favoriteCompanies[j] 的子集
                    auto &A = favoriteCompanies[i],&B = favoriteCompanies[j];
                    //a的下标
                    int a = 0;
                    //b从0开始
                    for(int b = 0;b < B.size() && a < A.size();b++ ) 
                        if(A[a] == B[b])
                            a++;
                    //说明 A 是 B 的子集
                    if(a == A.size())
                    {
                        is_subset =true;
                        break;
                    }
                }
                //如果当前字符串不是任何一个字符串的子集
                if(!is_subset) res.push_back(i);
        }
        return res;
    }
};

圆形靶内的最大飞镖数量

 

 

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

qiuqiuyaq

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

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

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

打赏作者

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

抵扣说明:

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

余额充值