leedcode 刷題 - 除自身以外數組的乘積 - 和為 K 的子數組

I238. 除自身以外數組的乘積 - 力扣(LeetCode)

給你一個整數數組?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]提示:2 <= nums.length <= 105
-30 <= nums[i] <= 30
保證 數組 nums之中任意元素的全部前綴元素和后綴的乘積都在  32 位 整數范圍內進階:你可以在 O(1) 的額外空間復雜度內完成這個題目嗎?( 出于對空間復雜度分析的目的,輸出數組 不被視為 額外空間。)

題目已經給的很明顯了,就是使用前綴積 和 后綴積 的方式來求解,這種方式其實 是一個簡化的 動態規劃。

用兩個數組,分別存儲 從起始位置到 i 位置的乘積 和 從 末尾位置 到 i 位置的乘積;

上述兩個結果對應的就是 f[i]? 和? g[i] 。

遞推公式:

f[i] = f[i - 1] * nums[i - 1];g[i] = g[i + 1] * nums[i + 1];

f[0] 和 g[nums.size()] 都是需要自己手動算的,上述遞推公式是算不出來的。

如果我們像計算題目描述的某個位置(比如是 i 位置)的 前綴積 和 后綴積的話,只需要計算? ? ? ? f[i] * g[i] 既可,因為?f[i] 表示的就是 i 之前的 所有積,g[i] 表示的就是 i 之后的所有的積。

完整代碼:

class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {vector<int> f(nums.size(), 1);vector<int> g(nums.size(), 1);vector<int> ret(nums.size());for(int i = 1;i < nums.size(); i++) f[i] = f[i - 1] * nums[i - 1];for(int i = nums.size() - 2; i >= 0; i--) g[i] = g[i + 1] * nums[i + 1];for(int i = 0;i < nums.size();i++) ret[i] = g[i] * f[i];return ret;
}
};

I560. 和為 K 的子數組 - 力扣(LeetCode)

給你一個整數數組?nums?和一個整數?k?,請你統計并返回?該數組中和為?k?的子數組的個數?

子數組是數組中元素的連續非空序列。

示例 1:輸入:nums = [1,1,1], k = 2
輸出:2
示例 2:輸入:nums = [1,2,3], k = 3
輸出:2

?還是使用前綴和,我們可以使用 找到一個前綴和 sum[i] 就表示,從數組 0 號位置開始,到 i 位置的所有元素之和。

那么,我們只需要在這個區間當中找到 在 [0,i] 這個區間當中,某一個位置作為起始位置(假設為 j? ?),到 i 位置,這個子數組的 元素之和等于k,那么 ,[0,j] 這個區間當中各個 元素之和就是? ? ? ? ? ?sum[i] - k;

?往后,只需要? i 往后尋找,就不會找漏。

但是,上述還是有一個問題,如果我們直接遍歷 sum 數組的,來找到 j 這個位置的話,在加上 創建 sum 數組的時間復雜度,實際上,這個算法的整個 時間復雜度其實還不如 暴力解法。

所以,其實我們不用? 循環一個一個 去找? j? 位置,我們可以利用一個 hash 表來 代替 sum 存儲的這些 前綴和的值,也就是代替 sum 存儲 其中的每一個元素。

哈希表:? hash<前綴和值, 前綴和出現次數>

這樣,如果我們 想 在? [0,i] 這個區間當中, 找到 j 這個位置,只需要 利用 hash 表的快速查找來查找 在當前hash 表當中有沒有 sum[i] - k 這個前綴和,同時,利用 hash 表當中的 count()函數,可以快速查找,這個?sum[i] - k ?出現次數。

關于前綴和加入hash 表的時機:
因為我們的前綴和算法,是要找的是?在 [0,i] 這個區間當中 ,有多少個 前綴和 等于sum[i] - k;? ?。

如果直接 在一開始就把 sum 計算出來,然后把 區間當中 前綴和 和 前綴和出現的次數加入到 hash 表當中是會計算到 i 后面的值。所以不行。

所以,我們在計算 i 位置之前,哈希表里面值存儲 [0, i - 1] 位置的前綴和。

還有一種情況,當 當前的整個的 前綴和 等于 k 的話,那么,在上述的算法當中,其實我們是找不到這個情況的,因為 我們找到的是 等于 k 的子區間,這個子區間的起始位置上述說過了,是 j ,那么 滿足? ?sum[i] - k;?的 區間就是 [0, j - 1], 那么在這個情況當中就是 [0, -1] 這個區間,這個區間是不存在的。

所以,我們開始就要默認 數組當中有一個 和為 0 的前綴和,即: hash[0] = 1;

完整代碼:

