Python编程之数据结构与算法练习_006

小和问题:在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组的小和。
例子[1, 3, 4, 6, 5]
1左边比1小的数,没有
3左边比3小的数,1;
4左边比4小的数,1,3;
6左边比6小的数,1,3,4;
5左边比5小的数,1,3,4;
所以小和为1+1+3+1+3+4+1+3+4=21

解题原理不写,《剑指Offer》书里有详细的讲解。简单说,就是使用了归并排序。

说句题外话,其实各种排序算法本身不是很重要,最重要的是排序算法体现出来的思想是非常值得深究的。

废话少说,直接撸代码,关键位置已标红

__author__ = 'Orcsir'
import random


def get_little_sum(array: list) -> int:
    def merge(array: list, left: int, middle: int, right: int) -> int:
        left_index = left
        right_index = middle + 1
        array_help = [0] * (right - left + 1)
        index = 0
        little_sum = 0
        while left_index <= middle and right_index <= right:
            if array[left_index] < array[right_index]:
                # 合并过程中出现左区数字x小于右区数字y,一次性榨取x对总体小和的贡献
                little_sum += (array[left_index] * (right - right_index + 1))

                array_help[index] = array[left_index]
                index, left_index = index + 1, left_index + 1

            else:
                array_help[index] = array[right_index]
                index, right_index = index + 1, right_index + 1

        while left_index <= middle:
            array_help[index] = array[left_index]
            index, left_index = index + 1, left_index + 1

        while right_index <= right:
            array_help[index] = array[right_index]
            index, right_index = index + 1, right_index + 1

        for i in range(len(array_help)):
            array[left + i] = array_help[i]
        return little_sum

    def merge_sort(array: list, left: int, right: int) -> int:
        if left == right:
            return 0
        mid = left + ((right - left) >> 1)
        left_little_sum = merge_sort(array, left, mid)
        right_little_sum = merge_sort(array, mid + 1, right)
        ret = merge(array, left, mid, right)
        return left_little_sum + right_little_sum + ret

    return merge_sort(array, 0, len(array) - 1)


def normal_method(lst: list) -> int:
    little_sum = 0
    for i in range(len(lst)):
        for j in range(i):
            if lst[j] < lst[i]:
                little_sum += lst[j]
    return little_sum


# Test
max_value = 100
max_length = 100
max_round = 100
array = [random.randint(-max_value, max_value) for i in range(max_length)]

for i in range(max_round):
    corr_answer = normal_method(array)
    little_sum = get_little_sum(array)
    if little_sum != corr_answer:
        print("Fucked.")
else:
    print("Success")

 

posted @ 2018-04-22 12:08  Orcsir  阅读(187)  评论(0编辑  收藏  举报