您的位置:首页 > 理论基础 > 数据结构算法

数组相关题目汇总

2018-01-31 23:48 204 查看
内容会持续更新,有错误的地方欢迎指正,谢谢!

前言

数据结构有这几类:数组、字符串、链表、树、栈、队列。

其中,数组和字符串都是用的连续内存,数组中装数字,字符串中装字符,这两个都是面试中出现频率最高的数据结构;链表和树需要大量指针,特别考察代码的鲁棒性;栈与递归紧密相关,队列与BFS紧密相关。

数组的时间效率高,空间效率低。为了解决数组空间效率低的问题,人们又实现了多种动态数组,比如:STL中的vector。

当数组作为函数的参数进行传递时,数组就自动退化为指针。

在面试的时候,一定要展示敏捷的思维能力、追求完美的激情、不怕困难的态度。

如何展示敏捷的思维能力:一般看到一道题都会马上有最直观的算法,一般不是最优的,但不妨告诉面试官,这样至少给人一种思维敏捷的印象。

如何才能有追求完美的激情:当想出几种思路之后,面试官可能仍然不满意,还在提示有更好的办法,这时我们不要轻言放弃,而要有积极思考的态度,努力从不同角度去思考问题。

有些题目真的很难,但他希望看到应聘者能够有激情、有耐心地去尝试新思路,而不是碰到难题就退缩。

数组中重复的数字

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

法一:先排序,再从排序的数组中找重复的数字,时间复杂度为O(nlogn)

法二:需要O(n)的空间来记录,O(1)的时间便可判断是否已包含重复数字

法三:这是最好的方法。若不存在重复的数字,那每个下标对应的数字 和 下标值 相等,也就是说a[i]=i。由此,以数组{2,3,1,0,2,5,3}为例,从下标为0开始,第一个数字2不等于下标0,就把数字2 和 下标为2的数字1 交换,得到数组{1,3,2,0,2,5,3};再从下标为0开始,再把数字1和下标为1的数字3交换,得到数组{3,1,2,0,2,5,3};再从下标为0开始,同理,得到数组{0,1,2,3,2,5,3};再从下标为0开始,符合要求,下标0,1,2,3都符合;下标为4时,数字2 和 下标为2的数字2 相等,则输出2。

bool duplicate(int numbers[], int length, int* duplication)
{
if(numbers==nullptr||length<=0)//数组不存在 或 数组存在但长度小于等于0
return false;
for(int i=0;i<length;++i)//存在长度大于等于0的数组,但每个元素的值不能超出范围
{
if(numbers[i]<0||numbers[i]>length-1)
return false;
}
int temp;
for(int i=0;i<length;++i)
{
while(i!=numbers[i])
{
if(numbers[i]==numbers[numbers[i]])
{
*duplication=numbers[i];
return true;
}
//交换,一定要注意
temp=numbers[i];
numbers[i]=numbers[temp];
numbers[temp]=temp;
//不能像下方这样写
//temp=numbers[i];
//numbers[i]=numbers[numbers[i]];
//numbers[numbers[i]]=temp;
}
}
return false;
}


尽管上述方法中有两重循环,但每个数字交换的次数可以为:0次、1次、2次就可找到属于他自己的位置,所以,总的时间复杂度是O(n),以及O(1)的空间复杂度。

不修改数组找出重复的数字

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

法一:需要O(n)的空间来记录,O(1)的时间便可判断是否已包含重复数字

法二:二分思想,根据前后两部分的个数进行判断:根据中间的数字m把1~n分为两部分,前一半为1~m,后一半为m+1~n。如果1~m的数字的数目大于m,那么前一半中一定包含重复的数字;否则,后一半中一定包含重复的数字。接下来,我们可以继续把包含重复的数字的区间一分为二,直到找到一个重复的数字。具体的逻辑,读者慢慢去思考动手吧。

小诀窍

根据上面两题,如果面试官提出不同的功能要求(找出任意一个重复数组、找出所有重复数字)或者性能要求(时间效率优先、空间效率优先),那么我们最终选取的算法也将不同。这说明在面试中和面试官交流的重要性,所以,问清再写!

二维数组中的查找

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。



思路:首先选取数组中右上角的数字。如果该数字等于要查找的数字,查找过程结束;如果该数字大于要查找的数字,剔除这个数字所在的列;如果该数字小于要查找的数字,剔除这个数字所在的行。也就是说如果要查找的数字不在数组的右上角,则每一次都在数组的查找范围中剔除一行或者一列,这样每一步都可以缩小查找的范围,直到找到要查找的数字,或者查找范围为空。如图:



(矩阵中加阴影背景的区域是下一步查找的范围)

当然,也可以从左下角开始,代码如下:

bool Find(int target, vector<vector<int> > array) {
int rowCount=array.size();
int colCount=array[0].size();
int i=0,j=0;
for(i=rowCount-1,j=0;i>=0&&j<=colCount-1;)//从左下角开始
{
if(array[i][j]==target){
return true;
}
if(array[i][j]>target){
i--;
continue;
}
if(array[i][j]<target){
j++;
continue;
}
}
return false;
}


小诀窍

当问题比较复杂时,可以通过具体的例子找出其中的规律,如上分析流程图所示。

总结

学会了上述一维数组和二维数组的两类题,其他数组的题型迎刃而解了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数组 数据结构 面试