记头条一面凉经

 

虽然那么菜,但是面试官还是给了一个小时的面试时间,语速比较快,看起来就是一个精神小伙。就是周围环境有点吵,导致自己思考也受阻。

1.自我介绍

2.讲下大学的项目经历

3.项目中的地图的数据结构是什么?你的CPU怎么和机器人进行通信的?(丢,现在发现面试答的时候不是特别好)

4.C++虚函数的机制

5.指针和引用的区别(1.引用得初始化,不能改变对象,引用只是一个别名,引用操作起来比较方便,引用sizeof()能出一个对象的大小,而指针可以....)

5.智能指针的实现,引用计数,以及什么时候开辟内存,什么时候申请内存,什么释放内存

6.判断是不是完全二叉树  https://leetcode-cn.com/problems/check-completeness-of-a-binary-tree/(感觉这题花了20分钟)

7.实现一个单例模式

8.概率题 

两个人抛硬币,规定第一个抛出正面的人可以吃到苹果,请问先抛的人能吃到苹果的概率多大 

9.反问环节

 

总结:关于C++那块答的还可以,算法在面试官的引导下才写出来,单例模式太久没看了,都忘记了。

概率题公式列出来了,但是算错了.....,竟然把等比数列的公式记错了,我日。。。。

 

 

 

3.项目中的地图的数据结构是什么?你的CPU怎么和机器人进行通信的?

应该说地图分为多种:有栅格地图,稀疏地图,以及稠密地图。每种格式都不太一样。

地图的数据结构为:存放关键帧和地图点

   
class Map{

public:
    
   ...


   ...
   vector<KeyFrame*> mvpKeyFrameOrigins;

    std::mutex mMutexMapUpdate;
    // This avoid that two points are created simultaneously in separate threads (id conflict)
    std::mutex mMutexPointCreation;

protected:
    std::set<MapPoint*> mspMapPoints;//地图点的集合
    std::set<KeyFrame*> mspKeyFrames;//关键帧的集合
    std::vector<MapPoint*> mvpReferenceMapPoints;//参考帧的地图点

    long unsigned int mnMaxKFid;
    std::mutex mMutexMap;
}

地图点:

class Mappoint{
public:
    long unsigned int mnId;
    static long unsigned int nNextId;
    long int mnFirstKFid;
    long int mnFirstFrame;
    int nObs;

    // Variables used by the tracking
    float mTrackProjX;
    float mTrackProjY;
    float mTrackProjXR;
    bool mbTrackInView;
    int mnTrackScaleLevel;
    float mTrackViewCos;
    long unsigned int mnTrackReferenceForFrame;
    long unsigned int mnLastFrameSeen;

    // Variables used by local mapping
    long unsigned int mnBALocalForKF;
    long unsigned int mnFuseCandidateForKF;

    // Variables used by loop closing
    long unsigned int mnLoopPointForKF;
    long unsigned int mnCorrectedByKF;
    long unsigned int mnCorrectedReference;
    cv::Mat mPosGBA;
    long unsigned int mnBAGlobalForKF;

    static std::mutex mGlobalMutex;

protected:
     // Position in absolute coordinates
     cv::Mat mWorldPos;

     // Keyframes observing the point and associated index in keyframe
     std::map<KeyFrame*,size_t> mObservations;

     // Mean viewing direction
     cv::Mat mNormalVector;

     // Best descriptor to fast matching
     cv::Mat mDescriptor;

     // Reference KeyFrame
     KeyFrame* mpRefKF;

     // Tracking counters
     int mnVisible;
     int mnFound;

     // Bad flag (we do not currently erase MapPoint from memory)
     bool mbBad;
     MapPoint* mpReplaced;

     // Scale invariance distances
     float mfMinDistance;
     float mfMaxDistance;

     Map* mpMap;

     std::mutex mMutexPos;
     std::mutex mMutexFeatures;
};

关键帧:

class KeyFrame{
public:

    static long unsigned int nNextId;//下一个关键帧的id,能够分配
    long unsigned int mnId;
    const long unsigned int mnFrameId;//

    const double mTimeStamp;

    // Grid (to speed up feature matching)
    const int mnGridCols;
    const int mnGridRows;
    const float mfGridElementWidthInv;
    const float mfGridElementHeightInv;

    // Variables used by the tracking
    long unsigned int mnTrackReferenceForFrame;
    long unsigned int mnFuseTargetForKF;

    // Variables used by the local mapping
    long unsigned int mnBALocalForKF;
    long unsigned int mnBAFixedForKF;

    // Variables used by the keyframe database
    long unsigned int mnLoopQuery;
    int mnLoopWords;
    float mLoopScore;
    long unsigned int mnRelocQuery;
    int mnRelocWords;
    float mRelocScore;

    // Variables used by loop closing
    cv::Mat mTcwGBA;
    cv::Mat mTcwBefGBA;
    long unsigned int mnBAGlobalForKF;

    // Calibration parameters
	const float mThDepth;

    // Number of KeyPoints
    const int N;

    // KeyPoints, stereo coordinate and descriptors (all associated by an index)
    const std::vector<cv::KeyPoint> mvKeys;
    const std::vector<cv::KeyPoint> mvKeysUn;
    const std::vector<float> mvuRight; // negative value for monocular points
    const std::vector<float> mvDepth; // negative value for monocular points
    const cv::Mat mDescriptors;

    // BoW
    DBoW2::BowVector mBowVec;
    DBoW2::FeatureVector mFeatVec;

