Google python course basic exercise——list2

list2里面含两个练习,方法多彩多样。

D题实现对list内数据去重操作,E题实现对已排序list实现归并排序,并且要求线性时间复杂度。

题目和代码如下:

 1 # D. Given a list of numbers, return a list where
 2 # all adjacent == elements have been reduced to a single element,
 3 # so [1, 2, 2, 3] returns [1, 2, 3]. You may create a new list or
 4 # modify the passed in list.
 5 def remove_adjacent(nums):
 6     for i in range(len(nums)): #注意边界条件
 7         for j in range(len(nums)-1,i,-1):#逆序遍历,当进行删除操作时不会影响待比较元素的序号
 8             if nums[i] == nums[j]:
 9                 nums.remove(nums[j])
10     return nums
11 
12 # E. Given two lists sorted in increasing order, create and return a merged
13 # list of all the elements in sorted order. You may modify the passed in lists.
14 # Ideally, the solution should work in "linear" time, making a single
15 # pass of both lists.
16 def linear_merge(list1, list2):
17     list3=[]
18     while list1 and list2:    
19         if list1[-1]>list2[-1]:
20             list3.append(list1.pop())  #pop()默认弹出list最末尾数据操作,时间O(1)
21         else:
22             list3.append(list2.pop())
23     list3 += (list1+list2)[::-1]
24     list3.reverse()  #reverse()built-in类型,时间复杂度为O(N)
25     return list3
26         
27 # Simple provided test() function used in main() to print
28 # what each function returns vs. what it's supposed to return.
29 def test(got, expected):
30     if got == expected:
31         prefix = ' OK '
32     else:
33         prefix = '  X '
34     print '%s got: %s expected: %s' % (prefix, repr(got), repr(expected))
35 
36 
37 # Calls the above functions with interesting inputs.
38 def main():
39     print 'remove_adjacent'
40     test(remove_adjacent([1, 2, 2, 2, 3]), [1, 2, 3])
41     test(remove_adjacent([2, 2, 3, 3, 3]), [2, 3])
42     test(remove_adjacent([]), [])
43 
44     print
45     print 'linear_merge'
46     test(linear_merge(['aa', 'xx', 'zz'], ['bb', 'cc']),
47          ['aa', 'bb', 'cc', 'xx', 'zz'])
48     test(linear_merge(['aa', 'xx'], ['bb', 'cc', 'zz']),
49          ['aa', 'bb', 'cc', 'xx', 'zz'])
50     test(linear_merge(['aa', 'aa'], ['aa', 'bb', 'bb']),
51          ['aa', 'aa', 'aa', 'bb', 'bb'])
52 
53 if __name__ == '__main__':
54   main()

运行结果:

remove_adjacent
 OK  got: [1, 2, 3] expected: [1, 2, 3]
 OK  got: [2, 3] expected: [2, 3]
 OK  got: [] expected: []

linear_merge
 OK  got: ['aa', 'bb', 'cc', 'xx', 'zz'] expected: ['aa', 'bb', 'cc', 'xx', 'zz']
 OK  got: ['aa', 'bb', 'cc', 'xx', 'zz'] expected: ['aa', 'bb', 'cc', 'xx', 'zz']
 OK  got: ['aa', 'aa', 'aa', 'bb', 'bb'] expected: ['aa', 'aa', 'aa', 'bb', 'bb']

 

ps:

  1. 关于D题,我借鉴了冒泡排序的思想,利用两轮循环,外层循环负责正序遍历,里层循环负责逆序遍历,判断是否有重复的,有则删除。里层循环一轮结束后,则会删除一个数字的副本。这里强调一下,里层循环必须是逆序的,否则当进行remove()操作时,会改变继续判断时后面元素在list里的index,得不到想要的结果。举例说明:在第一个test case中,nums[1] ==nums[2] 成立,则删除nums[2],nums=[1,2,2,3],搜索nums[3]时得到的是'3',不是第二个'2',显然错误。
  2. 关于D题,还有个更简单的方法:
    1     def remove_adjacent(nums):
    2       result = []
    3       for num in nums:
    4         if len(result) == 0 or num != result[-1]:
    5           result.append(num)
    6       return result

    其思想为对原list复制时去重,妙在num!=result[-1]这句。

  3. E题最自然的想法是:
    1 def linear_merge(list1, list2):
    2   list1.extend(list2) 
    3   return sorted(list1)

    但是,因为python2.3以后的版本使用的是adaptive mergesort algorithm,其时间复杂度为O(nlogn),不合题意。

  4.  

    因为list1和list2是已排序序列,要对他们重新归并排序成list3,想到list3中最大的必是list1和list2两者中最大的,故可用pop[-1]来解决。这然后再reverse()一下,即可。list.pop()的时间复杂度为O(1),list.reverse()的时间复杂度为O(N)。故整个算法的时间复杂度是线性的。
  5. 为什么不直接用pop(0)呢?因为根据资料显示,pop(0)时间复杂度非constant time(为O(N)),综合考虑用上面方法。
  6. 答案是丰富多彩的,所以E题还可以这样解:
     1 def linear_merge(list1,list2 ):
     2     list3 = []
     3     i = j = 0
     4     total = len(list1) + len(list2)
     5     while len(list3) != total:
     6         if len(list1) == i:
     7             list3 += list2[j:]
     8             break
     9         elif len(list2) == j:
    10             list3 += list1[i:]
    11             break
    12         elif list1[i] < list2[j]:
    13             list3.append(list1[i])
    14             i += 1
    15         else:
    16             list3.append(list2[j])
    17             j += 1
    18     return list3

     

 

 

 

posted @ 2013-04-01 18:41  Emma437211  阅读(297)  评论(0编辑  收藏  举报