Leetcode:Question23--Merge k Sorted Lists

题目描述

题目描述

解题思路

这道题可以使用归并排序的思想进行操作,不同的是归并排序通过递归,在并的过程中采用的是两个list进行比较。题目要求的是对k个排列好的lists进行操作,因此思路就是每次比较队列头的元素,找出其中最小的,并将该元素写入新的lists内,并将它从所在的队列中pop出来。假如队列达到了末尾,则不进行比较。当所有队列都到达末尾时,停止比较。

这道题采用的是lists,因此pop就通过指针右移来实现即可

每次找出队列头的最小值所需要的复杂度是O(n),一个队列元素数量为k,所以复杂度为O(kn)

代码

C++

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        vector<ListNode*>trackP = lists;
        ListNode* temp = new ListNode(0);
        ListNode* result = temp;
        int NumOfList = trackP.size();
        while (NumOfList != 0) {
        	NumOfList = trackP.size();
        	int minIndex = 0;    	
	        for (int i = 0; i < trackP.size(); ++i) {
	        	if (trackP[i] != NULL) {
		        	if (trackP[i]->val < trackP[minIndex]->val) {
		        		minIndex = i;
		        	}        		
	        	}
	        	else {
	        		NumOfList--;
	        	}
	        }
		    if (NumOfList != 0) {
			    temp->next = new ListNode(trackP[minIndex]->val);
			    temp = temp->next;	        
	        	trackP[minIndex] = trackP[minIndex]->next;
	        }
        }
        return result->next;
    }

};

优化

那么,在每次寻找最小值的过程中,需要的复杂度是O(n)。这一步的复杂度可以进行优化
假如采用最小堆实现的优先队列,那么每一次只需要将头放进优先队列即可,而队列头的元素即为最小。
这样的话插入和删除优先队列需要的复杂度为O(logK),而取最小值的复杂度为0(1)。每一队列有N个元素,因此需要O(Nlogk)的复杂度

代码实现

c++ 实现最小堆优先队列
// A C++ program to demonstrate common Binary Heap Operations
#include<iostream>
#include<climits>
using namespace std;
 
// Prototype of a utility function to swap two integers
void swap(int *x, int *y);
 
// A class for Min Heap
class MinHeap
{
    int *harr; // pointer to array of elements in heap
    int capacity; // maximum possible size of min heap
    int heap_size; // Current number of elements in min heap
public:
    // Constructor
    MinHeap(int capacity);
 
    // to heapify a subtree with the root at given index
    void MinHeapify(int );
 
    int parent(int i) { return (i-1)/2; }
 
    // to get index of left child of node at index i
    int left(int i) { return (2*i + 1); }
 
    // to get index of right child of node at index i
    int right(int i) { return (2*i + 2); }
 
    // to extract the root which is the minimum element
    int extractMin();
 
    // Decreases key value of key at index i to new_val
    void decreaseKey(int i, int new_val);
 
    // Returns the minimum key (key at root) from min heap
    int getMin() { return harr[0]; }
 
    // Deletes a key stored at index i
    void deleteKey(int i);
 
    // Inserts a new key 'k'
    void insertKey(int k);
};
 
// Constructor: Builds a heap from a given array a[] of given size
MinHeap::MinHeap(int cap)
{
    heap_size = 0;
    capacity = cap;
    harr = new int[cap];
}
 
// Inserts a new key 'k'
void MinHeap::insertKey(int k)
{
    if (heap_size == capacity)
    {
        cout << "\nOverflow: Could not insertKey\n";
        return;
    }
 
    // First insert the new key at the end
    heap_size++;
    int i = heap_size - 1;
    harr[i] = k;
 
    // Fix the min heap property if it is violated
    while (i != 0 && harr[parent(i)] > harr[i])
    {
       swap(&harr[i], &harr[parent(i)]);
       i = parent(i);
    }
}
 
// Decreases value of key at index 'i' to new_val.  It is assumed that
// new_val is smaller than harr[i].
void MinHeap::decreaseKey(int i, int new_val)
{
    harr[i] = new_val;
    while (i != 0 && harr[parent(i)] > harr[i])
    {
       swap(&harr[i], &harr[parent(i)]);
       i = parent(i);
    }
}
 
// Method to remove minimum element (or root) from min heap
int MinHeap::extractMin()
{
    if (heap_size <= 0)
        return INT_MAX;
    if (heap_size == 1)
    {
        heap_size--;
        return harr[0];
    }
 
    // Store the minimum value, and remove it from heap
    int root = harr[0];
    harr[0] = harr[heap_size-1];
    heap_size--;
    MinHeapify(0);
 
    return root;
}
 
 
// This function deletes key at index i. It first reduced value to minus
// infinite, then calls extractMin()
void MinHeap::deleteKey(int i)
{
    decreaseKey(i, INT_MIN);
    extractMin();
}
 
// A recursive method to heapify a subtree with the root at given index
// This method assumes that the subtrees are already heapified
void MinHeap::MinHeapify(int i)
{
    int l = left(i);
    int r = right(i);
    int smallest = i;
    if (l < heap_size && harr[l] < harr[i])
        smallest = l;
    if (r < heap_size && harr[r] < harr[smallest])
        smallest = r;
    if (smallest != i)
    {
        swap(&harr[i], &harr[smallest]);
        MinHeapify(smallest);
    }
}
 
// A utility function to swap two elements
void swap(int *x, int *y)
{
    int temp = *x;
    *x = *y;
    *y = temp;
}

接下来只需要创建一个优先队列,把所有lists放入队列中,每次pop出第一个元素,将所有元素pop完成后即为排列好的队列

猜你喜欢

转载自blog.csdn.net/huangbx_tx/article/details/82828324