Files
Learn-Algorithms/9 Algorithms Job Interview/5.4 数列-查找.md
T
2021-09-13 11:36:49 +08:00

4.6 KiB
Raw Blame History

数列-查找

数组中超过出现次数超过一半的数字

题目:数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字。

+-1 计数法

找数组里面重复的一个数

找数组里面重复的一个数,一个含n个元素的整数数组至少存在一个重复数,请编程实现,在O(n)时间内找出其中任意一个重复数。

  1. hash算法,空间要求多 (注意数组元素要是int类型),数的大小范围和数组长度N都可以是无穷大,这里使用hash算法,空间复杂度是O(n),空间可能无法满足条件。
  2. 先排序,复杂度n(logn);然后遍历一遍就可以知道哪些数重复了。
  3. 高级解法: 将问题转化为 判断单链表中存在环

类似问题:找出数组中唯一的重复元素

查找只出现一次的元素

给一个非空整数数组,比如 [2, 2, 3] ,其余元素均出现2次,找出那个只出现一次的元素。

思路: 异或运算,成对儿的数字就会变成 0,落单的数字和 0 做异或还是它本身

int singleNumber(vector<int>& nums) {
    int res = 0;
    for (int n : nums) {
        res ^= n;
    }
    return res;
}

数组中找出某数字出现的次数

在排序数组中,找出给定数字的出现次数。比如 [1, 2, 2, 2, 3] 中2的出现次数是3次。

分析:

  1. 因为是排序数组,可以使用二分查找
  2. 将二分查找坚持到底,这样在最坏的情况下([2,2,2,2,2,2,2])都有0(lgn)复杂度
int binary_search_first(int *a,int length,int key);
int binary_search_lash(int *a,int length,int key);

大于K的最小正整数

给定一个集合A=0,1,3,8,指定任意一个正整数K,请用A中的元素组成一个大于K的最小正整数。

比如,A=[1,0] K=21 那么输出结构应该为100。

查找最小的k个元素(top-k)

题目:输入n个整数,输出其中最小的k个。 例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4。

topMinK(int *a,int length,int k);
topMaxK(int *a,int length, int k);
  1. 全部排序 复杂度 NlogN , 数据了较大时,内存可能承受不住
  2. 部分排序 维护一个大小为K的数组,由大到小排序,然后遍历所有数据,每个数据跟数组中最小元素比较,如果比最小元素大,就要插入数组了,这里还有寻找插入位置,移动数组元素的cpu消耗。复杂度是N*K
  3. 堆排序 。在这的K较大时(比如这道题目:2亿个整数中求最大的100万之和),上面的算法还是有很多可以改进的地方,如采用二分查找定位插入位置,移动数组元素的计算是躲不过去了。那有没有什么数据结构即能快速查找,还能快速移动元素呢?最好是O(1)复杂度。

答案就是二叉堆。我们可以遍历总量中的每个元素来跟二叉堆中的堆顶元素比较(堆顶元素在小根堆中最小值,在大根堆中是最大值),这样在0(1)复杂度就可以完成查找操作,揭下来需要的操作就是重新调整推结构,复杂度是O(logk),因此整个操作复杂度是 O(n*logk)

top-k 小的时候用 *大根堆* ,top-k 大得时候用 *小根堆*

找第k大的数

比如 1,2,3,4,5,6,7和8这8个数字,低3大的数字是 6

int topK(int * a, int length, int k)

最长公共子序列 (动态规划的经典题目)

【最大/小差问题】 求相邻元素的最大差值,有无序的实数列V[N],要求求里面大小相邻的实数的差的最大值,关键是要求线性空间和线性时间

如 【9,-1,-11,2】 最大差值 = 2-(-11) = 13

最小差 hash合并 最大差 hash分解 桶排序

桶排序 比快排还快,最耗空间

最长递增子序列

题目描述:设L=<a1,a2,…,an>是n个不同的实数的序列,L的递增子序列是这样一个子序列 Lin=< aK1,ak2,…,akm >,其中k1< k2<…< km且aK1< ak2<…< akm。 求最大的m值。

如【5,6,7,3,2,8】 最长子序列 【5,6,7,8】

动态规划

在从1到n的正数中1出现的次数

题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。

例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次。 分析:这是一道广为流传的google面试题。

int one_appear_count(int n);

思路1. 遍历1~n,统计出现1的个数;n足够大时,效率很低 思路2. 分析规律