总结下,这几天的一个面试(你咋没直接干ta呢)

初面,我就不说公司了。给ta留点脸。当时,我就想你咋没一套军体拳给ta干过去,打的ta满地找牙!教教ta做人。

这家公司很奇怪,啥尿性就不说了。起初,以为四点中到,还以为啥呢!人多的踩破门了。结果没有,我就提前去了。在前台登记了下, 那张表开始填,还有面试题。我第一眼就看了面试题。觉得没啥,好像比较基础,就开始填了。写完之后我就开始看那些题了。三页纸,没多少东西。其实很就答完了。然后,我没急的交。想看看ta葫芦里卖的什么药。里面有些题,明显知道怎么解,有思路。写出来多少有些不满足的地方。所以就没写。在哪里多想了一会。后来,那个小伙过来催我了。让我交上去。我说,算了给ta吧。让我给等一会。说去叫他们负责人过来。

        精彩的来了。这个b一进来就说,你有工作经验吗?  我说,有, 有一段时间。 然后,问我这题写不出来吗?我说,能。思路是什么? 然后,人没继续听。说这题为什么错?是一个比较基础的题char a[] ="abcd"; sizeof(a)是多少()。我写了4.。这个确实错了。char结尾默认后面是不是还有个"\o"在哪。sizeof(a)会直接把"\0"也算上,所以就是5。所以在这点上疏忽了。后们的的基本上都是对的。

        然后,这个b开始潮了。 表给你,拿上走吧!哎,等下题不能给你。 卧槽!!!牛批啊,大厂就是吊啊!当面赶人的。这种。(至于是不是大厂,你们自己评价吧。反正人吹的规范很大500人,好家伙!年数也不小了,算资深的游戏公司了。我不想多说什么,就暂时算中大型厂吧!)。我笑了。拿走题算什么????我就不会了吗?? 还是怎么??? 我差点就笑出来,你的题,我都背下来了。拿走题又怎么样呢。真极品那(666)还玩这套。拧特么的,真行啊! 下次,下次,我就直接干你!

下面看下ta的题:

表面上的基础:

 char a[] = "abcd";

   char* str = a;

  char *str1 =str;

   cout<<sizeof(a)<<endl;

   cout<<sizeof(str)<<endl;

   cout<<sizeof(*str)<<endl;

   cout<<sizeof(str1)<<endl;

给出结果:我直接贴结果了(这里注意了64位指针跟32位是不是不一样!所以会有两份结果。这就是ta故意挖坑给你了。不过ta的题,没那个要求。给出结果就ok了。好像也点明了操作系统32位下,结果是什么?所以审题的时候,记得看清了。不然,没出门就挂了,下面没得谈了。)

 后面还有一些稍微难一点点。不过没听那个人,逼逼懒懒应该是对了。看一下吧!

 我稍微包装了一下,写好了点,笔试题可能就只有new跟sizeof这两行给出结果:

我直接贴结果了:原题没有malloc,是我自己加的。所以一块看了。

 

 所以有啥匪夷所思的地方吗?没有。这个就是考察你指针的理解了。在动态申请下会发生什么变化。所以不管在做函数传递时,还是new时,ta没提malloc,题还是简单了点。 sizeof(a)得到的结果都是指针的大小。

这基础就解释了。

下面就是算法题了。

什么题呢? 三道。 分了一张A4半纸,合并两个链表,字母去重(能理解吧!意思就是一堆字母,一直去到没有重样的才算完成,没有bug),青蛙跳台阶(这就是个数列,想到了,但,没写! 第一个题,写了部分。觉得不好重写了。杠掉了。得予以,面试前的一周,没碰电脑吧!直接手写,生呼了,没地了!)。是不是挺简单的。好像没什么难度。

下面把这几个小算法题写下。

1. 合并链表:题是这样,蛮简单的 ListNode L1,元素有 1,1,2,4, null;L2 6,3,4,5,null 这个一看就是单链表了。结构也给出来了。要求呢 合并出来的链表 1,1,2,3, 4, 4, 5 , 6,null 其实就是 合并再排序 ok了 结束。就这么简单。这不就个merger归并排序么,答案确实是的。但,这没那么复杂。所以从简就行了。初想,直接把两张链表合并到一张新表里,然后排序一下,完事。也算最符合题意了。 但,这种肯本不是最优解。实现出来,从使用效率和空间浪费上,肯定是不行的。算法的本质就是为了节省空间,提高效率。所以,就推翻了。重写

struct ListNode{

int val;

ListNode* next;

ListNode(int x) :val(x), next(NULL) {} //这是c++类内初始化的一种方法。 有人说这是leetcobe原题啊。你不知道吗?巧了, 我真不知道。。

}

struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) 函数体长这样,名也看出来了。所以就顺着往下写呗!

