2015.02.最新面试题总结(I)

来源:互联网 发布:共享经济 知乎 编辑:程序博客网 时间:2024/06/01 08:12

Q1:  数组A的元素有如下关系:A[x] = power(2, p) * power(3, q); 

比如

A[0] = 1;

A[1] = 2;
A[2] = 3;
A[3] = 4;
A[4] = 6;
A[5] = 8;
A[6] = 9;
A[7] = 12;

求 A[N] , N >=0  && N <=200 in case of overflow

分析:

其实就是数学上求smooth number。 参考 http://mathworld.wolfram.com/SmoothNumber.html 。

python code如下:

def smoothNumber(n):    A = [0]*201    A[0] = 1    j = 1    for k in range(1,201):        if 2*A[k-j] < 3**j:            A[k] = 2*A[k-j]        else:            A[k] = 3**j            j += 1    return A[n]


Q2. 类似于最大和的连续子数组。 但是有些不一样。
for array A[N],which can have negative values or positive values.
B[i][j] = Math.abs(A[i] + ... A[j]);
求 最小的 B[i][j];

分析:

1. 暴力解法复杂度是O(n^2)。

2. 下面的方法可以做到O(nlog(n)) 
time, O(n) space: 先求部分和序列 S[i] = A[0] + A[1] + ... + A[i],i = 0 to n
-1。所有n^2部分和可以由S序列中两项相减得到。对S排序,找相差最小的两项S[i], S
[j], abs(B[i][j]) 即得。注意,如果abs(S[i])中有可能有比所得到的B[i][j]中还小的值。

python code如下:

def absmin_subarray(A):    S = A[:]    for i in range(1, len(A)):        S[i] = S[i-1] + A[i]    S.sort()    min_s = abs(S[0])    for i in range(1, len(S)):        min_s = min(min_s, abs(S[i]-S[i-1]), abs(S[i]))    return min_s


Q3: N是一个很大的正整数——可能到10^15次方,
简单起见,不考虑溢出,或者假设用python
A 是一个array,里面存着一些正整数,up to 1000个

从1 - N这N个数,有多少个数,不能被A中的任何一个数整除的?

举个例子:
N = 10
A = [2,4,5]
那么返回4 (1,3,7,9满足条件)

分析:

方法1. 暴力求解,用数组存满足条件的数,缺点是内存可能不够,10^15 要至少 125 TB 的內存,这是不可能的。

方法2. Consider the simplest case: A={2}, then any odd number below N is OK, so the
result would be (N - N/2). Then consider A={2, 3}, any number below N that 
is not mutiply of 2 or 3 is OK, so the result would be (N - N/2 - N/3 + N/6)
. Then consider A={2, 3, 5}, the result would be (N - N/2 - N/3 - N/5 + N/6 
+ N/10 + N/15 - N/30). 
So there is a general rule: 
for A={a1, a2, ..., aN}, if ai is not dividable by aj for any i != j, then 
we could:
1. for i from 1 to N, calc r1 = N - SUM(N/ai);
2. for i, j from 1 to N, i != j, calc r2 = r1 + SUM(N/(ai*aj));
3. for i, j, k from 1 to N, i != j != k, calc r3 = r2 - SUM(N/(ai*aj*ak));
...
until all numbers in A are chosen.
then the final rN is the result.

So for the problem, first we preprocess A to eliminate any multiplies in A. 
For example, A={2, 4, 5}, we can eliminate 4 because it is a mutiply of 2 
which is also in A. So A'={2, 5}, then we calc:
r1 = 10 - 10/2 - 10/5 = 10 - 5 - 2 = 3;
r2 = r1 + 10/10 = 3 + 1 = 4;
then the final result is 4.




Q4: Write a function that is given an array of integers. It should return true 
if and only if there are two distinct indices i and j into the array such 
that the difference between arr[i] and arr[j] is at most L and the 
difference between i and j is at most K.

分析:

用hashmap存(key,value)对 (arr[i]/L, arr[i]),对每个arr[j] 检查是不是key=arr[j]/L, arr[j]/L-1,arr[j]/L+1,已经存在。 

python code如下:

def find_close_numbers(A, K, L):    hm = {}    for i in range(len(A)):        if i>K:             hm.pop(A[i-K-1]//L)        key = A[i]//L        if key in hm \           or key-1 in hm and abs(hm[key-1] - A[i])<=L \           or key+1 in hm and abs(hm[key+1] - A[i])<=L:             return True                hm[key] = A[i]    return False

Q4.  Given continuous incoming real time stock price stream,
  1) design data structure to support query for max, min price in the past 
