C++经典面试题打卡

Posted ych9527

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++经典面试题打卡相关的知识,希望对你有一定的参考价值。

传递信息

小朋友 A 在和 ta 的小伙伴们玩传信息游戏,游戏规则如下:

有 n 名玩家,所有玩家编号分别为 0 ~ n-1,其中小朋友 A 的编号为 0
每个玩家都有固定的若干个可传信息的其他玩家(也可能没有)。传信息的关系是单向的(比如 A 可以向 B 传信息,但 B 不能向 A 传信息)。
每轮信息必须需要传递给另一个人,且信息可重复经过同一个人
给定总玩家数 n,以及按 [玩家编号,对应可传递玩家编号] 关系组成的二维数组 relation。返回信息从小 A (编号 0 ) 经过 k 轮传递到编号为 n-1 的小伙伴处的方案数;若不能到达,返回 0。

题解1:dfs

  • 由题可知,是求路径总和问题,即每一步可以到达多个位置,利用递归属性,遍历这个位置

  • 递归出口:a.当前步伐数超过k,立即终止;b.当前步伐数=k,且编号=n-1

    class Solution {
    public:
        void _numWays(int n,vector<vector<int>>& relation,int k,int code,int count,int &ret)
        {
            if(count>k)
                return;
    
            if(count==k&&code==n-1)
            {
                ret++;
                return;
            }
    
            for(auto&e:relation)
            {
                if(e[0]==code)
                    _numWays(n,relation,k,e[1],count+1,ret);
            }
            
        }
        int numWays(int n, vector<vector<int>>& relation, int k) {
            //从0处传到n-1处,的所有路径总和数
    
            int code=0;//当前的编号
            int count=0;//记录当前步伐
            int ret=0;//记录路径总和
    
            _numWays(n,relation,k,code,count,ret);
            return ret;
        }
    };
    

题解2:动态规划

  • 设dp[i][j]表示第i轮,传递给编号为j的方案数
  • 对dp进行初始化,显然第0轮的时候,起始位置为dp[0][0] -> dp[0][0]=1,其余位置都为0
  • 转移方程的构建:设当前方案编号为des,到达des的编号为scr -> dp[i][des]+=dp[i-1][scr]
class Solution {
public:
    int numWays(int n, vector<vector<int>>& relation, int k)
     {
        //dp[i][j]表示第i轮,传递给编号j的方案数
        vector<vector<int>>dp(k+1,vector<int>(n,0));
        dp[0][0]=1;

        for(int i=0;i<k;i++)//控制轮数
        {
            for(auto&e:relation)
            {
                int scr=e[0];//从哪里来
                int des=e[1];//去往哪里

                dp[i+1][des]+=dp[i][scr];
            }
        }

        return dp[k][n-1];
    }
};

大餐计数

大餐 是指 恰好包含两道不同餐品 的一餐,其美味程度之和等于 2 的幂。你可以搭配 任意 两道餐品做一顿大餐。给你一个整数数组 deliciousness ,其中 deliciousness[i] 是第 i 道餐品的美味程度,返回你可以用数组中的餐品做出的不同 大餐 的数量。结果需要对 109 + 7 取余。注意,只要餐品下标不同,就可以认为是不同的餐品,即便它们的美味程度相同。

  • 1 <= deliciousness.length <= 105
  • 0 <= deliciousness[i] <= 2^20

题解:

  • 由题可知任意两数之和的范围在[1,2^21]
  • 在统计的时候,只需要从数组中拿出来一个数,在循环得到2的[0,21]的幂,然后进行相减,就可以得到另外一个数,是多少
  • 得到另外一个数后,就可以取数组中进行查找
  • 这时,我们在遍历的过程之中,可以将数加入map之中进行统计出现过的次数,为了防止重复查找,我们可以先查找这个数是否在map之中,然后再将数组中的元素添加至map之
class Solution {
public:
    int countPairs(vector<int>& deliciousness) {
        int div=pow(10,9)+7;
        //两数之和的范围为: [0,2^21]

        unordered_map<int,int> mp;
        int count=0;
        for(auto&e:deliciousness)
        {
            for(int i=0;i<22;i++)
            {
                int val=pow(2,i) - e;//得到另外一个数
                if(mp.find(val)!=mp.end())
                {
                    count=(count+mp[val])%div;
                }
            }

            mp[e]++;//统计所有数字出现的次数
        }

        return count;
    }
};

和相同的二元子数组

  • 将数组的前缀和存入哈希表中
  • val = 一个连续的子数组后- goal,如果val在哈希表中,则加上对应数值
  • image-20210708142925069
class Solution {
public:
    int numSubarraysWithSum(vector<int>& nums, int goal) {
        int count=0;
        unordered_map<int,int>mp;
        int sum=0;
        for(auto&e:nums)
        {
            mp[sum]++;
            sum+=e;
            count+=mp[sum-goal];
        }
        return count;
    }
};

基于时间的键值存储

创建一个基于时间的键值存储类 TimeMap,它支持下面两个操作:

  1. set(string key, string value, int timestamp)存储键 key、值 value,以及给定的时间戳 timestamp。

  2. get(string key, int timestamp)返回先前调用 set(key, value, timestamp_prev) 所存储的值,其中 timestamp_prev <= timestamp。如果有多个这样的值,则返回对应最大的 timestamp_prev 的那个值。如果没有值,则返回空字符串("")。

题解:

  • 构建一个 unordered_map<string,vector<pair<int,string>>> mp,存储三个元素
  • 由于是按时间戳进行存储的,因此vector里面的元素天然有序
  • 在取出来的时候,利用二分法进行判断

image-20210710215256097

class TimeMap {
public:

    /** Initialize your data structure here. */
    TimeMap() {}
    
    void set(string key, string value, int timestamp) {
        tp.first=timestamp;
        tp.second=value;

        mp[key].push_back(tp);
    }
    
    int BinarySearch(vector<pair<int,string>>&arr,int &time)
    {
        int left=0;
        int right=arr.size()-1;
       while(left<=right)
       {
           int mid=left+(right-left)/2;
           if(arr[mid].first>time)
                right=mid-1;
            else if(arr[mid].first<time)
                left=mid+1;
            else
                return mid;
       }
        return right;
    }
    string get(string key, int timestamp) {

        if(mp[key].size()==0||mp[key][0].first>timestamp)
            return "";
       //由于是按时间顺序插入的,因此arr里面的元素是按时间排好序的
       //找到对应的位置,前面一个位置就是需要找的值
        int mid= BinarySearch(mp[key],timestamp);
        if(mid>=0)
        {
            string ret=mp[key][mid].second;
            return ret;
        }
        return "";
    }

    unordered_map<string,vector<pair<int,string>>> mp;
    pair<int,string> tp;
};

以上是关于C++经典面试题打卡的主要内容,如果未能解决你的问题,请参考以下文章

面试题打卡——C++版

面试题打卡——C++版

面试题打卡——C++版

面试题打卡——C++版

面试题打卡——C++版

面试题打卡——C++版