LeetCode 題解 | 238. 除自身以外數組的乘積

2021-02-20 力扣LeetCode算法研究所
點擊上方藍字設為星標

238. 除自身以外數組的乘積點擊文末閱讀原文查看題目

給定長度為 n 的整數數組 nums,其中 n > 1,返回輸出數組 output ,其中 output[i] 等於 nums 中除 nums[i] 之外其餘各元素的乘積。
輸入: [1,2,3,4]輸出: [24,12,8,6]

說明: 請 不要使用除法,且在 O(n) 時間複雜度內完成此題。

進階

你可以在常數空間複雜度內完成這個題目嗎?( 出於對空間複雜度分析的目的,輸出數組 不被視為 額外空間。)

解決方案

概述

這似乎是一個簡單的問題,可以在線性時間和空間內解決。可以先計算給定數組所有元素的乘積,然後對數組中的每個元素 x ,將乘積除以 x 來求得除自身值的以外的數組乘積。

然後這樣的解決方法有一個問題,就是如果輸入數組中出現 0,那麼這個方法就失效了。而且在問題中說明了不允許使用除法運算。這增加了這個問題的難度。

方法一:左右乘積列表

我們不必將所有數字的乘積除以給定索引處的數字得到相應的答案,而是可以利用索引處左側的所有數字乘積和右側所有數字的乘積相乘得到答案。

對於給定索引 i,我們將使用它左邊所有數字的乘積乘以右邊所有數字的乘積。讓我們更加具體的描述這個算法。

初始化兩個空數組 L 和 R。對於給定索引 i,L[i] 代表的是 i左側所有數字的乘積,R[i] 代表的是 i 右側所有數字的乘積。我們需要用兩個循環來填充 L 和 R 數組的值。對於數組 L,L[0]應該是 1,因為第一個元素的左邊沒有元素。對於其他元素:L[i]=L[i-1]*nums[i-1]。同理,對於數組 R,R[length-1] 應為 1。length 指的是輸入數組的大小。其他元素:R[i]=R[i+1]*nums[i+1]。當 R 和 L 數組填充完成,我們只需要在輸入數組上迭代,且索引 i處的值為:L[i]*R[i]。
class Solution:    def productExceptSelf(self, nums: List[int]) -> List[int]:                        length = len(nums)                        L, R, answer = [0]*length, [0]*length, [0]*length                                        L[0] = 1        for i in range(1, length):                                                            L[i] = nums[i - 1] * L[i - 1]                                        R[length - 1] = 1        for i in reversed(range(length - 1)):                                                            R[i] = nums[i + 1] * R[i + 1]                        for i in range(length):                                                answer[i] = L[i] * R[i]                return answer

class Solution {    public int[] productExceptSelf(int[] nums) {
int length = nums.length;
int[] L = new int[length]; int[] R = new int[length];
int[] answer = new int[length];
L[0] = 1; for (int i = 1; i < length; i++) {
L[i] = nums[i - 1] * L[i - 1]; }
R[length - 1] = 1; for (int i = length - 2; i >= 0; i--) {
R[i] = nums[i + 1] * R[i + 1]; }
for (int i = 0; i < length; i++) { answer[i] = L[i] * R[i]; }
return answer; }}

複雜度分析

時間複雜度:O(N),其中 N 指的是輸入數組的大小。空間複雜度:O(N),使用了 L 和 R 數組去構造答案。方法二:空間複雜度 O(1) 的方法儘管上面的方法已經能夠很好的解決這個問題,但是不是常數的空間複雜度。由於輸出數組不算在空間複雜度內,那麼我們可以將 L 或 R 數組在用輸出數組來計算,然後再動態構造另一個。讓我們來看看基於這個思想的算法。初始化 answer 數組,對於給定索引 i,answer[i] 代表的是 i左側所有數字的乘積。這種方法的唯一變化就是我們沒有構造 R 數組。而是用一個遍歷來跟蹤右邊元素的乘積。並更新數組 answer[i] = answer[i] * R。然後 R 更新為 R = R* nums[i]
class Solution:    def productExceptSelf(self, nums: List[int]) -> List[int]:                        length = len(nums)                        answer = [0]*length                                        answer[0] = 1        for i in range(1, length):                                                            answer[i] = nums[i - 1] * answer[i - 1]                                        R = 1;        for i in reversed(range(length)):                                                answer[i] = answer[i] * R            R *= nums[i]                return answer

