Leecode位运算与堆排序

Posted 小虾米的数据分析

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leecode位运算与堆排序相关的知识,希望对你有一定的参考价值。

位运算

常见的位操作包括:

与 &

或  |

非  |

异或 ^

左移 <<

右移 >>




Leecode 136

这一题本质上就是考位运算的,对于异或操作来说,有:
a ^ a = 0
a ^ 0 = a
a ^ b ^ a = a ^ a ^ b = b
然后这题就解决了。


如下图所示:

Leecode位运算与堆排序

时间复杂度是O(n),所有num中元素遍历一遍。

空间复杂度是O(1)。

Leecode位运算与堆排序


Leecode 260


Leecode位运算与堆排序

如果仍然用上面位运算的方法,最终得到的是3和5异或的结果。用二进制表示就是:

                      0 0 1 1

                      0 1 0 1

得到的结果是  0 1 1 0

取出来第一位上为1的,表示这两个数在这一位上不同,根据这一位来进行分类后再异或求解。


具体做法如下:

Leecode位运算与堆排序Leecode位运算与堆排序

时间复杂度是O(n)。空间复杂度是O(1)


堆排序

堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。


堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。


Leecode位运算与堆排序

堆不需要用树来存储,可以直接用数组来存,根据完全二叉树的性质,在这个数组中对于当前节点i来说:
左节点为:2i+1
右节点为:2i+2
那么大顶堆有:
arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]  
小顶堆有:
arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]  


堆排序

堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。

所以为什么大顶堆是升序,而小顶堆是降序,因为大顶堆每次将最大的放到数组末尾,小顶堆也是一样!


举例说明:

题目:初始序列为1 8 6 2 5 4 7 3的一组数采用堆排序,当建堆(小根堆)完毕时,堆所对应的二叉树中序遍历序列为:( )(英特尔2016软件类研发在线测评)

A、8 3 2 5 1 6 4 7

B、3 2 8 5 1 4 6 7

C、3 8 2 5 1 6 7 4

D、8 2 3 5 1 4 7 6

 

Leecode位运算与堆排序


Leecode215. 数组中的第k个最大元


Leecode位运算与堆排序


对于本题来说,我们并不是进行排序,我们是寻找第k大的,所以并不需要排序完,我们进行了k次,就能够找到第K大的元素,所以我们只进行K次。

 

构建大顶堆

Leecode位运算与堆排序

Python3 完整代码


--------------------------------------------------------------------------

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        return self.heap_sort(nums, k)
   
    def heap_sort(self, nums, k):
        for i in range(len(nums)//2-1, -1, -1):
            self.heap_adjust(nums, i, len(nums))   
        cnt = 0
        for i in range(len(nums)-1, 0, -1):
            self.heap_swap(nums, 0, i)
            cnt+=1
            if cnt == k:
                return nums[i]
            self.heap_adjust(nums, 0, i)
        return nums[0]
   
    def heap_adjust(self, nums, start, length):
        tmp = nums[start]
        k = start*2+1
        while k<length:
            left  = start*2+1
            right = left+1
           
            if right<length and nums[left]<nums[right]:
                k = right
            if nums[k]>tmp:
                nums[start] = nums[k]
                start = k
            else:
                break
            k = k*2+1
        nums[start]=tmp
       
    def heap_swap(self, nums, i, j):
        nums[i],nums[j] = nums[j],nums[i]
        return nums
   
  -------------------------------------------------------------
   

时间复杂度-O(NlogK),空间复杂度-O(K)。

以上是关于Leecode位运算与堆排序的主要内容,如果未能解决你的问题,请参考以下文章

树二叉树与堆

Leecode题解汇总(持续更新)

leecode 278 数值溢出感想

leecode-268. 丢失的数字(异或的应用,找没有出现的数字,找只出现一次的数字)

leecode-268. 丢失的数字(异或的应用,找没有出现的数字,找只出现一次的数字)

leecode-268. 丢失的数字(异或的应用,找没有出现的数字,找只出现一次的数字)