搜索和排序算法部分:

(一)数字在升序数组中出现的次数

主要考察二分查找,建议背诵。唯一的区别在二分查找条件这一行代码。 

    def GetNumberOfK(self , data: List[int], k: int) -> int:
        # write code here
        return self.upper_bound(k, data)-self.lower_bound(k, data)
    def lower_bound(self, k, data):
        left = 0
        right = len(data)
        while left <right:
            mid = int((left +right)/2)
            # 二分查找的目标位置:第一个大于等于k的数
            if data[mid]>=k:
                right = mid
            else:
                left = mid+1
        return right
    def upper_bound(self, k, data):
        left = 0
        right = len(data)
        while left <right:
            mid = int((left+right)/2)
            # 二分查找的目标位置:第一个大于k的数
            if data[mid] > k:
                right = mid 
            else:
                left = mid +1
        return right

 (二)旋转数组的最小数字

极端例子:[1,0,1,1,1] 和 [1,1,1,0,1]

只要能够建立mid与left,right的关系,二分查找也适用,不仅仅是顺序数组。

这里最大的疑虑还是出现在mid的数值如果与端点相同,如何处理?可以选择right-1的方式,逐步缩小区间,不会漏掉结果。

    def minNumberInRotateArray(self , rotateArray: List[int]) -> int:
        # write code here
        left=0
        right=len(rotateArray)-1
        while right>left:
            mid=(right+left)//2
            if rotateArray[mid]<rotateArray[right]:
                right=mid
            elif rotateArray[mid]>rotateArray[right]:
                left=mid+1
            else:
                right-=1
        return rotateArray[right]

(三)字符串的全排列

递归的解法:空间复杂度 O(n!),时间复杂度 O(n!)

    def Permutation(self , str: str) -> List[str]:
        # write code here
        if len(str)<=1:
            return str
        res = []
        self.helper(str,'',res)
        return res
    def helper(self,array,solution,res):
        if len(array)==0:
            if solution not in res:
                res.append(solution)
            return
        for i in range (len(array)):
            newarray=array[:i]+array[i+1:]#删除第一个元素
            newsolution=solution+array[i]#加入新元素
            self.helper(newarray,newsolution,res)#寻找剩余元素的排列组合

常用的排序算法,有冒泡排序o(n2),选择排序o(n2),插入排序o(n2),归并排序o(nlogn),希尔排序o(nlogn),快速排序o(nlogn)

冒泡排序:

def bubble_sort(alist):
    length = len(alist)
    for i in range(length - 1):
        # i表示比较多少轮
        for j in range(length - i - 1):
            # j表示每轮比较的元素的范围,因为每比较一轮就会排序好一个元素的位置,
            # 所以在下一轮比较的时候就少比较了一个元素,所以要减去i
            if alist[j] > alist[j + 1]:
                alist[j], alist[j + 1] = alist[j + 1], alist[j]

选择排序: 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置。

插入排序:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

归并排序:归并排序中递归地将待排序列表进行拆分,直到拆分成只有一个元素的列表,然后调用merge(left_array, right_array)函数进行合并,这样依次递归合并,最终实现归并排序。