12 months.
  2)implement in code

分析:就是sliding window max的问题,详细讨论在 http://leetcode.com/2011/01/sliding-window-maximum.html。

解法1:最直接的想法是用heap,维护一个最小堆和最大堆,支持删除。但是时间复杂度是n Log(n),不太好。

解法2:用deque,时间复杂度是O(n),具体解法如下:

class SlidingWindowMinMax:    def __init__(self, w):        self.__timestamp = []        self.__dq_min = []        self.__dq_max = []        self.__window_size = w    def add(self, timestamp, value):        i = 0        while self.__timestamp and timestamp - self.__timestamp[i] >= self.__window_size:            i+=1        if i>0:             self.__remove(self.__timestamp[i-1])        del self.__timestamp[:i]                    self.__timestamp.append(timestamp)        self.__update_dq_min(timestamp, value)        self.__update_dq_max(timestamp, value)                def __update_dq_min(self, timestamp, value):         while self.__dq_min and self.__dq_min[-1][1]>value:            del self.__dq_min[-1]        self.__dq_min.append([timestamp, value])                    def __update_dq_max(self, timestamp, value):        while self.__dq_max and self.__dq_max[-1][1]<value:            del self.__dq_max[-1]        self.__dq_max.append([timestamp, value])    def __remove(self, timestamp):        i = 0        while self.__dq_min and self.__dq_min[i][0] <= timestamp:            i+=1        del self.__dq_min[:i]        i = 0        while self.__dq_max and self.__dq_max[i][0] <= timestamp:            i+=1        del self.__dq_max[:i]        def getMax(self):        return self.__dq_max[0][1]    def getMin(self):        return self.__dq_min[0][1]



G家面试题:

1. 无序数组求逆序对的数量
逆序对就是A[i] > A[j] 且 i<j

比如,[4,3,2,1] 有六个逆序对, [4,3], [4,2], [4,1], [3,2], [3,1], [2,1]。

分析:
用merge sort算法,归并的时候进行统计,时间复杂度n log(n)。 

python code如下:

def merge_sort(A):    if len(A)<=1:        return A, 0        left, ln = merge_sort(A[:len(A)//2])    right, rn = merge_sort(A[len(A)//2:])        result = left + right    i = len(left)-1    j = len(right)-1    cn = 0    while i >=0 and j>=0:        if left[i] > right[j]:            result[i+j+1] = left[i]            cn += j+1            i-=1        else:            result[i+j+1] = right[j]            j-=1        if j >= 0:         result[:j+1] = right[:j+1]        return result, cn+ln+rndef reverse_order_pair(A):    result, n = merge_sort(A)    return n


2. 给一个string的dictionary。求所有不share char的string pair中长度乘积最大的。
比如给了 cat dog map fast所求pair就是 (dog, fast) 输出12.

follow up: 求所有只share一个char的string pair中长度乘积最大的。

分析:

先从大到小排序,然后暴力求解。

def max_product(A):    A.sort(key=len, reverse=True)    result = 0    for i in range(len(A)):        for j in range(i+1, len(A)):            if result < len(A[i])*len(A[j]):                <span style="color:#ff0000;">if not any(c for c in A[i] if c in A[j]):</span>                    result = len(A[i])*len(A[j])            else: break    return result

follow up,只要把红色的一行改成 if len(list(c for c in A[i] if c in A[j]))==1: 就可以了。

其他解法:

如果,字符的范围很小,限于26个字母,不考虑大小写。

可以用hash每个dict中的string到 unordered_map<bitset<26>, int>,key是字符的map, bitset<26>,value是string的最大长度(因为两个不同的string可能用相同的key,比如abc vs aabbcc,这是要存长度6而不是3)。

然后对每个string的key的bitset<26>取反,然后把所有可能的key(有2^a个,a是key取反后,bit为1的个数)都试一遍。

最后找到最大的。时间复杂度是O(l + a*2^a),l是总字符个数, a是小于26的数.


3. 给一个0和1的矩阵,先全部为0,然后,用一个正方形或者三角形去覆盖这个矩阵,
若覆盖到的方格面积大于等于1/2,则标1。正方形和三角形的各个顶点都不会超过矩阵
边界。可以假设不存在只有一个格子为1的情况。正方形或者三角形可以在任意位置以
任意角度去覆盖。
那么,给你一个0,1矩阵,判断覆盖该矩阵的是正方形还是三角形。



0 0
原创粉丝点击