class Solution {    public int[] productExceptSelf(int[] nums) {
int length = nums.length;
int[] answer = new int[length];
answer[0] = 1; for (int i = 1; i < length; i++) {
answer[i] = nums[i - 1] * answer[i - 1]; }
int R = 1; for (int i = length - 1; i >= 0; i--) {
answer[i] = answer[i] * R; R *= nums[i]; }
return answer; }}

複雜度分析

時間複雜度:O(N),其中 N 指的是輸入數組的大小。空間複雜度:O(1),問題的描述中說明了輸出數組不算空間複雜度。

點個在看,少個 bug👇

相關焦點

  • LeetCode刷題第三周【數組(簡單)】
    = maxNum ):   #判斷除自身外,是否大於等於其它值的2倍            return nums.index(maxNum)   #若大於等於 返回最大值索引        return -1     #否則返回-1class Solution {public:
  • LeetCode數組類知識點&題型總結
    leetcode第一題就是two-sum,對於這類題目,首先看題目要求的時間複雜度和空間複雜度是什麼,其次看有沒有限制條件,如要求不能有重複的子數組或者要求按照升序/降序排列等。1.按start排序2.在前一個區間的end和後一個區間的start找交集例題:252 meeting room[easy](https://leetcode.com/problems/meeting-rooms/)題目理解:給定一個數組,包含每個會議的開始時間和結束時間[[s1,e1],[s2,e2],...]
  • Leetcode題解 MaximumProductSubarray
    題解算法及複雜度(9 ms)  考慮本題是最大子段的乘積,可以聯想到動態規劃中的一個經典問題——最大子段和.最大欄位和的求解過程中,設定以位置i結尾的連續子段的最大子段和為dp[i],那麼狀態轉移方程為
  • [LeetCode] 912. Sort an Array 數組排序
    Output: [1,2,3,5]Example 2:Input: [5,1,1,2,0,0]Output: [0,0,1,1,2,5]Note:1<=A.length<=10000-50000<=A[i]<=50000這道題讓我們給數組排序
  • [LeetCode] 996. Number of Squareful Arrays 平方數組的個數
    Example 2:Input: [2,2,2]Output: 1Note:1<=A.length<=120<=A[i]<=1e9這道題給了一個非負整數組成的數組A,定義了一種平方數組,即任意兩個相鄰的數字之和是個完全平方數,現在讓找出有多少個A
  • 數據結構與算法:05 Leetcode同步練習(一)
    目錄題目01:兩數之和題目02:刪除排序數組中的重複項題目03:移除元素題目04:最大子序和題目05:盛最多水的容器題目06:搜索旋轉排序數組題目07:數組中的第K個最大元素題目08:除自身以外數組的乘積題目09:尋找兩個有序數組的中位數題目10:缺失的第一個正數
  • LeetCode145|數組中數字出現的次數II
    一,數組中數字出現的次數II1,問題描述在一個數組 nums 中除一個數字只出現一次之外,其他數字都出現了三次
  • [LeetCode] 918. Maximum Sum Circular Subarray 環形子數組的最大和
    >Example 5:Input: [-2,-3,-1]Output: -1 Explanation: Subarray [-1] has maximum sum -1Note:-30000<=A[i]<=300001<=A.length<=30000這道題讓求環形子數組的最大和
  • Leetcode題解 ProductofArrayExceptSelf
    題目分析:給出一串n個數的序列nums,要求對於每個數nums[i]求出除了這個數以外的其他所有數的乘積
  • LeetCode刷題指南(數組和矩陣)
    ,這裡也準備和大家分享他的LeetCode題解,於是我結合自己在進行刷題時做的分析和理解,按照題目類型進行劃分,形成本系列的LeetCode刷題指南。本文主要介紹的是LeetCode題庫中與數組和矩陣相關的經典題目,提供了LeetCode原題題號,參考答案,以及題目的部分解析。數組和矩陣把數組中的 0 移到末尾283.
  • 通關LeetCode刷題完整攻略,省時又高效
    按照分類刷,每個分類的題目,解法類似,這樣就用一個思路解一類題目了:方便大家閱讀,我把內容也貼出來放在這個回答下:1.雙指針通常用在排好序的數組或是鍊表中尋找對子。比如,你需要去比較數組中每個元素和其他元素的關係時,你就需要用到雙指針了。我們需要雙指針的原因是:如果你只用一個指針的話,你得來回跑才能在數組中找到你需要的答案。這一個指針來來回回的過程就很耗時和浪費空間了 — 這是考慮算法的複雜度分析的時候的重要概念。
  • ​LeetCode刷題實戰53:最大子序和
    所以,為了提高大家的算法能力,這個公眾號後續每天帶大家做一道算法題,題目就從LeetCode上面選 !今天和大家聊的問題叫做 最大子序和,我們先來看題面:https://leetcode-cn.com/problems/maximum-subarray/Given an integer array nums, find the contiguous subarray (containing at least one number
  • ​LeetCode刷題實戰137:只出現一次的數字 II
    所以,為了提高大家的算法能力,這個公眾號後續每天帶大家做一道算法題,題目就從LeetCode上面選 !今天和大家聊的問題叫做只出現一次的數字 II,我們先來看題面:https://leetcode-cn.com/problems/single-number-ii/Given an integer array nums where every element appears three times except for one, which appears exactly
  • 旋轉數組的最小數字
    原題把一個數組最開始的若干個元素搬到數組的末尾,我們稱之為數組的旋轉。輸入一個遞增排序的數組的一個旋轉,輸出旋轉數組的最小元素。例如,數組 [3,4,5,1,2] 為 [1,2,3,4,5] 的一個旋轉,該數組的最小值為 1。
  • [LeetCode] 923. 3Sum With Multiplicity 三數之和的多種情況
    Note:3<=A.length<=30000<=A[i]<=1000<=target<=300這道題是之前那道 3Sum 的拓展,之前那道題是說沒有重複數字,而這道題卻有大量的重複數字,所以每個組合可能會大量重複出現,讓我們統計出所有組合的總出現次數,並對一個超大數取餘。
  • ​LeetCode刷題實戰15題: 三數之和
    所以,為了提高大家的算法能力,這個公眾號後續每天帶大家做一道算法題,題目就從LeetCode上面選 !今天和大家聊的問題叫做三數之和 ,我們先來看題面:https://leetcode.com/problems/3sum/描述給定一個整數的數組,要求尋找當中所有的a,b,c三個數的組合,使得三個數的和為0.注意,
  • LeetCode 例題精講 | 16 最大子數組和:子數組類問題的動態規劃技巧
    子數組要求元素是連續的,那麼,前一個子問題的最優解,可能在後一個子問題中用不上。子問題的遞推鏈條就斷開了。正確的子問題定義那麼,怎麼解決這個子問題「續不上」的問題呢?我們需要取所有子問題結果的最大值,也就是限於文章篇幅,我們這裡就不討論這道題的空間優化方法以及其他解法了。以後會專門寫一篇文章介紹這道題的不同解法。最長公共子數組 理解了「最大子數組和」問題的解法,我們再來看一道類似思路的二維動態規劃問題:最長公共子數組。
  • leetcode刷對了麼
    今天,逆行君就帶你從世界觀和方法論兩方面走進「leetcode」 簡單來說,leetcode是一個美國的在線編程網站,它收集了各大公司的經典算法面試題,用戶可以選擇不同的語言進行代碼的在線編寫、編譯和調試。
  • [LeetCode] 976. Largest Perimeter Triangle 最大周長的三角形
    Example 3:Input: [3,2,3,4]Output: 10Example 4:Input: [3,6,2,3]Output: 8Note:3<=A.length<=100001<=A[i]<=10^6這道題給了個正整數數組
  • [LeetCode] 850. Rectangle Area II 矩形面積之二
    這道題是之前那道 Rectangle Area 的拓展,那道題只有兩個矩形重疊,而這道題有多個矩形可能同時重疊,整體難度一下就上來了,那麼通過將所有矩形面積加起來再減去重疊區域的方法這裡就不太適用了,因為多個矩形在同一區域重疊的話,都減去重疊面積是會錯的,還得把多減的補回來,相當的麻煩。