数据结构与算法 leetcode 刷题010

关于优先队列的数据结构:

优先队列的底层实现是堆;

下面介绍一下堆数据结构:堆数据结构是由数组构建的,最大堆:所有非叶子节点值都大于等于其左右孩子结点的值;

最小堆:所有非叶子节点值都小于等于左右孩子结点的值;

如何构建一个堆;伪代码如下(为了方便起见,数组的第一个元素的索引是1开始的)

1.首先得到相应的左结点和右结点的下标索引

PARENT(i)
  return i / 2
LEFT(i)
  return 2 * i
RIGHT(i)
  2 * i + 1

2.从第一个非叶子节点开始,构建堆;(注意是从第一个非叶子节点开始构建堆)

A.heap-size = A.length
for A.length / 2 downto 1
  MAX-HEAPIFY(A, i)

3.一下是递归的max_heapify(array,n)的伪代码:(非叶子节点和左右两个节点进行比较,选择大的数的索引,然后将大的数与起先的非叶子节点进行交换),交换后如果index!=largest_index ,还需要在交换后的结点进行维护

l = LIFT(i)
r = RIGHT(i)
if l <= A.heapsize and A[l] > A[i]
  largest = l
else largest = i
if r <= A.heapsize and A[r] > A[largest]
  largest = r
if largest != i
  exchage A[i] with A[largest]
  MAX-HEAPIFY(A, largest)

4,然后是堆排序算法:

伪代码是:交换相应的堆顶元素和数组尾部的元素,然后弹出数组最后一个元素,然后继续维护堆,max_heapify(array,n-1);


优先队列就是堆排序的一种应用;在c++中优先队列数据结构的使用,以及leetcode刷题如下:


leetcode347:

返回数组中前k个频率最大的数;

1.首先将数组进行遍历,然后通过map数据结构(hash)存储,然后对map中值进行排序,然后选择前k个数,时间复杂度为O(nlogn)主要的时间复杂度都是在排序算法上面;

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        //算法一实现:使用map数据结构来实现
        unordered_map<int,int> nums_map;
        for(int i=0;i<nums.size();i++){
            nums_map[nums[i]]++;//同时也可以还是通过insert函数添加pair类型的数据;
        }
        unordered_map<int,int>::iterator iter=nums_map.begin();
        vector<pair<int,int>> temp_nums;
        for(iter;iter!=nums_map.end();iter++){
            temp_nums.push_back(make_pair(iter->first,iter->second));
        }
        sort(temp_nums.begin(),temp_nums.end(),compare);
        vector<int> ans;
        //没有iter+i的用法,关联容器
        for(int i=0;i<k;i++){
            ans.push_back(temp_nums[i].first);
        }
        return ans;
    }
    static int compare(const pair<int,int>& pair1,const pair<int,int> &pair2){
        if(pair1.second<pair2.second){
            return false;
        }
        else{
            return true;
        }
    }
};
时间复杂度为O(nlog(n));


2.使用优先队列来维护一个最小堆来实现相应;


class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        
        unordered_map<int,int> nums_map;
        for(int i=0;i<nums.size();i++){
            nums_map[nums[i]]++;//同时也可以还是通过insert函数添加pair类型的数据;
        }
        //如何创建一个优先对垒priority_queue<int,vector<int>,greater<int>> 基本数据结构是int时,如果基本数据结构是pair<int,int>
        priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> min_queue;//构建了一个最小堆;
        unordered_map<int,int>::iterator iter=nums_map.begin();
        for(iter;iter!=nums_map.end();iter++){//对排序默认按照是键值进行排序
            if(min_queue.size()==k){//如果已经维护了一个k个数字的最小堆
                pair<int,int> temp=max_queue.top();//得到最大堆顶元素;
                if(iter->second>temp.first){
                    min_queue.pop();//弹出最后的元素,k个值中的较小频率值
                    min_queue.push(pair<int,int>(iter->second,iter->first));
                }
            }
            else{
                min_queue.push(pair<int,int>(iter->second,iter->first));
            }
        }
        vector<int> ans;
        while(!min_queue.empty()){
            ans.push_back(min_queue.top().second);
            min_queue.pop();
        }
        return ans;
    }
};

python 中也有相应的高级数据结构

from collections import defaultdict
import heapq
class Solution:
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        mydict=defaultdict(int)
        for num in nums:
            mydict[num]+=1
        mylist=mydict.items()
        ans_list=heapq.nlargest(k,mylist,key=lambda x:x[1])
        result=[]
        for item in ans_list:
            result.append(item[0])
        return result




猜你喜欢

转载自blog.csdn.net/hufanglei007/article/details/79545726