130. 堆化

描述

给出一个整数数组,堆化操作就是把它变成一个最小堆数组。对于堆数组 A,A[0] 是堆的根,并对于每个 A[i],A [i * 2 + 1] 是 A[i] 的左儿子并且 A[i * 2 + 2] 是 A[i] 的右儿子。

说明

什么是堆?
堆是一种数据结构,它通常有三种方法:push, pop 和 top。其中,“push”添加新的元素进入堆,“pop”删除堆中最小/最大元素,“top”返回堆中最小/最大元素。

什么是堆化?
把一个无序整数数组变成一个堆数组。如果是最小堆,每个元素A[i],我们将得到 A[i * 2 + 1] >= A[i] 和 A[i * 2 + 2] >= A[i],如果有很多种堆化的结果?返回其中任何一个。

样例

给出 [3,2,1,4,5],返回 [1,2,3,4,5] 或者任何一个合法的堆数组

挑战

O(n) 的时间复杂度完成堆化

知识点

所谓堆化就是构造一个堆,堆化是堆排序的前提,堆排序就是建立一个初始堆,然后通过取出堆顶元素,再将剩下来的重新调整,最终可以得到一个有序的排序,不能对链表进行堆排序,因为链表不能像数组一样快速通过下标读取元素,堆中对结点的左儿子和右儿子之间谁大谁小没要求,只要左右儿子都同时大于或小于结点本身值就行

代码

方法区别

  1. 方法 1 和 2 都是从一颗二叉树的倒数第二层开始往上遍历,每次往下调顺序,倒数第二层最多要调 n/2 个点(最后一层只有最左边一个点),每次最多 O(1) 的操作,倒数第三层最多要调 n/4 个点,每次最多 O(2) 的操作......最顶层只有1个点,最多 O(logn) 次操作。时间复杂度为 n/2 * O(1) + n/4 * O(2) + ...... + O(log(n)) = O(n)
  2. 方法3的操作从上往下遍历每个结点,每次往上调,第一层1个结点 log1 的操作,第二层2个结点最多 log2 操作......最后一层 n/2 个结点最多 logn 的操作时间复杂度为 log 1 + 2 * log 2 + 3 * log 3......+ n/2 * log n
  1. 从倒数第二行最后一个元素开始往根结点扫描,对当前结点的子结点进行下面操作,跳过大于等于当前结点的儿子结点,如果子结点中较小的结点小于当前结点,交换当前结点和子结点中的较小结点,时间复杂度 O(n)
public class Solution {
    /**
     * @param A: Given an integer array
     * @return: void
     */
    private void siftdown(int[] A, int k) {
        while (k * 2 + 1 < A.length) {
            int son = k * 2 + 1;
            // 最小堆堆化,若左儿子大于右儿子,则根结点执行下沉操作同子结点交换值也轮不到左儿子,所以将结点切换到右儿子就可以了
            if (k * 2 + 2 < A.length && A[son] > A[k * 2 + 2]) {
                son = k * 2 + 2;
            }
            if (A[son] >= A[k]) {
                break;
            }

            int temp = A[son];
            A[son] = A[k];
            A[k] = temp;
            // 结点仍是原先的结点,堆的形态未变,但交换的 k 值变化成新的,对应结点下移
            // son 结点在 key 结点的下方
            k = son;
        }
    }
    
    public void heapify(int[] A) {
        for (int i = A.length / 2 - 1 ; i >= 0; i--) {
            siftdown(A, i);
        }
    }
}
  1. 和上种区别就在于多了个 A[smallest] 记录根结点,写法上的区别,时间复杂度 O(n)
public class Solution {
    /**
     * @param A: Given an integer array
     * @return: void
     */
    private void siftdown(int[] A, int k) {
        while (k < A.length) {
            int smallest = k;
            if (k * 2 + 1 < A.length && A[k * 2 + 1] < A[smallest]) {
                smallest = k * 2 + 1;
            }
            if (k * 2 + 2 < A.length && A[k * 2 + 2] < A[smallest]) {
                smallest = k * 2 + 2;
            }
            if (smallest == k) {
                break;
            }

            int temp = A[smallest];
            A[smallest] = A[k];
            A[k] = temp;
            
            k = smallest;
        }
    }
    
    public void heapify(int[] A) {
        for (int i = A.length / 2; i >= 0; i--) {
            siftdown(A, i);
        } // for
    }
}
  1. 從尾到頭掃一遍,如果遇到本身的值比 parent element 的值小的就一直跟 parent element 的值交換,直到交換到最頂層或是本身的值大於 parent element 的值
// O(nlogn)
public class Solution {
    /**
     * @param A: Given an integer array
     * @return: void
     */
    private void siftup(int[] A, int k) {
        while (k != 0) {
            int father = (k - 1) / 2;
            if (A[k] > A[father]) {
                break;
            }

            int temp = A[k];
            A[k] = A[father];
            A[father] = temp;
            
            k = father;
        }
    }
    
    public void heapify(int[] A) {
        for (int i = 0; i < A.length; i++) {
            siftup(A, i);
        }
    }
} 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350

推荐阅读更多精彩内容