LintCode 130: Heapify (建堆经典题)

  1. Heapify

Given an integer array, heapify it into a min-heap array.

For a heap array A, A[0] is the root of heap, and for each A[i], A[i * 2 + 1] is the left child of A[i] and A[i * 2 + 2] is the right child of A[i].
Example
Example 1

Input : [3,2,1,4,5]
Output : [1,2,3,4,5]
Explanation : return any one of the legitimate heap arrays
Challenge
O(n) time complexity

Clarification
What is heap? What is heapify? What if there is a lot of solutions?

Heap is a data structure, which usually have three methods: push, pop and top. where “push” add a new element the heap, “pop” delete the minimum/maximum element in the heap, “top” return the minimum/maximum element.
Convert an unordered integer array into a heap array. If it is min-heap, for each element A[i], we will get A[i * 2 + 1] >= A[i] and A[i * 2 + 2] >= A[i].
Return any of them.

解法1:经典的O(n)解法。递归版。这个min_heapify()就类似于shiftdown()。
下面这个链接解释了为什么复杂度是O(n)。
https://www.zhihu.com/question/20729324

class Solution {
public:
    /*
     * @param A: Given an integer array
     * @return: nothing
     */
    void heapify(vector<int> &A) {
        int n = A.size();
        for (int i = (n - 2) / 2; i >= 0; --i)
            min_heapify(A, i, n);
    }
    
private:
    void min_heapify(vector<int> &A, int i, int len) {
        int left = 2 * i + 1;
        int right = 2 * i + 2;
        
        int smallest = i;
        if (left < len && A[left] < A[i]) smallest = left;
        if (right < len && A[right] < A[smallest]) smallest = right;
        
        if (smallest != i) {
            swap(A[i], A[smallest]);
            min_heapify(A, smallest, len);
        }
    }
};

解法2:迭代版

   // it the same as shiftDown()
    void min_heapify(vector<int> &A, int i, int len) {
        while(2 * i + 1 < len) {
            int left = 2 * i + 1;
            int right = 2 * i + 2;
            int smallest = i;
            if (left < len && A[left] < A[i]) smallest = left;
            if (right < len && A[right] < A[smallest]) smallest = right;
        
            if (smallest != i) {
                swap(A[i], A[smallest]);
                i = smallest;
            } else {
                break;
            }
        }
    }

二刷:

class Solution {
public:
    /**
     * @param a: Given an integer array
     * @return: nothing
     */
    void heapify(vector<int> &a) {
        int arraySize = a.size();
        for (int i = arraySize / 2; i >= 0; i--) {
            int smallest = i;
            while (smallest < arraySize) {
                int orig = smallest;
                int left = smallest * 2 + 1;
                int right = smallest * 2 + 2;
                if (left < arraySize && a[left] < a[smallest]) smallest = left;
                if (right < arraySize && a[right] < a[smallest]) smallest = right;
                if (smallest == orig) break;
                swap(a[smallest], a[orig]);
            }
        }
        return;
    }
};

解法3:新建一个堆(数组)。每次往新堆末尾塞一个元素,然后shiftup。
此法较慢,时间复杂度O(nlogn),而且空间复杂度O(n)。

class Solution {
public:
    /*
     * @param A: Given an integer array
     * @return: nothing
     */
    void heapify(vector<int> &A) {
        int n = A.size();
        vector<int> B(n + 1, 0);
        
        for (int i = 1; i <= n; ++i) {
            B[i] = A[i - 1];
            shiftup(B, i);
        }
        
        for (int i = 1; i <= n; ++i) {
            A[i - 1] = B[i];
        }
    }
    
private:
    void shiftup(vector<int> & nums, int pos) {
        while(pos > 1) {
            if (nums[pos / 2] > nums[pos]) {
                swap(nums[pos / 2], nums[pos]);
                pos /= 2;
            } else {
                break;
            }
        }
    }
 };

注意:同样的数组nums,但建堆方法不一样,则建的堆也不一样。
下面是借用一个大牛的图。
添加链接描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值