【算法学习笔记02】 渐进分析思想和基础问题

发布于:2022-10-12 ⋅ 阅读:(317) ⋅ 点赞:(0)

1 求最大值问题

给一个数组,求数组中的最大值

输入:A=[1,2,3,4,7,8,9]

输出:9

    1.1遍历求解   

        求解思路:最先就能够想到用遍历的方式去求解。遍历整个数组,找到最大值。

        时间复杂度分析:每次寻找都需要遍历整个数组,所以时间复杂度为O(N)

def get_max(A):
    num=len(A)
    max=A[0]
    for i in range(1,num):
        if A[i]>max:
            max=A[i]
    return max

2 寻找peak

给定数组,寻找到数组中的一个山峰值,山峰值的要求是必须同时大于他的前一位和后一位。

输入:A=[1,2,3,5,4,6,7]

输出:5

 2.1 遍历求解

        求解思路:最先就能够想到用遍历的方式去求解。遍历整个数组,找到peak。

        时间复杂度分析:最坏情况下需要遍历整个数组,所以时间复杂度为O(N)

def find_peak(A):
    num=len(A)
    peak=0
    for i in range(num):
        if A[num]<A[num-1] and A[num]>A[num+1]:
            peak=A[num]
            return peak

遍历虽然可以精准的找到数组中的peak,但是如果peak在数组的最后,那么将遍历完整个数组后才能找到。由于我们只需要返回一个peak,那有没有更简便能够定位到一个peak的方式呢,可以尝试以下二分法。

2.2 二分法求解

        求解思路:拿到数组后首先取数组中间值,判断是否是peak,是的话直接返回,不是的话则进行以下判断:

        if  A[medium]>A[medium-1] and A[medium]<A[medium+1]:  //呈现递增趋势

                在右半部分中寻找

        elif  A[medium]<A[medium-1] and A[medium]>A[medium+1]:  //呈现递减趋势

                在左半部分中寻找

        //因为在存在比中间点大的一部分,更有可能存在一个peak

        时间复杂度:由于使用的二分法,每一次寻找到中间值就会舍弃掉另一半数组,故时间复杂度为O(logN),由此可见使用二分法能够大大降低时间复杂度。同样在有序数组的查找中,室友二分法也可以大大降低时间复杂度。

def find_peak(A:list):
    num=len(A)
    medium=int((num-1)/2)
    if num==1:
        return A[0]
    elif num==2:
        return max(A)
    else:
        if A[medium]>A[medium+1] and A[medium]>A[medium-1]:
            return A[medium]
        elif A[medium]<A[medium+1] and A[medium]>A[medium-1]:
            return find_peak(A[medium+1:])
        elif A[medium]>A[medium+1] and A[medium]<A[medium-1]:
            return find_peak(A[:medium])

三、返回累加和为0的子集

题目:给定某整型数组,返回数组中累加和为0的所有子集数组

输入:A=[-7,-3,-2,5,8]

输出:[-3,-2,5]

        求解思路:

  • 最能够想到的就是求出给定数组的所有的子集,在判断子集是否累加和为0,是的话则记录。
  • 问题就变成了怎样才能求解一个数组的所有子集

技巧:穷举的办法

穷举[1,2,3]:[1],[2],[3],[1,2],[1,3],[2,3]

不难发现,当数组有n个元素是,穷举子集就有(2^n-1)个 ,我们可以将穷举与二进制联系起来。

3位二进制一共有 000,001,010,100,101,110,011,111 这其中排列方式,这正是与我们穷举是对应的,所以我们只需要将数组序列依次点积他对应二进制序列,就可以实现穷举。

 有了以上穷举技巧,我们不难实现:

def qiongju(A):
    n=len(A)
    res=[]
    for i in range(2**n):
        binary=str(bin(i))[2:].rjust(n-1,'0') # 转化为2进制,并补全左侧位数
        ziji=[]  #存放子集的数组
        for j in range(len(binary)):
            if binary[j]=='1':
                ziji.append(A[j])
        if sum(ziji)==0 and ziji!=[]:
            res.append(ziji)
    return res

当然穷举还有好多中方法,循环、递归都可以实现。


网站公告

今日签到

点亮在社区的每一天
去签到