算法面試:10億個數中取TOP-1000個數

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/4/4 22:39
# @Author  : zhoujianwen
# @Email   : [email protected]
# @File    : topn.py
# @Describe: 

"""
    算法面試:10億個數中取TOP-1000個數
    堆的性質:每一個節點比它的左右子節點小,
    先取前N個數,構成小頂堆,即在內存中維護一個1000數的小頂堆
    然後對文件中讀取數據,和堆頂比較:
    if 比堆頂小,則丟棄
    if 比堆頂大,替換根節點,並且調整堆,保持小頂堆的性質
    所有數據處理完,得到的即是Top-N
"""


class TopN:
    # 父節點下標
    def parent(self, n):
        return int((n - 1) / 2)

    # 左節點下標
    def left(self, n):
        return 2 * n + 1

    # 右節點下標
    def right(self, n):
        return 2 * n + 2

    # 構建小頂堆,保證父節點小於左右子節點
    def buildHeap(self, n, data):
        for i in range(1, n):
            t = i
            # 調整堆,如果節點比父親節點小,則交換
            while t != 0 and data[t] < data[self.parent(t)]:
                temp = data[t]
                data[t] = data[self.parent(t)]
                data[self.parent(t)] = temp
                t = self.parent(t)

    # 調整data[i]
    def adjust(self, i, n, data):
        # 小於堆的根節點,不調整
        if data[i] <= data[0]:
            return

        # 置換堆頂
        temp = data[i]
        data[i] = data[0]
        data[0] = temp
        # 調整堆頂
        t = 0
        while (self.left(t) < n and data[self.left(t)] < data[t]) or (
                self.right(t) < n and data[self.right(t)] < data[t]):
            if self.right(t) < n and data[self.right(t)] < data[self.left(t)]:
                # 右孩子更小,置換右孩子
                temp = data[t]
                data[t] = data[self.right(t)]
                data[self.right(t)] = temp
                t = self.right(t)
            else:
                # 否則置換左孩子
                temp = data[t]
                data[t] = data[self.left(t)]
                data[self.left(t)] = temp
                t = self.left(t)

    # 尋找topN,調整data,將topN排到最前面
    def findTopN(self, n, data):
        # 先構建n個數的小頂堆
        self.buildHeap(n, data);
        # n往後的數進行調整
        for i in range(n, len(data)):
            self.adjust(i, n, data)
        return data


# 第一組測試 12個
arr1 = [58, 26, 45, 18, 22, 39, 96, 75, 80, 65, 63, 28]
print("原數組:" + str(arr1))
topn = TopN()
result = topn.findTopN(5, arr1)
print("數組進行Top-N調整:" + str(result))

# 第二組測試 隨機20個
import random

N = 10  # 從數組中取TOP-N數據排序
tempList = []
for i in range(20):  # 篇幅有限,只生成20個數據,讀者可自行修改爲1000
    temp = random.randint(0, 1000)
    tempList.append(temp)
print("原數組:" + str(tempList))
topn = TopN()
result = topn.findTopN(N, tempList)

temp = result[:N]
temp.sort(key=None, reverse=True)
print("數組進行Top-{0}調整:{1}".format(N,temp))  # 只顯示前10個數據,後面數據省略顯示

tempList.sort(key=None, reverse=True)
print("數組進行Top-{0}排序:{1}".format(N,tempList[:N]))  # 只顯示前10個數據,後面數據省略顯示
原數組:[58, 26, 45, 18, 22, 39, 96, 75, 80, 65, 63, 28]
數組進行Top-N調整:[63, 65, 80, 75, 96, 18, 22, 26, 39, 45, 58, 28]
原數組:[676, 931, 685, 823, 889, 428, 681, 445, 497, 940, 113, 102, 299, 224, 811, 157, 889, 41, 959, 250]
數組進行Top-10調整:[959, 940, 931, 889, 889, 823, 811, 685, 681, 676]
數組進行Top-10排序:[959, 940, 931, 889, 889, 823, 811, 685, 681, 676]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章