{        //新表,新表就要一张新的能装下这两个链表所有元素的表。 这就是正常人的思维方式了。于是L3 就来了。关于后边新的写法,我都会写。

        ListNode* L3 = new ListNode;        

        ListNode* temp =l3;

        for(:  L1->next !=null && L2->next != null :   :)  //这里,有人可能有人会说,啊,你怎么没用                 //while,没有效率。先这样。

        {        //然后 

                        if(l1->val <l2->val)//的话

                        {

                                temp->next =l1;   //L1的指针地址拿过来   

                                l1=l1->next;        //L1继续往下走

                        }

                        else //就是L2 同上L1一样的操作

                        {

                                temp->next =l2;

                                l2=l2->next;  

                        }

        temp=temp->next; //判断结束 temp继续往后走。

//这是不是就完了,实现上确实完了。但,链表指到最后是不是还有一个没拿过来。

        if(l1)

        {

        temp-next =l1;
        }

        if(l2)

        {

        temp-next =l2;
        }

return l3->next;

}

所以看下代码实现

ListNode* mergeTwoLists(ListNode* l1, ListNode* l2)
{
		ListNode* l3 = new ListNode();

		ListNode* temp = l3;
		while (l1 != nullptr && l2 != nullptr)
		{
			if (l1->val < l2->val) {
				temp->next = l1;
				l1 = l1->next;
			}
			else {
				temp->next = l2;
				l2 = l2->next;
			}
			temp = temp->next;
		}

		if (l1) {
			temp->next = l1;
		}
		if (l2) {
			temp->next = l2;
		}
	
		return l3->next;


		/*if (l1 == nullptr) {   //这个是递归 代码会变的更加简洁
			return l2;
		}
		else if (l2 == nullptr) {
			return l1;
		}
		else if (l1->val < l2->val) {
			l1->next = mergeTwoLists(l1->next, l2);
			return l1;
		}
		else {
			l2->next = mergeTwoLists(l1, l2->next);
			return l2;
		}*/

};

2. 字母去重

举例:“aabcbcddsad”

结果:“bcbcsad”

这好说吧!看你怎么解了。初感觉就是个连连看。没说怎么实现,用char还是string,或者容器啥的,也没有这种要求,所以只要有两个以上的重复字母消除就行了。 有人说这也是leetcode的题啊。管ta那么多,看下ta写的这个吧!

string removeDuplicates(string s, int k) {
	//int length = -1;                            
	//while (length != s.size()) {                //时间复杂度 while 一次
	//	length = s.size();
	//	for (int i = 0, count = 1; i < s.size(); ++i) {  //for一次 
	//		if (i == 0 || s[i] != s[i - 1]) {
	//			count = 1;
	//		}
	//		else if (++count == k) {            //k这里还有一次 所以是 O(n平方/k)
	//			s.erase(i - k + 1, k);         //这里是不是很讨巧的用了string.erase()
	//			break;                         //从i-k+1的位置删除 k个。然后break掉;  
	//		}            //空间复杂度  没有多余的申请空间所以就O(1)
	//	}
	//}

//这算是暴力穷举的方法了。 时间复杂度占用过高。 那么看下ta下面给出的这个解法。vector

	vector<int> count(s.size());
	for (int i = 0; i < s.size(); ++i) {        //一次for
		if (i == 0 || s[i] != s[i - 1]) {    //当前的不等于前一个的     
			count[i] = 1;
		}
		else {
			count[i] = count[i - 1] + 1;   //cout累计
			if (count[i] == k) {            
				s.erase(i - k + 1, k);   //删除
				i = i - k;            
			}
		};
	}
            //没有多余的申请空间空间复杂度O(1), 时间复杂度就是 O(n)只跑了一次循环。

	return s;        //最后返回。
}

3.青蛙跳台阶,这一看就是数列问题了,类似很多的这种书本上的问题。什么兔子按月生兔子,隔几个月就有新兔子,求解几年后有多少只兔子。斐波那契数列, 初解,用递归求解这个问题了。但,递归是不是在较小的空间情况下,求解会很快,求解数字大的效率就会立马低下来。因为要频繁的堆栈空间,当你要跳40四十阶以上的时候是不是就没效率了。如果你写的是无穷解,堆栈是不是很快就溢出了,程序就崩溃了。所以递归看似好,实则不好。 所以ta这个b,出的题。就说我们一下就跳40往上的,请你写这个算法。我哈哈哈^^ !直接没写。还想在这坑老子,给你装B的机会么。想多了。

所以写一下这个算法吧!

我用int解了,想跳大点,记得用换个大点的类型比如: long long

 int Faci(int n)
{
	/*if (n == 0)   
	{
		return 0;
	}
	if (n == 1)
	{
		return 1;
	}
	if (n == 2)
	{
		return 2;
	}
	else
	{
		return Faci(n - 1) + Faci(n - 2);  //这是递归
	}

	return n;*/

	 int a = 1;			
	 int b = 2;
	 int c = 0;
	 if (n == 1) {
		 return 1;
	 }
	 else if (n == 2) {
		 return 2;
	 }
	 else {
		 for (int i = 3; i <= n; i++) {			//这是迭代算法
			 c = a + b;
			 a = b;
			 b = c;
		 }
		 return c;
	 }
}

int main()
{
    int a = 40;

	int b= Faci(a);
	cout << b << endl;

}

内存题:(有6个)大概正好是一张A4纸,写运行下面程序会有什么结果。考的其实并不复杂。只要给出ta结果就行了。所以内存题,大概就那几个方面,是不是有指针乱指了,申请野指针去了。怎么样的。但,最终结果都是会导致一个问题,那就是 内存泄漏。我大概都写了一下,没看那个人多说,应该是都对了。所以就不多余写出来了。

类似 char* getMemory() 这种东西,有6个,让你思考,ta的结果问题。

猜你喜欢

转载自blog.csdn.net/qq_36912885/article/details/121583495
今日推荐