• 斗鱼C++研发春招实习生笔试总结


    考试题型

    共十道题,前六道是填空题,第七道是简答题,第八道是写出给出程序的输出。

    填空题对字符串和指针考察的比较多,大概三道和字符串有关,不是很难。其次虚函数考了两道,函数指针数组一道。第七道简答题给了三个实例,回答const的在不同情况下的用法;第八道题考的也是虚函数问题,没什么可说的;第九道用伪代码写出行列式求解的算法流程,第十题有两问,第一问找出一个int 数组中重复的数字,第二问要求对自己上一问写的代码进行优化,只写出思路即可。

    下面主要回顾一下最后一题。


    题目:在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组,假设数组中只有一个相同数字。例如,如果输入长度为5的数组{1,2,3,4,2},那么对应的输出是重复的数字2。

    思路1:借鉴二分查找的思想,将数字1~n拆分成1~m和m+1~n两部分,如果数字范围1~m中数字个数大于m,则重复数字在1~m中间,否则重复数字一定在数字范围m+1~n中,算法复杂度为O(nlogn)。

    #include <iostream>
    #include <vector>
    using namespace std;
    class Solution {
    public:
    	int duplication(vector<int> vec){
    		// 空数组
    		int length = vec.size();
    		if (vec.size() == 0) return -1;
    		// 数字超界
    		for (int i = 0; i < length; ++i)
    			if (vec[i]<1 || vec[i]>length - 1) return -1;
    		// 定义数字范围
    		int begin = 1;
    		int end = length - 1;
    		// 指定数字范围内的数字个数
    		while (begin <= end){
    			// 计算数字范围的中点
    			int mid = (begin + end) >> 1;
    			// 统计指定数字范围内的数字个数
    			int count = countrange(vec, begin, mid, length);
    			if (end > begin){
    				// 更新数字范围
    				if (count > (mid - begin + 1)) end = mid;
    				else begin = mid + 1;
    			}else{
    				if (count > 1) return begin;
    				else break;
    			}
    		}
    		return -1;
    	}
    	int countrange(vector<int> vec, int begin, int end, int length){
    		int count = 0;
    		for (int i = 0; i < length; ++i)
    			if (vec[i] >= begin && vec[i] <= end) ++count;
    		return count;
    	}
    };
    int main(){
    	vector<int> vec;
    	vector<int> vec1 = { 1,2,3,4,5,6,7 };
    	vector<int> vec2 = { 1,1,2,3,4,5,6 };
    	vector<int> vec3 = { 2,2,3,3,4,5,6 };
    	Solution solution;
    	cout << solution.duplication(vec) << endl;
    	cout << solution.duplication(vec1) << endl;
    	cout << solution.duplication(vec2) << endl;
    	cout << solution.duplication(vec3) << endl;
    	return 0;
    }
    
    /*
    输出:
    -1
    -1
     1
     3
    */

    思路2:利用类似于桶排序的原理,数组中的所有数字都为0到n-1,可以把这些数字当做数组下标,数值用来统计个数,即i为下标,a[i]为个数,如果a[i]>1,则i为相应的重复数字。时间复杂度为O(n),空间复杂度为O(n)。

    #include<iostream>
    using namespace std;
    bool func(int a[], int length, int *result){
    	/*错误判断省略*/
    	int map[255] = { 0 };
    	for (int i = 0; i < length; i++)map[a[i]]++;
    	for (int i = 0; i < length; i++){
    		if (map[i] > 1){
    			*result = i;
    			return true;
    		}
    	}
    	return false;
    }
    int main(){
    	int a[] = { 1,2,3,4,4,5,6 };
    	int length = sizeof(a) / sizeof(int);
    	int *result = a;
    	func(a, length,result);
    	cout << *result << endl;
    	return 0;
    }
    /*
    输出:
    4
    */

    思路3:如果一个长度为n,值为0到n-1,且没有重复的数组,i从0到n-1,对应的a[0]到a[n-1]不会指向同一个a[i]两次。这里,对于i,先让a[a[i]]加上一数组长度length,如果后面这个i再次出现,那么a[a[i]]必定比length大,那么i就位重复的数。算法复杂度为O(1)。

    #include<iostream>
    using namespace std;
    //a为该数组 length为数组长度 result为找到的一个重复数字
    int func(int numbers[], int length){
    	for (int i = 0; i < length; i++) {
    		int index = numbers[i];
    		if (index >= length) index -= length;
    		if (numbers[index] >= length) return index;
    		numbers[index] = numbers[index] + length;
    	}
    	return -1;
    }
    
    int main(){
    	int a[] = { 1,2,3,4,4,5,6 };
    	int length = sizeof(a) / sizeof(int);
    	int *result = a;
    	cout << func(a, length);
    	return 0;
    }
    /*
    输出:
    4
    */

    参考:https://blog.csdn.net/qq_32957239/article/details/80500183

              https://www.cnblogs.com/zijidan/p/9511235.html

    天上我才必有用,千金散尽还复来!
  • 相关阅读:
    Android学习进程 Java引用 Rxjava MVP
    小试 Xcode 逆向:App 内存监控原理初探
    春招路上孤独的iOSer的心路历程(面经)
    【译】4个你需要知道的Asset Catalog的秘密
    超全!iOS 面试题汇总
    整理 iOS 9 适配中出现的坑(图文)
    旧版Xcode下载地址
    xcode 自动添加注释,生成文档
    NDK_ROOT找不到的解决方法 MACOS
    13个小技巧帮你征服Xcode
  • 原文地址:https://www.cnblogs.com/lutaishi/p/13436323.html
Copyright © 2020-2023  润新知