Python-一个因浅复制和深复制引起的bug

来源:互联网 发布:知乎作死经历 编辑:程序博客网 时间:2024/06/05 08:21

Given a non-empty array of integers, return the k most frequent elements.

For example,Given [1,1,1,2,2,3] and k = 2, return [1,2].

Note: You may assume k is always valid, 1 ? k ? number of unique elements.Your algorithm’s time complexity must be better than O(n log n), where n is the array’s size.

思路

这是一个O(n)时间复杂度的算法,优于O(nlogn)
1. 求出每个数字的频次字典
2. 按照频次,装入桶中
3. 取前K个频次

Code

Python version

# -*- coding: utf-8 -*-# @Time    : 2017/7/14 15:44# @Author  : zhenguo# @Email   : guozhennianhua@163.com# @File    : topKFrequents.py# @Software: PyCharm Community Editionclass Solution(object):    def topKFrequent(self, nums, k):        """        :type nums: List[int]        :type k: int        :rtype: List[int]        """        frequency_map = {}        bucket = []        # get frequency dict for nums        # also init bucket used to get max k frequency        for n in nums:            if frequency_map.get(n) is not None:                frequency_map[n] += 1            else:                frequency_map[n] = 1            bucket.append([])        bucket.append([])        # frequency of each element for nums as index for sort bucket        # if both frequency for two different elements are equal to i,        # then they would append at rear of bucket[i](type list).        for item in frequency_map:            frequency = frequency_map[item]            bucket[frequency].append(item)        # iterator bucket as descending        # if length of bucket[pos] is bigger zero, it indicates at least element whose frequency equals to pos exist        # and if length of res(type: list) is less k, then all elements in this bucket would append at res(type: list)        res = []        pos = len(bucket) - 1        while pos >= 0 and len(res) < k:            if len(bucket[pos]) > 0:                for item in bucket[pos]:                    res.append(item)            pos -= 1        return res

然后发现桶的初始化不精简,作如下转化

 def topKFrequent2(self, nums, k):        """        :type nums: List[int]        :type k: int        :rtype: List[int]        """        frequency_map = {}        # get frequency dict for nums        # also init bucket used to get max k frequency        for n in nums:            if frequency_map.get(n) is not None:                frequency_map[n] += 1            else:                frequency_map[n] = 1        # frequency of each element for nums as bucket index,        # if both frequency for two different elements are equal to i,        # then they would append at rear of bucket[i](type list).        ###################################        # this is the only difference to method 1        # but it fails to get the right solution and one point is puzzling for me.        # By debug I found it would append an item at every element of bucket,        # and it's so puzzling!        bucket = [[]]*len(nums)        ##################################        for item in frequency_map:            frequency = frequency_map[item]            bucket[frequency].append(item)        # iterator bucket as descending        # if length of bucket[pos] is bigger zero, it indicates at least element whose frequency equals to pos exist,        # and if length of res(type: list) is less k, then all elements in this bucket would append at res(type: list).        res = []        pos = len(bucket) - 1        while pos >= 0 and len(res) < k:            if len(bucket[pos]) > 0:                for item in bucket[pos]:                    res.append(item)            pos -= 1        return res

浅复制导致的bug,因此改为深复制,

    def topKFrequent3(self, nums, k):        """        :type nums: List[int]        :type k: int        :rtype: List[int]        """        frequency_map = {}        # get frequency dict for nums        # also init bucket used to get max k frequency        for n in nums:            if frequency_map.get(n) is not None:                frequency_map[n] += 1            else:                frequency_map[n] = 1        # frequency of each element for nums as bucket index,        # if both frequency for two different elements are equal to i,        # then they would append at rear of bucket[i](type list).        ###################################        # The real reason for the question of topKFrequent2 method is shallow copy,        # so make a fix to deep copy        bucket = [[] for i in range(len(nums))]        ##################################        for item in frequency_map:            frequency = frequency_map[item]            bucket[frequency].append(item)        # iterator bucket as descending        # if length of bucket[pos] is bigger zero, it indicates at least element whose frequency equals to pos exist,        # and if length of res(type: list) is less k, then all elements in this bucket would append at res(type: list).        res = []        pos = len(bucket) - 1        while pos >= 0 and len(res) < k:            if len(bucket[pos]) > 0:                for item in bucket[pos]:                    res.append(item)            pos -= 1        return res
原创粉丝点击