排版若是影响阅读能够 阅读原文python
数组能够说是最简单的一种数据结构,它占据一块连续的内存并按照顺序存储数据。ios
建立数组时,须要先指定数组容器的大小,而后根据大小分配内存。c++
因为数组的内存是连续的,因而能够根据下标在O(1)时间读写任何元素,所以它的时间效率很高。git
根据数组时间效率高的优势, 实现简单的哈希表,用数组来实现简单的哈希表,把数组的下标设为哈希表的键,数组元素为哈希表的值,
有了这样的哈希表,咱们能够在O(1)时间内查找。程序员
为了解决数组空间效率不高的问题,人们又设计实现了多种动态数组,好比c++中的STL中的vector,为了不浪费,先为数组开辟较小的空间,而后往数组中添加数组。
当数组的数据超过数组容量时,咱们再从新分配一块更大的空间(c++ 中vector 为以前的两倍,python list也为以前的两倍),把以前的数据复制到新数组中,再把以前的内存释放。
这对时间性能有负面影响,所以使用动态数组时要尽可能减小改变数组容量大小的次数。github
在c/c++中,数组和指针是既相关又有区别的概念,当咱们声明一个数组时,其数组的名字也是一个指针,该指针指向数组的第一个元素。咱们能够用指针来访问数组。
c/c++没有记录数组的大小,所以在访问数组元素时,程序员要确保没有超出数组的边界。面试
运行下面代码,请问输出什么?算法
#include <iostream> using namespace std; int GetSize(int data[]) { return sizeof(data); } int main(int argc, const char* argv[]) { int data1[] = {1, 2, 3, 4, 5}; int size1 = sizeof(data1); int* data2 = data1; int size2 = sizeof(data2); int size3 = GetSize(data1); cout << size1 << endl << size2 << endl << size3 << endl; return 0; }
答案是: 20, 8, 8,data是一个数组,sizeof(data)求的是数组的大小,5个整数,每一个整数占4个字节,所以占20个字节。
data2是指针,指针在32位操做系统上占4位,64位操做系统占8位。在c/c++中,当数组看成函数的参数进行传递时,数组就自动退化为同类型的指针。所以,尽管函数GetSize的参数data被声明为数组,但他会退化为指针。编程
在一个长度为n的数组里的全部数字都在0~n-1的范围内。数组中某些数字是重复的,可是不知道有几个数字是重复的了,也不知道数字重复了几回。请找出数组中任意一个重复的数字。例如,若是输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出重复的数字2或者3。数组
解法一: 解决这个问题的一个简单的办法是先把输入的数组排序。从排序的数组中找出重复的数字只须要扫描排序的数组就能够了。排序一个长度为n的数组须要O(nlgn)的时间。
解法二: 还能够利用哈希表来解决这个问题,从头至尾按顺序扫描数组的每一个数字,每扫描到一个数字的时候,均可以用O(1)的时间来判断哈希表里是否已经包含了该数字,若是哈希表里尚未这个数字,就把它加入到哈希表。若是哈希表里已经存在这个数字,就找到了一个重复的数字。这个算法的时间复杂度是O(n),但它提升时间效率是以一个大小为O(n)的哈希表为代价的。
解法三: 咱们注意到数组中的数字都在0~n-1的范围内。若是这个数组中没有重复的数字,那么当数组排序以后数组i将出如今下标为i的位置。因为数组中有重复的数字,有些位置可能存在多个数字。 如今让咱们重排数组,从头至尾扫描数组,当扫描到下标i时,判断数组下标i的元素是否和i相同(arr[i] == i),不相同,则把它和第arr[i]个数进行交换(swap(arr[i], arr[arr[i]])),直到arr[i]和i同等,把arr[i]放回属于他的位置。重复上述的操做。
直到咱们发现一个重复的数字。
arr[] = {2, 3, 1, 0, 2, 5, 3} i = 0; arr[i] != i; swap(arr[i], arr[arr[i]]); // {1, 3, 2, 0, 2, 5, 3} arr[i] != i; swap(arr[i], arr[arr[i]]); // {3, 1, 2, 0, 2, 5, 3} arr[i] != i; swap(arr[i], arr[arr[i]]); // {0, 1, 2, 3, 2, 5, 3} i = 1; arr[i] == i; i = 2; arr[i] == i; i = 3; arr[i] == i; i = 4; arr[i] != i; arr[arr[i]] = arr[i]; return arr[i];
c++: array_repeat.cpp
python: array_repeat.py
本题考点:
在一个长度为n+1的数组里的全部数字都在1~n的范围内,因此数组种至少有一个数字是重复的。 请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,若是输入长度为8的数组{2, 3, 5, 4, 3, 2, 6, 7}, 那么对应的输出是重复的数字2或者3。
解法一: 看起来和上一题相似,因为题目要求不能修改输入的数组,咱们能够建立一个n+1的数组为哈希表来辅助,则须要O(n)的空间,O(n)的时间。
解法二: 接下来咱们尝试O(1)的空间,咱们把从1-n是数字从中间的数字m分为两部分,前一半为1m,后一半为m+1n,若是1~m的数字出现的次数超过m,那么这一半确定有重复的数字,不然另外一半确定有重复的数字。咱们能够继续把重复的区间一分为二,直到找到一个重复的数字。这个过程和二分法很像,只是多了一步统计区间里的数字。
每次统计范围内的数字O(n),二分查找O(lgn),时间复杂度为O(nlgn),空间复杂度为O(1),这是利用时间换空间的算法。
int nums[] = {2, 3, 5, 4, 3, 2, 6, 7}; // length = 8; //mid=(1+8)/2, 1~4 出现了5次,5-7 出现了3次,重复数字在1~4内 //mid=(1+4)/2, 1~2 出现了2次,3-4 出现了3次,重复数字在3~4内 //mid=(3+4)/2, 3 出现了2次,4 出现了1次,重复数字为3
须要指出的是,这种算法并不能找出全部重复的数字。例如上例,咱们只找出了3,其实2也是重复的,因此若是面试官要求的功能不一样或是性能要求不一样,咱们选择的算法也不相同,这就须要和面试官沟通。
c++: array_repeat2.cpp
python: array_repeat2.py
本题考查:
在一个二维数组中,每一行都按照从左到右的递增的顺序排序,每一列都按照从上到下的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
解法一: 遍历数组,判断目标元素是否在二维数组内,时间复杂度O(m*n)
, 空间复杂度O(1);
解法二: 找到目标元素所在的列,遍历目标列,时间复杂度O(m+n)
,空间复杂度O(1);
解法三: 从最右上角开始找,首先,咱们选取数组右上角的9,因为9>7, 而且9仍是第4列的最小的数,所以7不可能出如今数字9所在列,因而咱们把这一列从须要考虑的区域踢出,整个过程以下如所示。
c++: find_number_in_2D_array.cpp
python: find_number_in_2D_array.py