From a6029b2a76dae43df3923d94c247bbb2948d6cdd Mon Sep 17 00:00:00 2001 From: gameloader Date: Fri, 15 Mar 2024 10:28:20 +0800 Subject: [PATCH] leetcode update --- content/posts/leetcode.md | 79 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/content/posts/leetcode.md b/content/posts/leetcode.md index 46c7ed3..6d1a0f4 100644 --- a/content/posts/leetcode.md +++ b/content/posts/leetcode.md @@ -1216,3 +1216,82 @@ func counting(nums []int, goal int) int { } ``` + +## day18 2024-03-15 + +### 238. Product of Array Except Self + +Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i]. + +The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer. + +You must write an algorithm that runs in O(n) time and without using the division operation. + +![0315l01oAnZceg6j](https://testingcf.jsdelivr.net/gh/game-loader/picbase@master/uPic/0315l01oAnZceg6j.png) + +### 题解 + +题目中明确要求本题不能使用分治法, 且算法复杂度在O(n). 本题要求的为数组中每个元素对应的除该元素之外的其他元素的乘积. 根据给出的例子可以发现当存在0的时候是一种特殊情况. 当存在0时除0以外的其他元素对应的结果均为0. 一般情况下可以使用先求出全部元素的乘积, 再遍历数据使用总乘积除以当前元素即可求得对应位置的结果. 因为这样只需要固定遍历两次数据, 故时间复杂度为O(n), 又只需要一个变量来保存总乘积, 一个变量指示是否存在0元素, 故空间复杂度为O(1). 因为题目中明确说明了乘积保证为整数, 故在使用除法的过程中不用考虑结果为小数的问题. + +### 代码 + +```go +func productExceptSelf(nums []int) []int { + sum := 1 + flag := 0 + for _, value := range nums{ + if value == 0{ + flag++ + }else{ + sum *= value + } + } + if flag > 1{ + return make([]int, len(nums)) + } + if flag == 1{ + result := []int{} + for _, value := range nums{ + if value == 0{ + result = append(result, sum) + }else{ + result = append(result, 0) + } + } + return result + } + result := []int{} + if flag == 0{ + for _, value := range nums{ + result = append(result, sum/value) + } + + } + return result +} +``` + +### 总结 + +查看更快的解法, 发现都使用了前缀积和后缀积, 即从前向后遍历, 计算出当前位置元素的前缀积, 然后反向遍历, 在计算出后缀积的同时就得到了最终的结果. 一个示例代码如下 + +```go +func productExceptSelf(nums []int) []int { + res := make([]int, len(nums)) + + prefix := 1 + for i, n := range nums { + res[i] = prefix + prefix *= n + } + + postfix := 1 + for i := len(nums) - 1; i >= 0; i-- { + res[i] *= postfix + postfix *= nums[i] + } + return res +} +``` + +其实无论是前缀和还是前缀积, 都是一个对以往的计算状态的保留, 保存了更多的信息, 避免了重复的运算, 这种思想是值得细细品味的.