LeetCode算法題 (除自身以外數組的乘積)Day14!!!C/C++

https://leetcode.cn/problems/product-of-array-except-self/description/

一、題目分析

給你一個整數數組?nums,返回 數組?answer?,其中?answer[i]?等于?nums?中除?nums[i]?之外其余各元素的乘積?。

題目數據?保證?數組?nums之中任意元素的全部前綴元素和后綴的乘積都在??32 位?整數范圍內。

請?不要使用除法在?O(n)?時間復雜度內完成此題。

二、示例分析

示例 1:

輸入: nums =[1,2,3,4]
輸出:[24,12,8,6]

示例 2:

輸入: nums = [-1,1,0,-3,3]
輸出: [0,0,9,0,0]

? ? ? ? 結合題目以及示例,我們不難看出今天這道題目的需要完成的操作就是求出除自身以外的乘積,并存放到一個數組中,最后返回數組。

三、解題思路&代碼實現

? ? ? ? 在拿到任何一道題目的時候,我們首先要做的就是認真審題,讀懂題目要求以后,在心里或者草稿紙上寫出模擬過程的偽代碼,之后再做進一步的優化。今天這道題目也一樣,我們什么算法都先不要考慮,就用最暴力的方法來做。

1、暴力解法(復雜度為O(n^2))

1、核心思路:對于每一個nums[i],遍歷整個數組,跳過nums[i]并計算其余元素的乘積

?2、關鍵步驟:

? ? ? ? ?1、初始化ans數組,該數組的長度于nums數組相同
?????????2、雙重循環計算乘積:

? ? ? ? ? ? ? ? 外層循環:遍歷每個nums[i],準備計算ans[i]。

? ? ? ? ? ? ? ? 內層循環:遍歷nums所有元素,遇到 i == j時跳出此次循環(排除自身),其余元素累乘到sum。

????????3、存儲結果:

? ? ? ? ? ? ? ? 將計算好的sum存入到ans[i]中。

vector<int> productExceptSelf(vector<int>& nums) {vector<int> ans(nums.size());  // 定義結果數組,長度與 nums 相同// 遍歷計算每個位置 ans[i] 的值for (int i = 0; i < nums.size(); i++) {long long sum = 1;  // 初始化乘積為 1(因為 1 不影響乘法結果)// 計算 nums 中除 nums[i] 外所有元素的乘積for (int j = 0; j < nums.size(); j++) {if (j == i) continue;  // 跳過當前元素 nums[i],不參與乘積計算sum *= nums[j];  // 累乘其他元素}ans[i] = sum;  // 將計算結果存入 ans[i]}return ans;  // 返回最終結果
}

? ? ? ? 但是本題暴力解法是并不能通過所有的測試用例,題目的數據范圍給到了1e5,如果是雙重循環的話就是1e10。(PS:C/C++ 1秒能跑的數據大概是在1e7~1e8左右)。

? ? ? ? 那么現在就要想辦法優化把這段程序優化至O(n);????????

2、分類討論(數學分類法)

? ? ? ? 數學分類法的核心思路:

????????首先要統計出數組中是否有零,如果有的話零有多少個,如果有且僅有一個的話,那么ans數組中的元素就應該是除nums數組元素中為0的那一個元素應該為其余元素的乘積,其他元素則全部為零。

? ? ? ? 如果nums數組中0的個數>1,那么ans數組中的所有元素都應為0;

? ? ? ? 除以上兩種情況外 也就是nums數組中沒有零。

  1. 單零情況:若數組中僅含一個零,那么結果數組中,零所在位置的元素為其余非零元素的乘積,其余位置元素均為零。例如,對于數組?[1, 0, 2, 3],結果數組為?[0, 6, 0, 0],因為?1*2*3=6,零位置填充該值,其余位置補零。
  2. 多零情況:當數組中零的數量大于 1 時,無論如何計算,乘積必然為零,因此結果數組的所有元素均為零。
  3. 無零情況:若數組中不存在零,結果數組的每個元素等于數組所有元素的乘積除以對應位置的元素。例如,對于數組?[1, 2, 3, 4],結果數組為?[24, 12, 8, 6]?,因為?1*2*3*4=24,分別除以?1234?得到對應位置結果。
