练题100天——DAY28:找消失的数字+分发饼干

今天记录了两道题,难度范围:★~★★。想到解决办法都不困难,想到奇招挺困难的。

一.找到所有数组中消失的数字 ★★☆☆☆

题目

448. 找到所有数组中消失的数字 给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

思路1

将1~n先存入结果数组,然后遍历nums数组,将nums存在的元素移除res,最后剩下的就是消失的数字。

说明:

auto it=find(res.begin(),res.end(),nums[i]);------查找nums[i]在res中的迭代器,然后从res在擦除对应元素

代码(未通过所有测试用例)

cpp 复制代码
class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        int n=nums.size();
        vector<int> res;
        //先将1~n存入res
        //然后遍历数组移除在数组中的元素
        for(int i=1;i<=n;i++){
            res.push_back(i);
        }
        for(int i=0;i<n;i++){
            auto it=find(res.begin(),res.end(),nums[i]);
            res.erase(it);
        }
        return res;
    }
};

代码运行时间太长,无法通过所有测试用例

思路2

利用哈希集合记录下数组的元素,然后在哈希集合中寻找1~n的数字,未找到的数字加入结果数组,最后结果数组中保存的就是答案。

代码2

cpp 复制代码
class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        int n=nums.size();
        vector<int> res;
        unordered_set<int> s;
        //先将1~n存入res
        //然后遍历数组移除在数组中的元素
        for(int i=0;i<n;i++){
            s.insert(nums[i]);
        }
        for(int i=1;i<=n;i++){
            if(s.find(i)==s.end()){
                res.push_back(i);
            }
        }
        return res;
    }
};

复杂度

时间复杂度:O(n)。遍历数组并插入哈希集合+遍历并查找集合→O(n)+O(n)=O(n)

空间复杂度:O(n)。需要额外的 O (n) 空间存储哈希集合

官方题解------原地修改 ★★★★☆

我标的四星难度,主要是因为个人觉得这个做法很难想到。

一般的思路就是利用哈希表记录数字,也可以创建一个数组代替哈希表,而数组nums的长度刚好是n,所以可以用nums充当哈希表。

数字范围是 1~n,可以利用此范围外的数字表示"是否存在",具体做法:遍历数组nums,每遇到一个数字x,就让nums[x-1]+n。因为nums数组中的所有数都在要求的数字范围内,所以这些数之后一定大于n,最后再次遍历nums数组,如果有nums[i]不大于n,说明没有遇到对应的数字 i+1,此数字就属于消失的数字。

注意点:遍历数组时,存在该数已经增加过n的情况,所以需要对n取模还原出本来的值。

代码

cpp 复制代码
class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        int n=nums.size();
        for(auto & num:nums){
            int x=(num-1)%n;
            if(nums[x]<=n){
                nums[x]+=n;
            }
        }
        vector<int> res;
        for(int i=0;i<n;i++){
            if(nums[i]<=n){
                res.push_back(i+1);
            }
        }
        return res;
    }
};

复杂度

时间复杂度:O(n)

空间复杂度:O(1)

二.分发饼干 ★☆☆☆☆

题目

455. 分发饼干

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。

对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是满足尽可能多的孩子,并输出这个最大数值。

思路

先对胃口值和饼干尺寸进行升序排序,使得用尽量合适的饼干尺寸满足胃口。

类似于双指针思想,创建变量 i 和 j 表示对应索引的胃口值和饼干尺寸。先通过移动 j 找到第一块满足 g[i] 的饼干,res满足的人数+1,然后移动 i 和 j,继续找饼干满足下一个人,重复操作。

代码

cpp 复制代码
class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        //先排序
        //在找
        int gLen=g.size();
        int sLen=s.size();
        int res=0;
        int i=0,j=0;
        sort(g.begin(),g.end());
        sort(s.begin(),s.end());
        while(i<gLen && j<sLen){
            //找到第一块满足的饼干
            while(j<sLen && s[j]<g[i]){
                j++;
            }
            if((i<gLen && j<sLen) && s[j]>=g[i]){
                res++;
                i++;
                j++;
            }
        }
        return res;
    }
};

复杂度

m、n分别为数组g和s的长度

时间复杂度:O(nlogn+mlogm)。时间开销分为排序操作和循环操作。排序操作所用的时间复杂度O(mlogm+nlogn);循环操作主要是 i 和 j 的移动,总操作次数为 m+n,不存在循环操作,所以整体的时间复杂度为O(nlogn+mlogm+n+m)=O(nlogn+mlogm)。

空间复杂度:O(logn+logm)。辅助空间分为排序操作所需的辅助空间O(logn+logm)和局部变量的空间开销O(1),所以整体的空间复杂度为O(logn+logm)。

代码2

我的代码和官方题解的代码大差不差,但是评论区有一个回答看起来更简单点,来自:dp小亡子

直接将满足了的胃口值的个数作为答案,不断移动 j 的时候,能满足胃口值时,移动 i ,最后的 i 就是最多被满足的人数。

cpp 复制代码
class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        int gLen=g.size();
        int sLen=s.size();
        int i=0,j=0;
        sort(g.begin(),g.end());
        sort(s.begin(),s.end());
        while(i<gLen && j<sLen){
            if(g[i]<=s[j]){
                i++;
            }
            j++;
        }
        return i;
    }
};

复杂度和之前的代码基本一致

相关推荐
lzh200409192 小时前
二叉搜索树与双向链表
数据结构·链表
studytosky2 小时前
深度学习理论与实战:反向传播、参数初始化与优化算法全解析
人工智能·python·深度学习·算法·分类·matplotlib
WolfGang0073212 小时前
代码随想录算法训练营Day48 | 108.冗余连接、109.冗余连接II
数据结构·c++·算法
努力学算法的蒟蒻3 小时前
day35(12.16)——leetcode面试经典150
算法·leetcode·面试
cccc来财3 小时前
角点检测算法:Harris 和 FAST 方法
算法·计算机视觉·特征提取
风中月隐3 小时前
C语言中以坐标的方式图解“字母金字塔”的绘制
c语言·开发语言·算法·字母金子塔·坐标图解法
q_30238195563 小时前
告别“笨重”检测!VA-YOLO算法让疲劳驾驶识别更轻更快更准
算法·yolo
45288655上山打老虎3 小时前
List容器
数据结构·windows·list
松涛和鸣3 小时前
DAY32 Linux Thread Programming
linux·运维·数据库·算法·list