《剑指offer》10&18、旋转数组的最小值&重排数组

数组

数组(Array)是有序的元素序列,组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按有序的形式组织起来的一种形式。可以说,数组是最常见的数据结构了,也是出题时能玩出花来的一种类型。它和数学,排序息息相关,实际上我们在offer01-03中已经数次见到它们了。
《剑指offer》01&02、数组中的重复数
《剑指offer》03、二维数组的检索
而offer10和18也是和数组、排序相关的。

旋转数组的最小值

offer10的要求是,给定一个非严格递增数组的一个旋转,求这个数组的最小元素。

num = [int(n) for n in input().split()]

所谓旋转,比如数组
[1,2,3,4,5,6],它的一个旋转就是[3,4,5,6,1,2];简单地理解,就是将前n个元素整段抽出来拼在数组的后面。非严格递增的情况下,比如[0,0,1,1,1,1,2],它的一个旋转是[1,1,1,2,0,0,1],另一个旋转是[1,2,0,0,1,1,1]。这个概念还是好理解的。
首先,非常好理解的方式就是一次遍历,时间复杂度O(n)

# offer10-solution 1
def MinNUMinRotatedArray01(num):
    start = num[0]
    for i in range(1, len(num), 1):
        if num[i] < start:
            print(num[i])
            return
    print(start)
    return

MinNUMinRotatedArray01(num)

以及,很容易想到的二分查找法。
二分查找需要设置一个头指针,尾指针和中间指针,通过中间指针的摇摆,判断最小值在数组的哪一部分,从而达到缩小搜索范围的目的。需要注意的是:当旋转数组的两端点的值都与中间点的值相等时,无法判断最小值在哪一部分,这时候还是需要采用顺序查找。

# offer10-solution 2
def MinNUMinRotatedArray02(num):
    length = len(num)
    start, mid, end = 0, 0, length-1
    while True:
        # 如果出现头指针,中指针,尾指针对应的值相同,就无法二分查找,要遍历
        if (num[start] == num[mid]) and (num[mid] == num[end]):
            # 偷懒直接应用之前的题解
            MinNUMinRotatedArray01(num)
            return
        if end - start == 1:  # 二分查找到头指针和尾指针相邻时结束
            mid = end
            break
        # 改写中间指针
        mid = int((start + end) / 2)
        if num[start] <= num[mid]:
            start = mid
        elif num[end] >= num[mid]:
            end = mid
    print(num[mid])
    return

MinNUMinRotatedArray02(num)

关于二分查找,文末有个blog我个人感觉是不错的。

重排数组

offer18的要求是,给出一个数组 [ x 1 , x 2 , … x n , y 1 , y 2 , … y n ] {\left[x_{1}, x_{2}, \ldots x_{n}, y_{1}, y_{2}, \ldots y_{n}\right]} [x1,x2,xn,y1,y2,yn],要求将其重新排列成 [ x 1 , y 1 , x 2 , y 2 , … x n , y n ] {\left[x_{1}, y_{1}, x_{2}, y_{2}, \ldots x_{n}, y_{n}\right]} [x1,y1,x2,y2,xn,yn]

num = [int(n) for n in input().split()]

很容易想到利用append的一次遍历,时间和空间复杂度都是O(n),我一开始还想复杂了……

# offer18-solution
def reOrderArray(num):
    n = int(len(num) / 2)
    res = []
    for i in range(0, n, 1):
        res.append(num[i])
        res.append(num[i+n])
    print(res)
    return

reOrderArray(num)

参考

二分查找-百度百科
详解二分查找算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值