class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {// 初始化結果數組,大小與輸入數組相同vector<int> ans(nums.size());// sum: 所有元素的乘積(初始為1)// cnt_0: 統計數組中0的個數int sum = 1, cnt_0 = 0;// 第一次遍歷:計算所有元素的乘積,并統計0的個數for (auto i : nums) {sum *= i;           // 累乘所有元素if (i == 0)         // 遇到0時計數cnt_0++;}// 情況1:數組中恰好有1個0if (cnt_0 == 1) {int sum = 1;  // 重新計算非0元素的乘積(避免之前sum=0的影響)// 計算所有非0元素的乘積for (int i = 0; i < nums.size(); i++) {if (nums[i] != 0)sum *= nums[i];}// 填充結果數組:// - 非0位置的結果為0(因為總乘積含0)// - 0位置的結果為非0元素的乘積for (int i = 0; i < nums.size(); i++) {if (nums[i] != 0)ans[i] = 0;elseans[i] = sum;}return ans;}// 情況2:數組中有超過1個0// 所有位置的結果都是0(因為任何位置都至少包含一個0)if (cnt_0 > 1) {return ans;  // ans已初始化為全0}// 情況3:數組中沒有0// 直接計算:ans[i] = 總乘積 / nums[i]for (int i = 0; i < nums.size(); i++) {ans[i] = sum / nums[i];}return ans;}
};

????????以上代碼是優化了時間復雜度,但是題目中也是有明確要求不能使用除法的,所以盡管我們這段代碼的時間復雜度已經優化至O(n)。但還是需要改進。

3、前綴和&后綴和思想(正解

? ? ? ??核心思想:

? ? ? ??此方法的核心思想就是空間換時間,利用前綴和的思想的對ans數組進行預處理,這樣的好處就是每次取一個結果所需的時間復雜度為常數級,也就是O(1)。

? ? ? ? 其次通過將目標乘積拆分為兩部分(左部分、右部分)。第一次看到這段代碼時候,應該會想為什么能把nums[i]排除呢?

  • 左邊乘積ans[i])不包含?nums[i](因為只乘到?nums[i-1])。

  • 右邊乘積right)不包含?nums[i](因為先乘?right,再更新?right)。

  • 最終結果ans[i] = 左邊乘積 × 右邊乘積,自然排除了?nums[i]

class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {// 初始化結果數組,所有元素初始值為1(乘法單位元)vector<int> ans(nums.size(), 1);// 第一次遍歷:計算每個元素左邊所有元素的乘積(前綴積)// ans[i] 表示 nums[0] × nums[1] × ... × nums[i-1]for (int i = 1; i < nums.size(); i++) {ans[i] = ans[i - 1] * nums[i - 1];  // 遞推計算前綴積}// 初始化右邊乘積為1(最右邊元素的右邊沒有元素)int right = 1;// 第二次遍歷(從右往左):計算右邊乘積并合并到結果中// 此時 ans[i] = 左邊乘積 × 右邊乘積for (int i = nums.size() - 1; i >= 0; i--) {ans[i] *= right;   // 將當前元素的右邊乘積乘到結果上right *= nums[i];  // 更新右邊乘積(包含當前元素)}return ans;}
};

????????至此,上述代碼均滿足題目的所有要求!!!完結撒花🌸🌸🌸

四、題目總結

????????本題要求在不使用除法且時間復雜度為?O(n)?的條件下,計算數組中除自身元素之外其余各元素的乘積。解題過程需結合題目要求與數據限制,通過逐步優化算法來實現目標。

????????在暴力解法中,采用雙重循環遍歷數組,對每個元素計算其余元素的乘積,雖然邏輯直觀,但時間復雜度高達?O(n^2),無法滿足題目數據范圍的要求。

????????數學分類法通過統計數組中零的數量進行分類討論,優化了時間復雜度至?O(n)。當數組中有一個零,結果數組中零位置為其余非零元素乘積,其余位置為零;若有多個零,結果數組全為零;若無零,則用所有元素乘積除以對應位置元素得到結果。然而,該方法使用了除法運算,不符合題目要求。

????????最終的前綴和與后綴和思想是本題正解。利用空間換時間,通過兩次遍歷分別計算前綴積和后綴積,將目標乘積拆分為左右兩部分。先從前向后計算前綴積存入結果數組,再從后向前更新后綴積并與前綴積合并,既避免了除法運算,又滿足了?O(n)?的時間復雜度要求,高效且準確地解決了問題 。這種解題過程體現了在算法設計中平衡時間復雜度、空間復雜度與題目限制條件的重要性。

