最近在帮别人弄聊天机器人
虽然只是很小型的学习应用
但觉得很有意思
尤其是涉及到了知识图谱的应用
可以好好来看看
题目描述:
给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。
示例:
输入: [1,2,3,4]
输出: [24,12,8,6]
提示:题目数据保证数组之中任意元素的全部前缀元素和后缀(甚至是整个数组)的乘积都在 32 位整数范围内。
说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。
思路解析:
这一题可谓是有些刁钻了,因为有两个限制条件:1)不要使用除法;2)在O(n) 时间复杂度内完成此题。我们一个一个来剖析,首先,不要使用除法,这就断了我们大多数人最原本的想法。最简单的无非就是首先求得给定的nums数组中所有元素的乘积,然后依次遍历该数组,将乘积值除以当前元素值,即可得 nums 中除 nums[i] 之外其余各元素的乘积。现在题目给了条件一,也就限制了这种解法。我们再来看看条件二,要求我们算法的时间复杂度为O(n) ,这无非就是要求我们只能用一层遍历,不能超过了两层。这个条件限制了我们使用暴力法的可能,即遍历某一个元素时,继续遍历nums数组中除该元素的所有元素,相乘即可得我们想要的结果。那么只能用一层遍历,怎么搞呢?
别急,我们还是得抓住解题的一般做法,即output[i] 是怎么计算出来的,过程如下所示:
那么关键点就转换成了如何找到每个元素的左右集合,而且还得考虑时间复杂度。既然是两个左右集合,那么最容易想到的无非就是先定义两个list集合出来分别代表左右集合。然后就是各自遍历数组,分别求值。这里面都有个时间差,也就是当前output[i]只是之前所有元素的乘积,不包括当前nums[i]的值,get到了这点那么求解左右集合就很easy了。最后我们只需要再从左至右遍历一次数组,将left[i]和right[i]的值相乘即可得output[i],也就得到了我们最终想要的结果。代码如下:
class Solution(object):
def productExceptSelf(self, nums):
"""
空间复杂度O(n)
:type nums: List[int]
:rtype: List[int]
"""
left_list, right_list = [1] * (len(nums)+1), [1] * (len(nums)+1)
left, right = 1, 1
result = []
for i in range(len(nums)):
left_list[i+1] = left_list[i] * left
left = nums[i]
for j in range(len(nums)-1, -1, -1):
right = nums[j]
right_list[j] = right_list[j+1] * right
for index in range(1, len(nums)+1):
result.append(left_list[index] * right_list[index])
return result
if __name__ == "__main__":
nums = [1, 2, 3, 4]
result = Solution().productExceptSelf(nums)
print(result)
执行效率还算是不错,在80%左右。