直通BAT面试算法精讲--排序(3)

注:
所有的代码都是用python实现的,都是自己写的,可能有些地方不太完善

案例一

小范围排序练习题
已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离不超过k,并且k相对于数组长度来说很小。请问选择什么方法对其排序比较好

解题思路:
移动不超过k,说明最小值位于0~k-1中,将0~k-1组成个最小堆。弹出堆顶元素,将位置k上的数放置堆顶,再次调整小根堆。递归实现。实际上采取的是改进后的堆排序的算法,时间复杂度为O(nlogk)

import copy
def sort(arr,n,k):
    if n ==0 or n<k:
        return arr
    heap = copy.copy(arr[:k])

    #建立k个元素的小根堆
    for i in range(k//2-1,-1,-1):
        fixDown(heap,0,k)

    #取出堆顶,赋值给arr的第一个元素
    #然后从后面的从k到n的元素置换堆顶
    for i in range(k,n):
        arr[i-k] = heap[0]
        heap[0] = arr[i]
        fixDown(heap,0,k)

    #逐步建堆排序结束后,最后还有从n-1-k+1到n-1的k-1个元素的完整堆
    #用普通堆排序思想输出
    #堆顶与最后一个元素交换
    for i in range(n-k,n):
        arr[i] = heap[0]
        heap[0],heap[k-1] = heap[k-1],heap[0]
        k -= 1
        fixDown(heap,0,k)
    return arr

def fixDown(heap,i,k):
    for j in range(2*i+1,k,2*i+1):
        if j+1<k and heap[j]>heap[j+1]:
            j += 1
        if heap[i]<heap[j]:
            break
        else:
            heap[i],heap[j] = heap[j],heap[i]
            i = j

案例二

重复值判断练习题
判断数组中是否有重复值, 请设计一个高效算法,判断数组中是否有重复值,必须保证额外空间复杂度为O(1)。给定一个int数组A及它的大小n,请返回它是否有重复值。

解题思路:
先进行排序,再比较相邻元素。选择时间复杂度为O(nlogn)的堆排序
存在返回True,不存在返回False

def sort(arr,n):
    if n == 0:
        return False
    for i in range(n//2-1,-1,-1):
        fixDown(arr,i,n)
    for i in range(n-1,-1,-1):
        arr[0],arr[i] = arr[i],arr[0]
        fixDown(arr,0,i)
    for i in range(0,n):
        if arr[i-1] == arr[i]:
            return True
    return False

def fixDown(arr,i,n):
    while 2*i+1 < n:
        j = 2*i+1
        if j+1<n and arr[j]<arr[j+1]:
            j += 1
        if arr[i]>arr[j]:
            break
        else:
            arr[i],arr[j] = arr[j],arr[i]
            i = j

案例三

有序数组合并练习题
把两个有序数组合并为一个数组。第一个数组空间正好可以容纳两个数组的元素。
A:2 4 6 空 空 空
B:1 3 5
输出:A: 1 2 3 4 5 6
该题核心:从后向前覆盖数组A,保证数组A有用信息不会被覆盖掉

解题思路:
(1)将第二个数组中的元素依次append进第一个数组,然后再采取一种排序方式,这个就非常简单了
(2另一种就是左成云在视频中说的,如果A有多余的空间,这个在c++中可以用arr.push_back()将数组长度扩充,但是在python里面没有想到这样的方法。自己采用的方法是重新建立一个列表,将两个列表放置在一个列表中。虽然感觉有点不符合题意了,但是目前没有想到别的办法,如果后期想到了再改

def sort(arr1,arr2):
    arr = []
    while arr1 and arr2:
        if arr1[0] <= arr2[0]:
            arr.append(arr1.pop(0))
        else:
            arr.append(arr2.pop(0))
            arr2.remove(arr2[0])
    arr.extend(arr1)
    arr.extend(arr2)
    return arr

猜你喜欢

转载自blog.csdn.net/yato0514/article/details/81045034
今日推荐