我爱编程Python学习

求数组有序后相邻元素的最大差值,时间复杂度:O(n)

2018-06-17  本文已影响1人  牵丝笼海

问题描述:
给定一个数组,求有序后相邻两个数的最大差值,要求时间复杂度为O(n)
并且不能用非基于比较的排序算法

解决思路
我们使用桶排序的思想,但是不对数组进行排序操作
因为我们只需要获取当前数组元素所在桶的序号,并不是真实地将元素插入某个桶中

下面只是模拟的过程:

  1. 数组 a 中有 n 个元素,则准备 n+1 个桶,将数组的最小值放入 0 号桶,最大值放入 n 号桶
  2. 将数组剩余的 n-2 个元素按顺序均匀放入剩余的 n-1 个桶中(每个桶中的元素是有序的),则必有一个空桶,
    因此要求的最大差值一定不会来自同一个桶的相邻元素之差
  3. 最大差值一定是相邻两个桶的后一个桶中最小值与前一个桶中最大值之差,相邻两个桶中间可能会有空桶

max_differ_sorted.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2018-06-16 23:09:23

"""
给定一个数组,求排序之后相邻两个数的最大差值,要求时间复杂度为O(n)
并且不能用非基于比较的排序算法

解决思路
我们使用桶排序的思想,但是不对数组进行排序操作
因为我们只需要获取当前数组元素所在桶的序号,并不是真实地将元素插入某个桶中
下面只是模拟的过程:
1.数组 a 中有 n 个元素,则准备 n+1 个桶,将数组的最小值放入 0 号桶,最大值放入 n 号桶
2.将数组剩余的 n-2 个元素按顺序均匀放入剩余的 n-1 个桶中,则必有一个空桶,
  因此要求的最大差值一定不会来自同一个桶的相邻元素之差
3.最大差值一定是相邻两个桶的后一个桶中最小值与前一个桶中最大值之差,相邻两个桶中间可能会有空桶
"""

from util import Util
from sort import Sort

def max_differ_sorted(a):
    """
    时间复杂度:O(n)
    """
    n = len(a)
    if n < 2:
        return 0

    _max = max(a)   #获取最大值
    _min = min(a)   #获取最小值
    # print(_min)
    # print(_max)
    if _min == _max:    #如果最大值等于最小值,则a中所有的数相等
        return 0

    # 准备三个长度为n+1的列表
    # hasNum记录每个桶中是否有数字
    # mins记录每个桶中的最小值
    # maxs记录每个桶中的最大值
    hasNum = [False] * (n+1)
    mins = [None] * (n+1)
    maxs = [None] * (n+1)
    id = 0
    for i in range(0, n):
        id = bucket(a[i], n, _min, _max)    # 获得当前元素属于哪个桶
        mins[id] = min(a[i], mins[id]) if hasNum[id] else a[i]
        maxs[id] = max(a[i], maxs[id]) if hasNum[id] else a[i]
        hasNum[id] = True

    # max_differ等于后一个桶最小值与前一个桶最大值之差的最大值
    res = 0
    lastMax = maxs[0]
    for j in range(1, n+1):
        if hasNum[j]:
            res = max(res, mins[j] - lastMax)
            lastMax = maxs[j]

    return res
    pass

def max_differ_sorted_std(a):
    """
    最直接的方法,先排序,再求相邻的最大差值
    时间复杂度:平均O(nlogn) > O(n)
    """
    n = len(a)
    if n < 2:
        return 0

    Sort.quick_sort(a)
    res = 0
    for i in range(n-1):
        res = max(res, a[i+1] - a[i])
        pass
    return res
    pass

def bucket(x, n, min, max):
    """
    x:待放入桶中的数
    n:数组的长度
    min:数组元素最小值
    max:数组元素最大值
    """
    return (x - min) * n // (max - min)
    pass

def test():
    a = Util.gen_randint_list()

    max_differ = max_differ_sorted(a)
    print(a)
    max_differ_std = max_differ_sorted_std(a)
    print(a)

    print('test: ', end = '')
    print(max_differ)
    print('std:  ', end = '')
    print(max_differ_std)

    if max_differ_std == max_differ:
        print('true')
    else:
        print('false')
    pass

if __name__ == '__main__':
    for x in range(10):
        test()
        pass

util.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2018-06-11 22:58:30

import random

class Util(object):
    """
    工具类
    """
    def gen_randint_list(n = 5, min = 0, max = 10):
        """
        生成一个随机int型列表
        """
        if n < 1 or min > max:
            return []

        rand_list = []
        for i in range(n):
            rand_list.append(random.randint(min, max))
            
        return rand_list
        pass

测试结果

max_differ_sorted.PNG
上一篇下一篇

猜你喜欢

热点阅读