????????算法之美在于其嚴謹的邏輯與精巧的設計。希望讀者能通過本題,掌握空間換時間的核心思想,在日后的開發中靈活運用這種預處理技巧。謝謝大家!!!荊軻刺秦!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/903610.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/903610.shtml
英文地址,請注明出處:http://en.pswp.cn/news/903610.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何寫好Verilog狀態機

還記得之前軟件的同事說過的一句話。怎么凸顯自己的工作量&#xff0c;就是自己給自己寫BUG。 看過夏宇聞老師書的都知道&#xff0c;verilog的FSM有moore和mealy,然后有一段&#xff0c;二段&#xff0c;三段式。記得我還是學生的時候&#xff0c;看到這里的時候&#xff0c;感…

晶振頻率/穩定度/精度/溫度特性的深度解析與測量技巧

在電子設備的精密世界里&#xff0c;晶振如同跳動的心臟&#xff0c;為各類系統提供穩定的時鐘信號。晶振的頻率、穩定度、精度以及溫度特性&#xff0c;這些關鍵參數不僅決定了設備的性能&#xff0c;更在不同的應用場景中發揮著至關重要的作用。 一、頻率選擇的本質&#xff…

Kafka-可視化工具-Offset Explorer

安裝&#xff1a; 下載地址&#xff1a;Offset Explorer 安裝好后如圖&#xff1a; 1、下載安裝完畢&#xff0c;進行新增連接&#xff0c;啟動offsetexplorer.exe&#xff0c;在Add Cluster窗口Properties 選項下填寫Cluster name 和 kafka Cluster Version Cluster name (集…

LabVIEW模板之溫度監測應用

這是一個溫度監測應用程序&#xff0c;基于 Continuous Measurement and Logging 示例項目構建&#xff0c;用于讀取模擬溫度值&#xff0c;當溫度超出給定范圍時發出警報 。 這個。 詳細說明 運行操作&#xff1a;直接運行該 VI 程序。點擊 “Start” 按鈕&#xff0c;即可開…

后端[特殊字符][特殊字符]看前端之Row與Col

是的&#xff0c;在 Ant Design 的柵格布局系統中&#xff0c;每個 <Row> 組件確實對應頁面上的一個獨立行。以下是更詳細的解釋&#xff1a; 核心概念 組件作用類比現實場景<Row>橫向容器&#xff0c;定義一行內容類似 Excel 表格中的一行<Col>縱向分割&am…

[特殊字符] SpringCloud項目中使用OpenFeign進行微服務遠程調用詳解(含連接池與日志配置)

&#x1f4da; 目錄 為什么要用OpenFeign&#xff1f; 在cart-service中整合OpenFeign 2.1 引入依賴 2.2 啟用OpenFeign 2.3 編寫Feign客戶端 2.4 調用Feign接口 開啟連接池&#xff0c;優化Feign性能 3.1 引入OkHttp 3.2 配置啟用OkHttp連接池 3.3 驗證連接池生效 Feign最佳…

VARIAN安捷倫真空泵維修清潔保養操作SOP換油操作流程內部轉子圖文并茂內部培訓手側

VARIAN安捷倫真空泵維修清潔保養操作SOP換油操作流程內部轉子圖文并茂內部培訓手側

【android bluetooth 案例分析 03】【PTS 測試 】【PBAP/PCE/SSM/BV-10-C】

1. PBAP/PCE/SSM/BV-10-C [PCE Does not share PbapSupportedFeatures bits] 這個 PTS 測試用例 PBAP/PCE/SSM/BV-10-C 的核心目的是驗證 PBAP 客戶端&#xff08;PCE&#xff09;在與舊版服務器通信時&#xff0c;不會發送 PbapSupportedFeatures 特性位&#xff0c;以確保兼…

批量刪除OpenStack實例

在Linux終端實現批量刪除OpenStack實例&#xff0c;支持并發刪除、安全確認、重試機制、優先清理運行中實例 #!/bin/bash # # 增強版 OpenStack 刪除實例腳本 # 功能&#xff1a;支持并發刪除、安全確認、重試機制、優先清理運行中實例 # 更新&#xff1a;2025年4月30日 # ##…

# 基于 Python 和 jieba 的中文文本自動摘要工具

基于 Python 和 jieba 的中文文本自動摘要工具 在信息爆炸的時代&#xff0c;快速準確地提取文本核心內容變得至關重要。今天&#xff0c;我將介紹一個基于 Python 和 jieba 的中文文本自動摘要工具&#xff0c;幫助你高效地從長文本中提取關鍵信息。 一、背景與需求 在處理…