def merge_sort(array):
    if len(array) == 1:
        return array
    left_array = merge_sort(array[:len(array)//2])
    right_array = merge_sort(array[len(array)//2:])
    return merge(left_array, right_array)
 
 
def merge(left_array, right_array):
    left_index, right_index, merge_array = 0, 0, list()
    while left_index < len(left_array) and right_index < len(right_array):
        if left_array[left_index] <= right_array[right_index]:
            merge_array.append(left_array[left_index])
            left_index += 1
        else:
            merge_array.append(right_array[right_index])
            right_index += 1
    merge_array = merge_array + left_array[left_index:] + right_array[right_index:]
    return merge_array

希尔排序(缩小增量排序):固定间隔的几个元素之间排序,然后再缩小这个间隔,直至为1,就成了有序数列。计算复杂度为o(logn~o(n2))

def shell_sort(arr):
    gap = len(arr) // 2
    while gap > 0:
        for i in range(gap, len(arr)):
            j = i
            current = arr[i]
            while j - gap >= 0 and current < arr[j - gap]:
                arr[j] = arr[j - gap]
                j -= gap
            arr[j] = current
        gap //= 2
    return arr

快速排序:给基准数据找其正确索引位置的过程。

def quick_sort(alist, start, end):
    """快速排序"""
    if start >= end:  # 递归的退出条件
        return
    mid = alist[start]  # 设定起始的基准元素
    low = start  # low为序列左边在开始位置的由左向右移动的游标
    high = end  # high为序列右边末尾位置的由右向左移动的游标
    while low < high:
        # 如果low与high未重合,high(右边)指向的元素大于等于基准元素,则high向左移动
        while low < high and alist[high] >= mid:
            high -= 1
        alist[low] = alist[high]  # 走到此位置时high指向一个比基准元素小的元素,将high指向的元素放到low的位置上,此时high指向的位置空着,接下来移动low找到符合条件的元素放在此处
        # 如果low与high未重合,low指向的元素比基准元素小,则low向右移动
        while low < high and alist[low] < mid:
            low += 1
        alist[high] = alist[low]  # 此时low指向一个比基准元素大的元素,将low指向的元素放到high空着的位置上,此时low指向的位置空着,之后进行下一次循环,将high找到符合条件的元素填到此处

    # 退出循环后,low与high重合,此时所指位置为基准元素的正确位置,左边的元素都比基准元素小,右边的元素都比基准元素大
    alist[low] = mid  # 将基准元素放到该位置,
    # 对基准元素左边的子序列进行快速排序
    quick_sort(alist, start, low - 1)  # start :0  low -1 原基准元素靠左边一位
    # 对基准元素右边的子序列进行快速排序
    quick_sort(alist, low + 1, end)  # low+1 : 原基准元素靠右一位  end: 最后

堆排序:是一种选择排序算法,最好和最坏的计算复杂度都是logn,不稳定。核心步骤是大根堆调整,将堆的末端子节点作调整,使得子节点永远小于父节点。

def build_max_heap(heap):  # 构造一个堆,将堆中所有数据重新排序
    heapSize = len(heap)
    for i in range((heapSize-2)//2,-1,-1):  # 自底向上建堆
        max_heapify(heap, heapSize, i)

def max_heapify(heap,heapSize,root):  # 调整列表中的元素并保证以root为根的堆是一个大根堆
    """
    给定某个节点的下标root,这个节点的父节点、左子节点、右子节点的下标都可以被计算出来。
    父节点:(root-1)//2
    左子节点:2*root + 1
    右子节点:2*root + 2  即:左子节点 + 1
    """
    left = 2*root + 1
    right = 2*root + 2
    larger = root
    # 小根堆只需要把下面and后面的条件改成:heap[larger] < heap[left] 和 heap[larger] < heap[right]
    # 当然,为了能见名知义,可以把larger换成smaller
    if left < heapSize and heap[larger] < heap[left]:
        larger = left
    if right < heapSize and heap[larger] < heap[right]:
        larger = right
    if larger != root:  # 如果做了堆调整则larger的值等于左节点或者右节点的值,这个时候做堆调整操作,交换此时的最大值到root节点
        heap[larger], heap[root] = heap[root], heap[larger]
        # 递归的对子树做调整
        max_heapify(heap, heapSize, larger)

def heap_sort(heap):  # 将根节点取出与最后一位做对调,对前面len-1个节点继续进行堆调整过程。
    build_max_heap(heap)
    # 调整后列表的第一个元素就是这个列表中最大的元素,将其与最后一个元素交换,然后将剩余的列表再递归的调整为最大堆
    for i in range(len(heap)-1, -1, -1):
        heap[0], heap[i] = heap[i], heap[0]
        max_heapify(heap, i, 0)

(四)数组中的逆序对

 分治的解法

    def InversePairs(self , data: List[int]) -> int:
        # write code here
        return self.recur(data)%1000000007
    def recur(self,arr):
        if len(arr) <= 1: 
            return 0
        b,s = [],[]
        res,pre=0,arr[0]
        for n in arr[1:]:
            if n > pre:
                b.append(n)
            else:
                s.append(n)
                res += len(b) + 1
        return res + self.recur(b) + self.recur(s)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值