题目:
给定一串数字
判断是否存在这三个元素,它们将数字串分为四个子串,其中每个子串的数字之和均相同(该3个元素不纳入计算)
要求时间复杂度和空间复杂度均不能超过O(n)
# -*- 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个相等的和即为找到了