    // Pose relative to parent (this is computed when bad flag is activated)
    cv::Mat mTcp;

    // Scale
    const int mnScaleLevels;
    const float mfScaleFactor;
    const float mfLogScaleFactor;
    const std::vector<float> mvScaleFactors;
    const std::vector<float> mvLevelSigma2;
    const std::vector<float> mvInvLevelSigma2;

    // Image bounds and calibration
    const int mnMinX;
    const int mnMinY;
    const int mnMaxX;
    const int mnMaxY;
   
    // Moving flg
    int flag_kf_mov;

    // The following variables need to be accessed trough a mutex to be thread safe.
protected:

    // SE3 Pose and camera center
    cv::Mat Tcw;
    cv::Mat Twc;
    cv::Mat Ow;

    cv::Mat Cw; // Stereo middel point. Only for visualization

    // MapPoints associated to keypoints
    std::vector<MapPoint*> mvpMapPoints;

    // BoW
    KeyFrameDatabase* mpKeyFrameDB;
    ORBVocabulary* mpORBvocabulary;

    // Grid over the image to speed up feature matching
    std::vector< std::vector <std::vector<size_t> > > mGrid;

    std::map<KeyFrame*,int> mConnectedKeyFrameWeights;
    std::vector<KeyFrame*> mvpOrderedConnectedKeyFrames;
    std::vector<int> mvOrderedWeights;

    // Spanning Tree and Loop Edges
    bool mbFirstConnection;
    KeyFrame* mpParent;
    std::set<KeyFrame*> mspChildrens;
    std::set<KeyFrame*> mspLoopEdges;

    // Bad flags
    bool mbNotErase;
    bool mbToBeErased;
    bool mbBad;    

    float mHalfBaseline; // Only for visualization

    Map* mpMap;

    std::mutex mMutexPose;
    std::mutex mMutexConnections;
    std::mutex mMutexFeatures;
};

 

 

6.判断是不是完全二叉树  

注意不是弹出队列的时候才加入值,而是在加入队列的时候加入值

class Solution {
public:
    
    bool isCompleteTree(TreeNode* root) {
        if(root == NULL) return true;
        queue<TreeNode*> m_queue;
        m_queue.push(root);
        vector<int> res;
        res.push_back(root->val);
        while(m_queue.size()){
            TreeNode* curNode = m_queue.front();
            m_queue.pop();
          //  res.push_back(curNode->val);

            if(curNode->left){
                m_queue.push(curNode->left);
                res.push_back(curNode->left->val);
            }
            else{
                res.push_back(-1);
            }

            if(curNode->right){
                m_queue.push(curNode->right);
                res.push_back(curNode->right->val);
            }else{
                res.push_back(-1);
            }
        }


    // 1 2 3 
      //  1 2 3 X X 4
        for(int i = 0 ; i < res.size() ; i++){
            if(res[i] == -1){
                while(i+1 < res.size()){
                    if(res[i+1] != -1)
                        return false;
                        i++;
                }
            } 
        }
        return true;
    }

};

7.单例模式

饿汉:就是一开始太饿了,所以类刚使用时就创建了这个对象。程序启动时就创建一个唯一的实例对象,即单例类定义的时候就进行实例化。

懒汉:就是知道使用的时候才

 

饿汉模式不需要考虑加锁问题

class CSingleton
{
public:
	static CSingleton * getSingleton()
	{
		return msin;
	}

	class CDestroy
    {
    public:
        ~CDestroy()
        {
			if(CSingleton::msin != NULL)
			{
				delete CSingleton::msin;
				msin = NULL;
				cout << "~CSingleton()" << endl;
			}   
        }
    };

    static CDestroy mDel;

private:
	static CSingleton * msin;

	CSingleton() 
	{
		cout << "CSingleton()" << endl;
	}
};

CSingleton* CSingleton :: msin = new CSingleton();
CSingleton::CDestroy mDel;

int main()
{
	cout << "Process Begin" << endl;
	CSingleton *s1 = CSingleton::getSingleton();
	CSingleton *s2 = CSingleton::getSingleton();
	cout << "s1 = " << s1 << endl << "s2 = "<< s2 << endl;
	//delete s1;
}

懒汉模式:

#include <iostream>
#include <pthread.h>
using namespace std;

class CSingleton
{
public:
	static CSingleton * getSingleton()
	{
		pthread_mutex_lock(&mutex);
		cout << "lock()" << endl;

		if (msin == NULL)
		{
			msin = new CSingleton();
		}

		pthread_mutex_unlock(&mutex);
		cout << "unlock()" << endl;
		return msin;
	}

	class CDestroy
    {
    public:
        ~CDestroy()
        {
			if(CSingleton::msin != NULL)
			{
				delete CSingleton::msin;
				cout << "~CSingleton()" << endl;
			}   
        }
    };

    static CDestroy mDel;

private:
	CSingleton()
	{
		cout << "CSingleton()" << endl;
	}

	static CSingleton* msin;
	static pthread_mutex_t mutex;
};

CSingleton* CSingleton::msin = NULL;
pthread_mutex_t CSingleton::mutex = PTHREAD_MUTEX_INITIALIZER;
CSingleton::CDestroy mDel;

int main()
{
	cout << "Process Begin" << endl;
	CSingleton *s1 = CSingleton::getSingleton();
	CSingleton *s2 = CSingleton::getSingleton();
	cout << "s1 = " << s1 << endl << "s2 = "<< s2 << endl;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值