求3個元素把一串數字均分爲4個子串,其和相等

題目:python

給定一串數字 
判斷是否存在這三個元素,它們將數字串分爲四個子串,其中每一個子串的數字之和均相同(該3個元素不歸入計算) 
要求時間複雜度和空間複雜度均不能超過O(n)app

# -*- coding: utf-8 -*-

import random


def split_to_four(n):
    nums = []
    for i in range(n):
        nums.append(random.randint(0, 99))
    # nums = [2, 1, 1, 1, 85, 1, 1, 1, 2]
    # nums = [5,1,3,1,1,3,3,2,2,1,1,1,1,1]
    print nums

    # i 三元素中左側元素索引
    # j 三元素中右側元素索引
    i, j = 1, len(nums) - 1

    total = sum(nums)

    k = None  # 三元素中中間元素索引

    # 當i<j,而且中間k還沒找到時,繼續循環
    while i < j and k is None:
        i, j, k = find_3th_points(i, j, nums, total)

    if k is None:
        return []

    return i, k, j


def find_3th_points(i, j, nums, total):
    """
    根據左右兩個點找中間的第三個點
    :param i:
    :param j:
    :param nums:
    :param total:
    :return:
    """
    i, j = find_two_points_on_side(i, j, nums)
    # 假如i,j都交叉了都沒找到左右和相等的狀況,那麼確定不存在這3個元素
    if i >= j:
        return i, j, None

    # 假如找到左右的位置,那麼就把i,j位置中間的元素進行計算,
    # 若是知足總值-左值-右值-中間的值%4==0,以及中間分隔的這段和邊上的同樣,
    # 那麼就找到這個k了,結束程序返回
    # 若是循環完了尚未這個k,則左右都往中間走,繼續找兩側相等的i,j點,繼續計算
    for k in range(i + 1, j):
        if (total - nums[i] - nums[j] - nums[k]) % 4 == 0 and sum(nums[:i]) == sum(nums[i + 1:k]):
            return i, j, k

    return i + 1, j - 1, None


def find_two_points_on_side(i, j, nums):
    """
    找出兩側分隔元素的位置
    從左側和右側分別求和判斷是否相等,相等則認爲找到i,j,不然根據左右和的大小判斷是i往前走1,仍是j往左側走1
    :param i:
    :param j:
    :param nums:
    :return:
    """
    while i < j:
        if sum(nums[:i]) > sum(nums[j:]):
            j -= 1
        elif sum(nums[:i]) < sum(nums[j:]):
            i += 1
        else:
            return i, j - 1
    return i, j


print split_to_four(10)

注意是利用左右兩側數據和相等的特性,再根據4個和相等的特性,找到左右2個,那麼總和減去左右2個線,再從中間找個線,能分隔出4個相等的和即爲找到了dom

相關文章
相關標籤/搜索