算法——数组和Hash(30%)
2012-12-18 15:10 msfte 阅读(1667) 评论(0) 编辑 收藏 举报1,求子数组的最大和(数组)
分析:
1)枚举:遍历每个子数组,比较并记录最大的
2)分治:从中间分开,有三种情况:(1)最大子数组在左边,(2)最大子数组在右边,(3)最大子数组包括中间的元素。T(n)=2T(n/2)+O(n): O(nlogn)
3)动态规划:(1)子结构:从开始到当前元素。(2)子结构Cache:1,内部最大值。2包含当前元素的最大值。(3)状态转移:1,如果前一个子结构的Cache2为负,当前则Cache2为当前元素,否则为前一元素Cache2加当前元素。2当前Cache1为当前Cache2和前一元素Cache1较大者。 O(n)
代码:
1)枚举
private int Enumeration(int[] array) { if (array == null || array.Length == 0) return -1; int? max = null; for (int i = 0; i < array.Length; i++) { int sum = 0; for (int j = i; j < array.Length; j++) { sum += array[j]; if (max == null || sum > max) max = sum; } } return max.Value; }
2)分治
private int DivideAndConquer(int[] array) { if (array == null || array.Length == 0) return -1; return DivideAndConquerRecur(array, 0, array.Length - 1); } private int DivideAndConquerRecur(int[] array, int low, int high)//T(n):O(nlogn) { if (low >= high) return array[low]; int max = array[low]; int middle = low + (high - low) / 2; int left = DivideAndConquerRecur(array, low, middle - 1);//T(n/2) int right = DivideAndConquerRecur(array, middle + 1, high);//T(n/2) int middleMax = GetMiddleMax(array, low, high, middle);//O(n) return GetBigger(GetBigger(left, right), middleMax); } private int GetMiddleMax(int[] array, int low, int high, int middle) { int middleMax = array[middle]; int middleSum = 0; for (int i = middle; i <= high; i++) { middleSum += array[middle]; if (middleSum > middleMax) middleMax = middleSum; } middleSum = 0; for (int i = middle; i >= low; i--) { middleSum += array[middle]; if (middleSum > middleMax) middleMax = middleSum; } return middleMax; } private int GetBigger(int first,int second) { return first > second ? first : second; }
3)动态规划
private int DynamicProgramming(int[] array) { int max = array[0]; int maxUntil = array[0]; for (int i = 1; i < array.Length; i++) { if (maxUntil <= 0) maxUntil = array[i]; else maxUntil = array[i] + maxUntil; if (maxUntil > max) max = maxUntil; } return max; }
2,查找最小的k个元素(数组)
3, 假设你有一个用1001个整数组成的数组,这些整数是任意排列的,但是你知道所有的整数都在1到1000(包括1000)之间。此外,除一个数字出现两次外,其他所有数字只出现一次。假设你只能对这个数组做一次处理,用一种算法找出重复的那个数字。如果你在运算中使用了辅助的存储方式,那么你能找到不用这种方式的算法吗?
4, 输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。
要求时间复杂度是
O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。
例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。
5, n个数字(0,1,…,n-1)形成一个圆圈,从数字0开始,
每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。当一个数字删除后,从被删除数字的下一个继续删除第m个数字。
求出在这个圆圈中剩下的最后一个数字。
6, 输入两个整数
n 和m,从数列1,2,3.......n 中随意取几个数,
使其和等于
m ,要求将其中所有的可能组合列出来.
7, 有两个序列
a,b,大小都为n,序列元素的值任意整数,无序;
要求:通过交换
a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。
8,收藏了1万条url,现在给你一条url,如何找出相似的url。(面试官不解释何为相似)
9,一个整数数组,长度为n,将其分为m份,使各份的和相等,求m的最大值
比如{3,2,4,3,6} 可以分成{3,2,4,3,6} m=1;
{3,6}{2,4,3} m=2
{3,3}{2,4}{6} m=3
所以m的最大值为3
10, 求一个数组的最长递减子序列比如
{9,4,3,2,5,4,3,2}的最长递减子序列为{9,5,4,3,2}
11, 一个数组是由一个递减数列左移若干位形成的,比如{4,3,2,1,6,5}
是由{6,5,4,3,2,1}左移两位形成的,在这种数组中查找某一个数。
12, 和为n连续正数序列(数组)。
题目:输入一个正数n,输出所有和为n连续正数序列。
例如输入15,由于1+2+3+4+5=4+5+6=7+8=15,所以输出3个连续序列1-5、4-6和7-8。
分析:这是网易的一道面试题。
13, 调整数组顺序使奇数位于偶数前面(数组)。
题目:输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,
所有偶数位于数组的后半部分。要求时间复杂度为O(n)。
14, 找出数组中两个只出现一次的数字(数组)
15, 把数组排成最小的数(数组、算法)。
题目:输入一个正整数数组,将它们连接起来排成一个数,输出能排出的所有数字中最小的一个。
例如输入数组{32, 321},则输出这两个能排成的最小数字32132。
请给出解决问题的算法,并证明该算法。
16, 旋转数组中的最小元素(数组、算法)。
题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。
17, 数组中超过出现次数超过一半的数字(数组)
题目:数组中有一个数字出现的次数超过了数组长度的一半,找出这个数字。
18, 一个int数组,里面数据无任何限制,要求求出所有这样的数a[i],其左边的数都小于等于它,右边的数都大于等于它。
能否只用一个额外数组和少量其它空间实现。
19, a~z包括大小写与0~9组成的N个数用最快的方式把其中重复的元素挑出来。
20, 求随机数构成的数组中找到长度大于
=3的最长的等差数列9 d-x' W) w9 ?" o3 b0 R
输出等差数列由小到大:
如果没有符合条件的就输出
格式:
输入[1,3,0,5,-1,6]
输出[-1,1,3,5]
要求时间复杂度,空间复杂度尽量小
21, 用递归的方法判断整数组a[N]是不是升序排列
22,数组al[0,mid-1] 和 al[mid,num-1],都分别有序。将其merge成有序数组al[0,num-1],要求空间复杂度O(1)
23,求旋转数组的最小元素(把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1)
24,有一个整数数组,求数组中第二大的数
25,对于给定的整数集合S,求出最大的d,使得a+b+c=d。a,b,c,d互不相同,且都属于S。集合的元素个数小于等于2000个,元素的取值范围在[-2^28,2^28 - 1],假定可用内存空间为100MB,硬盘使用空间无限大,试分析时间和空间复杂度,找出最快的解决方法。
26,给一个浮点数序列,取最大乘积子序列的值,例如 -2.5,4,0,3,0.5,8,-1,则取出的最大乘积子序列为3,0.5,8。
27,一个数组里,数都是两两出现的,但是有三个数是唯一出现的,找出这三个数。
28,给定一整型数组,若数组中某个下标值大的元素值小于某个下标值比它小的元素值,称这是一个反序。
即:数组a[]; 对于i < j 且 a[i] > a[j],则称这是一个反序。
给定一个数组,要求写一个函数,计算出这个数组里所有反序的个数。
29,有两个序列A和B,A=(a1,a2,...,ak),B=(b1,b2,...,bk),A和B都按升序排列,对于1<=i,j<=k,求k个最小的(ai+bj),要求算法尽量高效。
30,有20个数组,每个数组里面有500个数组,降序排列,每个数字是32位的unit,求出这10000个数字中最大的500个。
31,一个N个元素的整形数组,如何找出前K个最大的元素
32,给定一数组,输出满足2a=b(a,b代表数组中的数)的数对
33,一个有序数组(从小到大排列),数组中的数据有正有负,求这个数组中的最小绝对值
34,有一个数组a,设有一个值n。在数组中找到两个元素a[i]和a[j],使得a[i]+a[j]等于n,求出所有满足以上条件的i和j。
35,1万个元素的数组,90%的元素都是1到100的数,10%的元素是101--10000的数,如何高效排序。
36,有序数组里二分查找一个数(如果有相同的找最后一次出现的)。
37,数组里找到和最接近于0的两个值。
38,对长度12的有序数组进行二分查找,目标等概率出现在数组的每个位置上,则平均比较次数为
39,一个文件有N个单词,每行一个,其中一个单词出现的次数大于N/2,怎么样才能快速找出这个单词
40,有一亿个数,输入一个数,找出与它编辑距离在3以内的书,比如输入6(0110),找出0010等数,数是32位的
41,一个文本,一万行,每行一个词,统计出现频率最高的前10个词(词的平均长度为Len)。并分析时间复杂度。
42,求数组中最长递增子序列
43,A[i]是一个有序递增数组,其中所有的数字都不相等,请设计一种算法,求出其中所有的A[i]=i的数字并分析时间复杂度,不分析复杂度不得分。
44,N个数组,每个数组中的元素都是递增的顺序,现在要找出这N个数组中的公共元素部分,如何做? 注:不能用额外辅助空间。
45,降序排列的数组,找到其中两个不同的值,其乘积最接近一个给定的值M,感觉和加法求和很类似
46,序列123...N,N介于3和9之间,在其中加入+-或者空格,使其和为0,
如123456 1-2 3-4 5+6 7 等价于1-23-45+67=0。请问,如何获得所有组合?
47,判断两个数组中是否有相同的数字
48,快排最坏情况下是O(n^2),
49,长度为N的数组乱序存放着0带N-1.现在只能进行0与其他数的swap操作,请设计并实现排序,必须通过交换实现排序。
50,有个长度为2n的数组{a1,a2,a3,...,an,b1,b2,b3,...,bn},希望排序后{a1,b1,a2,b2,....,an,bn},要求时间复杂度o(n),空间复杂度0(1)。
51,如何找到一个数组中的两个数,他们的和为0
52,数组a[n]里存有1到n的所有树,除了一个数removed,找出这个missing的树
53,20个排序好的数组,每个数组500个数,按照降序排序好的,让找出500个最大的数。
54,一在线推送服务,同时为10万个用户提供服务,对于每个用户服务从10万首歌的曲库中为他们随机选择一首,同一用户不能推送重复的,设计方案,内存尽可能小
55,实现完整顺序表(Init,Search,Insert,Update,Delete,Length)
56,二分查找
int binarySearch(int *array,int start,int end ,int value){ int mid = start+ (end-start)/2; if(value ==array[mid] ) { return mid; } if(value > array[mid]){ start = mid+1; } else{ end = mid-1; } if(end<start){ return -1; } else{ return binarySearch(array, start,end,value); } return 0; }
57,实现完整哈希表(Init,Search,Insert,Update,Delete,Length)
58,把list2没有的元素加到list1里 void Union(List<int> list1,List<int> list2){}
59,顺序表的Merge SeqList MergeList(SeqList list1,SeqList list2){}