Seaborn數據可視化庫

一、Seaborn介紹&#xff1a;基于Matplotlib的Python數據可視化庫&#xff0c;專注繪制統計圖形&#xff0c;簡化可視化過程&#xff0c;提供高級接口和美觀默認主題。 二、安裝與導入 1.安裝&#xff1a;可使用pip install seaborn或conda install seaborn&#xff0c;也可使…

機器視覺2D碼垛和機器視覺3D碼垛的區別

機器視覺3D碼垛是一種結合3D視覺技術和工業機器人的自動化系統,主要用于在復雜環境中精準識別、定位并堆疊(碼垛)各種形狀、尺寸的物體。它通過3D傳感器(如激光雷達、結構光相機、雙目視覺等)獲取物體的三維空間信息,并結合算法規劃機器人的抓取路徑和碼放策略,實現高效…

Python魔法函數深度解析

一、魔法函數是什么&#xff1f; 魔法函數&#xff08;Magic Methods&#xff09;是Python中以雙下劃線&#xff08;__xx__&#xff09;包裹的特殊方法&#xff0c;它們為類提供了一種與Python內置語法深度集成的能力。這些方法由解釋器自動調用&#xff0c;無需顯式調用&…

C++負載均衡遠程調用學習之自定義內存池管理

目錄 1.內存管理_io_buf的結構分析 2.Lars_內存管理_io_buf內存塊的實現 3.buf總結 4.buf_pool連接池的單例模式設計和基本屬性 5.buf_pool的初始化構造內存池 6.buf_pool的申請內存和重置內存實現 7.課前回顧 1.內存管理_io_buf的結構分析 ## 3) Lars系統總體架構 ? …

流水線問題(算法設計)C++

目錄 一、需求分析 1.1 問題描述 1.2 數據需求 1.3 功能需求 1.4 開發環境 二、概要設計 2.1 抽象數據類型 ADT 的定義 2.2 系統的主要功能模塊 2.3 功能模塊聯系圖 三、詳細設計 3.1 數據結構設計 3.2 主要算法 四、系統運行及結果分析 1. 用戶界面 2. 程序運行…

從實列中學習linux shell4: shell 腳本中 $0 $1 $2 $3 >> 以及 awk 都是干啥的?

在 Linux Shell 腳本中&#xff0c;這些符號和工具的功能如下&#xff1a; 一、位置參數 $0 $1 $2 $3 符號功能說明示例$0腳本自身的文件名若執行 ./test.sh&#xff0c;則 $0 值為 ./test.sh$1第一個參數執行 ./test.sh apple 時&#xff0c;$1 值為 "apple"$2第二…

TM1668芯片學習心得三

一、鍵掃數據儲存地址如下所示&#xff0c;先發讀鍵命令后&#xff0c;開始讀取按鍵數據BYTE1-BYTE5字節&#xff0c;讀數據從低位開始輸出&#xff0c;其中B6和B7位為無效位&#xff0c;此時芯片輸出為0。芯片K和KS引腳對應的按鍵按下時&#xff0c;相對應的字節內的 BIT位為1…

MySQL 基本查詢(一)

文章目錄 Create(insert)指定列的單行插入和全列插入多行全列插入和指定列的多行插入如果主鍵存在&#xff0c;要插入替換存在的值replace 基本select全列查詢指定列查詢where子句where子句案例語文成績在 [80, 90] 分的同學及語文成績數學成績是 58 或者 59 或者 98 或者 99 分…

LeetCode路徑總和系列問題解析:I、II、III的解決方案與優化

文章目錄 引言一、路徑總和 I&#xff08;LeetCode 112&#xff09;問題描述方法思路Java代碼實現復雜度分析 二、路徑總和 II&#xff08;LeetCode 113&#xff09;問題描述方法思路Java代碼實現復雜度分析 三、路徑總和 III&#xff08;LeetCode 437&#xff09;問題描述方法…

NFC 碰一碰發視頻貼牌技術,音頻功能的開發實踐與技術解析

在數字化營銷與信息交互場景中&#xff0c;NFC 碰一碰技術憑借其便捷性和高效性&#xff0c;成為快速傳遞多媒體內容的新選擇。通過 NFC 實現視頻音頻的快速傳輸&#xff0c;不僅能提升用戶體驗&#xff0c;還能為各類場景帶來創新應用。本文將深入探討該功能開發過程中的關鍵技…