力扣—LCP08剧情触发时间

题目描述

在战略游戏中,玩家往往需要发展自己的势力来触发各种新的剧情。一个势力的主要属性有三种,分别是文明等级(C),资源储备(R)以及人口数量(H)。在游戏开始时(第 0 天),三种属性的值均为 0。

随着游戏进程的进行,每一天玩家的三种属性都会对应增加,我们用一个二维数组 increase 来表示每天的增加情况。这个二维数组的每个元素是一个长度为 3 的一维数组,例如 [[1,2,1],[3,4,2]] 表示第一天三种属性分别增加 1,2,1 而第二天分别增加 3,4,2。

所有剧情的触发条件也用一个二维数组 requirements 表示。这个二维数组的每个元素是一个长度为 3 的一维数组,对于某个剧情的触发条件 c[i], r[i], h[i],如果当前 C >= c[i] 且 R >= r[i] 且 H >= h[i] ,则剧情会被触发。

根据所给信息,请计算每个剧情的触发时间,并以一个数组返回。如果某个剧情不会被触发,则该剧情对应的触发时间为 -1 。

示例 1:


输入: increase = [[2,8,4],[2,5,0],[10,9,8]] requirements = [[2,11,3],[15,10,7],[9,17,12],[8,1,14]]

输出: [2,-1,3,-1]

解释:

初始时,C = 0,R = 0,H = 0

第 1 天,C = 2,R = 8,H = 4

第 2 天,C = 4,R = 13,H = 4,此时触发剧情 0

第 3 天,C = 14,R = 22,H = 12,此时触发剧情 2

剧情 1 和 3 无法触发。


示例 2:


输入: increase = [[0,4,5],[4,8,8],[8,6,1],[10,10,0]] requirements = [[12,11,16],[20,2,6],[9,2,6],[10,18,3],[8,14,9]]

输出: [-1,4,3,3,3]


示例 3:


输入: increase = [[1,1,1]] requirements = [[0,0,0]]

输出: [0]

解题思路

一开始拿到这道题,心想这不是挺简单吗,外层一个循环用来累加increase,然后每累加一次,就在requirements里面循环找出满足条件得,事实证明,想得太天真了!中等难度得题目这么好想怎么可能,结果超时了。

看了别人大佬得解法,才觉得恍然大悟,用二分法来查找速度会更快,开始先一层循环保存increase所有可能的结果,然后遍历requirements每一个元素,在实现保存好的结果中使用二分查找。

代码1是暴力解法(超时):

class Solution(object):
    def onCondi(self, a, b):
        for i in range(len(a)):
            if a[i] < b[i]:
                return False
        return True
    def calPlus(self, a, b):
        for i in range(len(a)):
            a[i] += b[i]
        return a
    def getTriggerTime(self, increase, requirements):
        increase.insert(0, [0] * len(increase[0]))
        res = [-1] * len(requirements)
        cur = [0] * len(increase[0])
        for i in range(len(increase)):
            cur = self.calPlus(cur, increase[i])
            for j in range(len(requirements)):
                if self.onCondi(cur, requirements[j]):
                    if res[j] == -1:
                        res[j] = i
        return res


S = Solution()
print(S.getTriggerTime([[2,8,4],[2,5,0],[10,9,8]], [[2,11,3],[15,10,7],[9,17,12],[8,1,14]]))

代码1中getTriggerTime函数两层循环已经很恐怖了,特别是1 <= increase.length <= 10000, 1 <= requirements.length <= 100000,两层循环进行10亿次计算,必定超时

代码2是二分解法:

from copy import deepcopy
class Solution(object):
    def calPlus(self, a, b):
        temp = deepcopy(a)
        for i in range(len(a)):
            temp[i] += b[i]
        return temp

    def getTriggerTime(self, increase, requirements):
        res = [-1] * len(requirements)
        forces = [[0, 0, 0]]
        for i in range(len(increase)):
            forces.append(self.calPlus(forces[-1], increase[i]))
        for i, requirement in enumerate(requirements):
            left, right = 0, len(forces) - 1
            while left <= right:
                mid = left + (right - left) // 2
                if requirement[0] <= forces[mid][0] and requirement[1] <= forces[mid][1] and requirement[2] <= forces[mid][2]:
                    res[i] = mid
                    right = mid - 1
                else:
                    left = mid + 1
        return res

S = Solution()
print(S.getTriggerTime([[2,8,4],[2,5,0],[10,9,8]], [[2,11,3],[15,10,7],[9,17,12],[8,1,14]]))

代码2中第一层for循环首先保存结果,这个时间复杂度比较小,尽管后面也是二层循环(for和while),但是while里面是二分查找,节省了大量的循环时间,所以比代码1快不少

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值