class Solution {
public:int subarraySum(vector<int>& nums, int k) {unordered_map<int, int> hash(nums.size());hash[0] = 1;int sum = 0, ret = 0; // sum 代替sum數組,利用變量給 hash 當中賦值;ret 返回個數for(auto& e : nums){sum += e; // 計算當前的前綴和// 計算滿足 條件的區間,是否在 hash 當中出現。count()函數判斷是否出現//  出現計數器 加上 這個前綴和 在 hash 當中出現的次數if(hash.count(sum - k)) ret += hash[sum - k]; hash[sum]++;                  }return ret;}
};

I974. 和可被 K 整除的子數組 - 力扣(LeetCode)

給定一個整數數組?nums?和一個整數?k?,返回其中元素之和可被?k?整除的(連續、非空)?子數組?的數目。

子數組?是數組的?連續?部分。

示例 1:輸入:nums = [4,5,0,-2,-3,1], k = 5
輸出:7
解釋:
有 7 個子數組滿足其元素之和可被 k = 5 整除:
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
示例 2:輸入: nums = [5], k = 9
輸出: 0

要解決這道題目,首先要知道 同于定理?

也就是 如果 a 和 b 的差值,除上 p ,如果是整除的話,也就是余數是零的話,a 除上 p 的余數 =? ? b 除上 p 的余數

而且,還需要清楚,在C++ 當中, [負數 % 正數] 的結果是 一個負數

?也就是說,其實[負數 % 正數] ? 其實結果也是一個 余數,但是這個余數是負數。

所以,針對這種情況,我們要對這個負數進行修正,把他修正為 正數。

所以,當我們在計算?[負數 % 正數] 的 結果之時,其實,計算出的負數的結果在加上 模數(也就是其中的正數),其實就是對應的正數的結果。如下圖所示:
?

上述的計算方式對于 a 是負數的情況來說,計算出的結果就是修正之后的結果,也就是修正為 正數之后的結果。

但是上述的 修正方式對于 a 是正數的情況是 計算錯誤的,因為 對于 a 是正數的情況來說, a % b 本來就是 正確的結果,但是后面又加上了 一個 b,所以是不正確的。

所以,為了 正數和負數統一,我們共用的方式就是? 在上述計算式子當中,再 % b 即可。

上述式子就是我們想要的i修正公式了。


所以,按照和這個問題其實就和上述 和為K的子數組求解方式一樣了。

先求出所有的 從 0 號數組位置開始的 所以前綴模,保存到一個數組當中,然后 求出 與 K 模的余數即可。

同樣優化方式和上述一樣,不需要多定義一個 數組來保存 前綴模,這樣也不好 查找對應的前綴模,只需要 用一個 hash表來存儲即可。

上述問題就被簡化為了 在 [0, i - 1] 這個區間當中,找到有多少個前綴和 的 余數等于 (sum %? k + k ) % k。

完整代碼:
?

class Solution {
public:int subarraysDivByK(vector<int>& nums, int k) {unordered_map<int, int> hash;hash[0 % k] = 1; // 0 這數的余數int sum = 0, ret = 0;for(auto& e : nums){sum += e;int r = (sum%k + k) % k;if(hash.count(r)) ret += hash[r];hash[r]++;}return ret;}
};

I525. 連續數組 - 力扣(LeetCode)

?給定一個二進制數組?nums?, 找到含有相同數量的?0?和?1?的最長連續子數組,并返回該子數組的長度。

示例 1:輸入: nums = [0,1]
輸出: 2
說明: [0, 1] 是具有相同數量 0 和 1 的最長連續子數組。
示例 2:輸入: nums = [0,1,0]
輸出: 2
說明: [0, 1] (或 [1, 0]) 是具有相同數量0和1的最長連續子數組。

在數組當中,所有的 元素的值要么是 0 ,要么是1。我們需要找到一個 符合要求的最長的連續的子數組,返回這個子數組的長度。

我們在統計個數的時候,其實是可以做到轉化的,如果把 0 全部替換為-1,那么我們統計個數的問題,其實就 轉化成了 找到一個 元素之和等于 0 的子數組。

所以,這道題目就可以使用前綴和的方法來解決。

使用hash 表來存儲 前綴和為 sum 的區間,所以嗎,應該是 unordered_map<sum, i > (其中 sum 是前綴和,i 是這個前綴和區間的下標)。

當找到某一個下標,和為? sum,計算出 這個區間的長度,就把這個 對應的 綁定的值存入到哈希表當中。

如果有重復的 sum,但是區間不一樣,不需要重新更新原本在 hash 表當中的 <sum , i>, 只需要保留之前存入的 <sum, i> 即可。因為 ,我們需要找到 子區間最長的子數組,那么 下標應該是越考左 ,那么 計算出的 子區間 長度才是最大的。

同樣,為了處理特殊情況:當 [0?, i] 這個子區間計算出的前綴和就是0了,那么按照上述? 和為K的子數組 這個題目當中邏輯去 找到子區間的話,就會在 -1 為開始的區間去找。

所以,我們需要 在開始 默認 一個子區間的前綴和是0,即? hash[0] = -1;

上述的過程就可以找出所有的 合法的子數組了,現在就是如何計算這個子數組的區間大小?

如上,我們只需要找出 i 和 j 兩個下標,使得 [0, i] 的 前綴和 和 [0, j] 的前綴和 相等即可

?所以我們計算出的 區間的 長度就是 i - j

完整代碼:

class Solution {
public:int findMaxLength(vector<int>& nums) {unordered_map<int ,int> hash;hash[0] = -1;   // 默認 剛開始 哈希表當中有一個 前綴和為0 的區間int sum = 0, ret = 0;for(int i = 0 ;i < nums.size(); i++){sum += nums[i] == 0 ? -1 : 1; // 如果是 0 就加-1,如是1 就加 1// 如果 sum 在hash 當中存在,說明此時就已經找到了 符合條件的子區間// 那么就更新的 ret 返回值。if(hash.count(sum)) ret = max(ret, i - hash[sum] + 1 - 1);else hash[sum] = i;  // sum 在 hash 當中不存在,那么 就添加一個 hash 元素}return ret;}
};

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

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

相關文章

AdaBoost提升分類器性能

目錄 AdaBoost算法原理 AdaBoost工作詳情 初始權重分配 第一輪 第二輪 后續輪次 最終模型 AdaBoost的API解釋 AdaBoost 對房價進行預測 AdaBoost 與決策樹模型的比較 結論 AdaBoost算法原理 在數據挖掘中&#xff0c;分類算法可以說是核心算法&#xff0c;其中 Ada…

gitee推薦-PHP面試準備的資料

該內容為giee項目。PHP-Interview: 這個項目是自己準備PHP面試整理的資料。包括PHP、MySQL、Linux、計算機網絡等資料。方便自己以后查閱&#xff0c;會不定期更新&#xff0c;歡迎提交pr&#xff0c;如果錯誤&#xff0c;請指出&#xff0c;謝謝 在線預覽地址&#xff1a;Intr…

leetcode面試經典150題——31 無重復字符的最長子串(方法二極簡代碼!!!)

題目&#xff1a; 無重復字符的最長子串 描述&#xff1a; 給定一個字符串 s &#xff0c;請你找出其中不含有重復字符的 最長子串 的長度。 示例 1: 輸入: s “abcabcbb” 輸出: 3 解釋: 因為無重復字符的最長子串是 “abc”&#xff0c;所以其長度為 3。 leetcode鏈接 方法…

【LeetCode刷題筆記】DFSBFS(三)

圖的基礎知識 鄰接矩陣是一個二維表,其中橫縱坐標交叉的格子值為 1 的表示這兩個頂點是連通的,否則是不連通的。

Python-csv庫進行數據保存和讀寫

在 Python 中使用 CSV 文件非常簡單&#xff0c;Python 提供了內置的 csv 模塊來處理 CSV 文件。你可以使用 csv 模塊來讀取、寫入和操作 CSV 文件中的數據。 基礎使用 讀取 CSV 文件 python import csv# 打開 CSV 文件進行讀取 with open(file.csv, moder) as file:reader …

NVM得介紹和詳細使用教程

NVM???????&#xff08;Node Version Manager&#xff09;是一個用于管理多個Node.js版本的工具。它允許您在同一臺計算機上輕松地切換和管理不同的Node.js版本。以下是NVM的介紹和詳細使用教程&#xff1a; 安裝NVM&#xff1a; 首先&#xff0c;您需要在計算機上安裝N…

C#串口通信從入門到精通(27)——高速通信下解決數據處理慢的問題(20ms以內)

前言 我們在開發串口通信程序時,有時候會遇到比如單片機或者傳感器發送的數據速度特別快,比如10ms、20ms發送一次,并且每次發送的數據量還比較大,如果按照常規的寫法,我們會發現接收的數據還沒處理完,新的數據又發送過來了,這就會導致處理數據滯后,軟件始終處理的不是…

python樹的雙親存儲結構

這種存儲結構是一種順序存儲結構&#xff0c;采用元素形如“[結點值&#xff0c;雙親結點索引]”的列表表示。通常每個結點有唯一的索引(或者偽地址&#xff09;,根結點的索引為0&#xff0c;它沒有雙親結點&#xff0c;其雙親結點的索引為-1。例如&#xff0c;所示的樹對應的雙…

123. 股票買賣的最佳時機III(2次交易)

題目 題解 class Solution:def maxProfit(self, prices: List[int]) -> int:N len(prices)# 狀態定義 dp[i][j][k]代表在第i天&#xff0c;被允許完成j次交易時&#xff0c;持有或者不持有的最大利潤。k0代表不持有&#xff0c;k1代表持有dp [[[0 for k in range(2)] for…

醫學生秋招攻略,面試時一定要注意這些方面!

醫學生別拖了&#xff0c;今年秋招已經過去一波熱度了&#xff0c;趕早不趕晚&#xff01;在籌備第二輪秋招以及明年的春招的醫學生一定要注意以下事項。 1.清晰目標 搜集秋招訊息 一定要早點多做準備&#xff0c;想清楚未來的目標&#xff0c;是繼續深造還是就業做醫生或者是…

FileReader與URL.createObjectURL實現圖片、視頻上傳預覽

之前做圖片、視頻上傳預覽常用的方案是先把文件上傳到服務器&#xff0c;等服務器返回文件的地址后&#xff0c;再把該地址字符串賦給img或video的src屬性&#xff0c;這才實現所謂的文件預覽。實際上這只是文件“上傳后再預覽”&#xff0c;這既浪費了用戶的時間&#xff0c;也…

java開發合同相關

【點我-這里送書】 本人詳解 作者:王文峰,參加過 CSDN 2020年度博客之星,《Java王大師王天師》 公眾號:JAVA開發王大師,專注于天道酬勤的 Java 開發問題中國國學、傳統文化和代碼愛好者的程序人生,期待你的關注和支持!本人外號:神秘小峯 山峯 轉載說明:務必注明來源(…

集合的分類

Python內建的集合類&#xff0c;有有序和無序之分&#xff0c;還有可修改和不可修改之分。 1 有序和無序 有序是說某數據集合中的每個元素都有一個位置信息&#xff0c;通常用index表示&#xff0c;可以借助這種集合類型名和位置信息訪問集合里的某元素值&#xff0c;在Pytho…

【開源】基于Vue.js的用戶畫像活動推薦系統

項目編號&#xff1a; S 061 &#xff0c;文末獲取源碼。 \color{red}{項目編號&#xff1a;S061&#xff0c;文末獲取源碼。} 項目編號&#xff1a;S061&#xff0c;文末獲取源碼。 目錄 一、摘要1.1 項目介紹1.2 項目錄屏 二、功能模塊2.1 數據中心模塊2.2 興趣標簽模塊2.3 活…

[Android]使用Git將項目提交到GitHub

如果你的Mac還沒有安裝Git&#xff0c;你可以通過Homebrew來安裝它&#xff1a; brew install git 方式一&#xff1a;終端管理 1.創建本地Git倉庫 在項目的根目錄下&#xff0c;打開終端&#xff08;Terminal&#xff09;并執行以下命令來初始化一個新的Git倉庫&#xff1…

vue3-組件傳參及計算屬性

?&#x1f308;個人主頁&#xff1a;前端青山 &#x1f525;系列專欄&#xff1a;Vue篇 &#x1f516;人終將被年少不可得之物困其一生 依舊青山,本期給大家帶來vue篇專欄內容:vue3-組件傳參及計算屬性 目錄 vue3中的組件傳參 1、父傳子 2、子傳父 toRef 與 toRefs vue3中…

數據結構 查找基本概念

敬請期待。。。 1. 適用于折半查找的表的存儲方式及元素排列要求為&#xff08;順序方式存儲&#xff0c;元素有序 &#xff09;。 2. 有一個按元素值排好序的順序表(長度大于2)&#xff0c;分別用順序查找和折半查找與給定值相等的元素&#xff0c;比較次數分別是s和b&am…

拼接合并yuv序列轉成mp4

ffmpeg需要用支持libx264的版本&#xff0c;如果需要&#xff0c;可以從這個網站下載編譯支持libx264\x265的ffmpeg https://www.gyan.dev/ffmpeg/builds/packages/ffmpeg-6.1-essentials_build.7z #-*- coding:utf-8-*- import osif __name__ "__main__":# 1 輸入…

實例講解:在3dMax中如何使用python腳本?

如果你是Python或Maxscript的新手&#xff0c;你現在可以跟著這篇文章開始做一些代碼了&#xff0c;本文將讓我們從非常基本的東西開始學習。 如何在3dmax中獲取選定的節點并打印出它們的名稱&#xff1f;所有場景對象如何&#xff1f;我們直接看代碼&#xff1a; import MaxP…

Word/PPT/PDF怎么免費轉為JPG圖片?

1、打開金鳴表格文字識別網站。 2、點擊導航條上的“軟件下載” 3、安裝并打開金鳴表格文字識別軟件。 4、點擊頂部導航欄的“文件轉圖片”。 5、選擇需要轉換成圖片的文件&#xff08;支持Word/PPT/PDF&#xff09;. 6、點“打開”程序將自動分頁轉換為圖片。