这一章是关于第4章 数组
1. 如何找出数组中唯一的重复元素
第一种方法:空间换时间。建立一个hash表,在python中可以用字典来代替。思路:首先定义一个字典,将字典中的元素值(key值)都设置为0,将原数组中的元素一一映射到字典的key中,当对应key中的value为0时,置key的值为1,如果为1,表明是重复的。输出即可
第二种方法:累加求和。(如果数据量巨大时可能会溢出)
第三种方法:异或法。重要知识点,相同元素异或时,其运算结果是0;当不同的元素异或时,其运算结果不为0;任何数与数字0异或时,其运算结果为该数。在本题中可以将数组中的元素逐一进行异或运算,得到的值再与数字1,2,3...N进行异或运算。得到的结果就是重读的数
2.如何查找数组中元素的最大值和最小值
第一种方法:蛮力法。定义min和max两个变量,都初始化定义为数组首元素的值,然后从数组的第二个元素开始遍历,如果比max大,替换max,比min小,替换min。一共比较了2n-2次。
第二种方法:分治法。分治法就是将一个规模为n的,难以解决的大问题,分割成k个规模较小的子问题,采用各个击破、分而治之的策略得到各个子问题的解,然后将各个子问题的解进行合并,从而得到原问题解的一种方法。在本题中,将所有的元素两两分组,值小的数字放在左边,值大的数字放在右边,需要n/2次,这样最小的值一定都在左边,而最大的值一定都在右边,再从最左边、最右边找值即可,一共需要n/2*3次。
第三种方法:变形的分治法--递归法。将数组分成左右两个部分,在左边部分找最大最小值,再在右边部分找最大最小值,综合起来的最大最小值就是最后的结果,对于最左最右的划分可以用到递归的方法,直到最左最右只有两个值为止。
3.如何找出旋转数组的最小值 (有序数数组最开始的若干元素搬到数组的末尾,[3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该旋转最小的数字为1)
查找的话,我觉得大部分可以用二分法。给定两个指针 low(指向首端),high(指向尾端),正常情况(arr[high] 大于 arr[low], 如果没有代表数组没有旋转)。mid = (high + low )/ 2。下面分情况讨论 :
a. arr[mid] < arr[mid-1]; arr[mid] 就是最小值 b. arr[mid+1]<arr[mid]; arr[mid+1]就是最小值
c. arr[high] > arr[mid]; 在左边 d arr[high] < arr[mid]; 在右边
e.如果arr[high] = arr[mid] 并且 arr[low] = arr[mid],类似[2,2,2,1,2]等,只能左右遍历。
5. 如何找出数组中出现奇数次的数
第一种方法:字典法。将数组元素看作字典的key,如果key不存在,value值设置为1,如果key存在,value设置为0 (翻转),最后统计value为1 的个数。
第二种方法:异或法。通过异或法,我们目前也只是消除了偶数次的值,最后的结果是两个奇数次的值的异或。将异或的结果与所有第position位为1 的数字异或,出现的结果一定是两个数中的一个
6.如何找出第k小的数 ([4,0,1,0,2,3] 第3小的元素是1)
第一种方法:排序法。采用最高效的方法,快速排序。
第二种方法:部分排序。第一次找出最小值,第二次在剩下的数中找出最小的,第k次遍历就能找到最小的了
第三种方法:类快速排序法。arr[low...high]中的第一个元素作为划分依据,然后将数组分为三个部分,小于等于它,它自己,比它大,如果小于它的数刚好有k-1个,那么它就是第k小的元素,如果大于k-1个,代表在左边,找第k小;如果大于k-1,代表在右边,找k-(i-low)-1 小元素。
扩展:o(N)查找数组的前k个,初始化前3名,r1,r2,r3 分别代表第一名,第二名,第三名 。如果新来的数字大于谁替换谁的位置。
7.如何求数组中两个元素的最小距离 (数组中含有重复元素,给定两个数字num1和num2,求出现的最小位置)。
第一种方法:双重遍历。外循环查找num1的值,内循环查找num2的值。
第二种方法:动态规划法。遇到num1,记录下标值,与num2的上次下标值进行相减;如果遇到num2,与num1的上次下标值进行相减,求min值
8.如何求解最小的三元组距离 (已知三个升序数组,请在三个数组中各选择一个数字组成三元组的距离最小,三元数组的定义是D = max(|a-b|,|b-c|,|a-c|))
首先每一个数组都取第一个元素, 然后计算距离,然后再找到三个数中最小的那一个,往后移动一位,再次寻找最小值。
9.如何求数组中绝对值最小的数字 (一个升序排列的数组,数组中可能有正数,有负数,还有0)
如果第一个数是正数,那么最小值就是第一个数,如果第一个数是负数,那么最小的值就是最后一个数。又有正数又有负数,就可以找到临界点。可以通过二分法找临界点,如果中间这个值是0,那么就是最小的值;如果这个数大于0,比它小的数也大于0,那么最小值就在左边;如果这个数小于0,比它大的数也小于0,那么就是在右边。递归找
10.如何求数组连续最大值 (数组[1,-2,4,8,-4,7,-1,-5] 中,最大和的子数组为[4,8,-4,7])
定义一个和,首先等于第一个数,再定义一个变量,从第二个数进行遍历,用和去加这个变量,如果结果小于0,那么和置0;如果结果大于0,比较结果与原来的和,如果大于,就更新和,如果小于,就不变,继续往下运行。
13. 如何在不排序的情况下求数组的中位数
类快速排序的方法,类似与找第k大的值。pos大于一半,那么在左边,等于,就是,小于,在右边。
14.如何求集合的所有子集 (两个元素<a,b>,全部子集为<a,ab,b>)
第一种方法:位图法,模拟数组加一;使用非递归的思想,如果位数对应位1,就输出,否则就不输出。
第二种方法:迭代法。每一次迭代,都是上一次的迭代结果+上一次迭代中的每一个元素加上当前迭代的元素+当前迭代的元素。
15.如何对数组进行循环位移
翻转法,前半段翻转,后半段翻转,合起来再翻转
16.如何在有规律的二维数组中进行高效的数据查找。
在有序的数组中进行查找,二分法是一个很不错的选择。
17.寻找最多的覆盖点 (一根长为L的木棍,最多能够覆盖多少坐标轴的多少点)
假设两个点分别为j 和 i,满足条件a[j]-a[i] < L && a[j+1] - a[i] > L,并且j - i 最大。首先定义i是最开始的一点,j往后增大,直到超过L, 这时候将i+1,j从当前位置继续加
18.如何判断请求能够在给定的储存条件下完成 (计算占R, 储存占O)
按照R-Q的大小进行排序,从大到小进行处理。
22.如何从3个有序数组中找出它们的公共元素
可以充分使用有序这个条件,如果a<b,a中的数据后移,如果b<c,那么b的数据后移, 否则,c的数据后移。有点类似最小的距离,都是最小的数据后移。