高级算法日记1:摸底课

来源:互联网 发布:收货人 余杭嘉云淘宝 编辑:程序博客网 时间:2024/06/05 03:08

第一次上课之前,沈教授留了一次摸底作业。下面对这次作业做一个总结。
习题的解答整合了:我自己的作业,其他同学更好的作业以及沈教授的讲解。

Dear all, our lecturer has assigned the first homework for background knowledge assessment, all of you are asked to download the homework (from Group Sharing files) and send it to sunxiangguodut@qq.com after finishing. The due is May 26.
As long as you submit this homwork before due, you will get the points. Problems with * mark are not required. You can get extra points if you solve them.


Homework 1

Sorting, divide & conquer, Greedy


孙相国
161547
sunxianguodut@qq.com


1 The number of cars produced by Toyota company in the past n years are stored in an array A[1], A[2], …, A[n]. We wish to find if there is a period of consecutive years such that the total number of cars produced in this period is exactly equal to M. That is, we wish to find if there exist i and j, 1ijn, such that jk=iA[k]=M. Please design an O(n) time greedy algorithm to solve this problem. You need to give a pseudo code.


我的解答:

def greedy_equal(A, M):    pre, post = 0, 0    s = A[0]    while post < len(A)-1:        if s < M:            post += 1            s += A[post]        elif s > M:            s -= A[pre]            pre += 1        else:            return pre, post    return NoneA = [2, 3, 2, 9, 4, 8, 6, 10, 13, 6, 3, 9]M = 20print(greedy_equal(A,M))

2 In a given sequence, A[1], A[2], …, A[n], a number may occur a multiple number of times. A number is called the dominating number if it occurs strictly more than n/2 times. For example, in the sequence, 2, 4, 5, 2, 2, 6, 2, the number 2 which occurs 4 (> 7/2) times is the dominating number. A sequence may have no dominating number. You may compare two numbers, A[i] and A[j], 1 ≤ i < j ≤ n, to see if A[i] = A[j]. However, we assume this comparison does not tell which one is smaller in case they are not identical. (序列中数的比较只告诉相等与否,不告诉大小。)Please use this kind of comparisons among the numbers in array A and counting to determine if array A has a dominating number. You can expect to know which number is smaller or larger if the two numbers in comparison are not both from array A. (不是序列中俩数字的比较可知大小。)Your algorithm must use divide and conquer method and has O(nlgn) complexity.


我的解答:


事实上,如果序列中存在这样的dominating number,那么这个数字要么在左半边是domination number,要么在右半边是dominating number,要么两边都是dominating number.
因此,有如下的四种情况存在:
1. 两边都没有找到dominating number.此时算法返回None
2. 右半边找到了dominating number,左半边没有dominating number。由于dominating number要求出现次数大于n/2次,而右半边的元素个数为n/2次(为了简化问题,没有考虑取整,这里假设n为偶数),因此右半边的dominating number出现的次数大于n/4.。因此需要联合左半边的数,依次与这个domination number比较,并记录相等的个数,如果大于n/2,那么就返回这个数,反之返回None。
3. 左半边找到了dominating number,右半边没有dominating number。与2相同,此时左右两边操作相反。
4. 两边都找到了dominating number.分别计算这两个dominating number的个数。如果符合条件,就返回。否则,返回None
时间复杂度计算为:T(n)=2T(n/2)+2n
根据主定理得到复杂度为:O(nlogn)


3* 设计一个复杂度为O(n) 的贪心算法来解第2题。


我的解答:


def get_most(A):    candidate=A[0]    count = 1    for item in A[1:]:        if item == candidate:            count +=1        else:            count -=1            if count == 0:            candidate = item            count = 1    return candidatedef get_count(A):    most = get_most(A)    count = 0    for item in A:        if most == item:            count += 1    if count > len(A)/2:        return most, count    else:        return None

4 Given a sequence of n real numbers stored in a array, A[1], A[2], …, A[n]. We wish to find two numbers A[i] and A[j], where i < j, such that A[i] ≤ A[j] and their sum is the largest. That is,A[i] + A[j] = Max {A[u] + A[v] | 1 ≤ u < v ≤.n, A[u] ≤ A[v]}.Please design a divide-and-conquer algorithm to solve the above problem. Please analyze the complexity of your algorithm. The complexity of your algorithm must be O(nlgn) or better.


我的解答:


事实上,所求解的可能情况有三种:
1. A[i]和A[j]分别在数组的左半边和右半边。在这种情况下,我们首先用O(n/2)的时间找到右半边的最大值A[j],然后再用O(n/2)的时间找到左半边比A[j]小的最大数A[i],然后返回A[i]+A[j]即可。
2. A[i],A[j]都在左半边。此时返回左半边的结果。
3. A[i],A[j]都在右半边。此时返回右半边的结果。
复杂度分析:
T(n)=2T(n/2)+n
根据主定理可以知道,复杂度为O(nlogn)


5 Design an O(n) greedy algorithm to solve problem 4.


我的解答:


事实上,如果(i,j)为所求解,那么A[i]一定是A[1:i]中最大的,否则,在A[1:i]的最大值设为A[v]那么解(v,j)为更优解,矛盾。
同样的,A[j]一定是A[j:n]中的最大的。
因此,我们采用双游标法,用O(n)的时间分别从右侧到左侧和从左侧到右侧找到最大值和次大值。

maxj = nfor (j = n - 1 down to 1):  if (a[j] > a[maxj]) then:    maxj = j  else:    check if (j, maxj) is a better solution

6 Given a sequence of n (n > 2) real numbers in a array, A[1], A[2], …, A[n], we wish to find two numbers A[i] and A[j], where i < j, such that A[i] ≤ A[j] and their distance is the largest. That is,j - i = max {v - u | 1 ≤ u < v ≤ n, A[u] ≤ A[v]}.If no such pair, report - ∞. Please design a O(nlgn) algorithm to solve this problem. You can use any method, including divide & conquer, greedy, or dynamic programming.


我的解答


事实上,对于所求解,(i,j),可以知道A[i]一定是A[1:i]中的最小的数,A[j]一定是A[j:n]中最大的数。
构造两个数组left和right,其中left[i]表示A[1:i]中的最小值,right[j]表示A[j:n]中的最大值。

def maxdist(A):    left=[]    right = []    left.append(A[0])    right.append(A[-1])    for i in range(1,len(A)):        left.append(min(A[i], left[-1]))    for i in range(0,len(A)-1,-1):        right.append(max(A[i],right[-1]))    right = right.reverse()    i = 0    j = len(A)-1    dist = -1    while j > 0 and i < len(A):        if left[i] < right[j]:            dist = max(dist , j-i)            j -= 1        else:            i += 1    return dist

7* A sequence of 2k numbers, a1, a2, …, a2k, have k different values with each value occurs exactly twice. Now, we wish to find the k pairs such that the two numbers in each pair have the same value. For example, a sequence of 6 numbers are a1 = 5, a2 = 7.5, a3 = 7.5, a4 = 10, a5 = 5, a6 = 10. Then the answer should be (a1, a5), (a2, a3), (a4, a6). Prove that, in the worst case, any algorithm needs at least (klgk) comparisons to find the k pairs. We assume there are 3 possible outcomes by comparing two numbers a and b, that is, a = b, a < b, and a > b.


我的解答


对于最坏的情况,我们可以采用排序算法先进行排序,排序算法的最小复杂度为O(klgk),排序后再遍历一遍需要O(k),总计O(klgk)。

原创粉丝点击