力扣熱題100——普通數組(不普通)

普通數組但一點不普通!

  • 最大子數組和
  • 合并區間
  • 輪轉數組
  • 除自身以外數組的乘積
  • 缺失的第一個正數

最大子數組和

在這里插入圖片描述
在這里插入圖片描述

這道題是非常經典的適用動態規劃解決題目,但同時這里給出兩種解法
動態規劃分治法
那么動態規劃方法大家可以在我的另外一篇博客總結中看到,因此直接給出代碼,著重講第二道題

動態規劃:

//使用動態規劃方法
class Solution {
public:int ans = INT_MIN;//動態規劃方法:令A[i]表示以i結尾的連續子數組的和int maxSubArray(vector<int>& nums) {int n = nums.size();int A[n];for(int i = 0;i<n;i++){if(!i){A[0] = nums[0];ans = nums[0];continue;}A[i] = max(A[i-1]+nums[i],nums[i]);ans = max(A[i],ans);}return ans;}
};

使用分治法
分治法就可以片面的理解為遞歸 若只是應對公司的筆試 不必分的那么清 咱又不寫教科書:
分治算法的基本思想是將一個規模為N的問題分解為K個規模較小的子問題,這些子問題相互獨立且與原問題性質相同。求出子問題的解,就可得到原問題的解。
1.我們來定義get(a,l,r)表示查詢a序列 [l,r] 區間內的最大子段和,那么最終的答案就是get(nums,0,num.size()-1)。則實現分治法應該將區間進行劃分:
對于一個區間[l,r],取m = [(l+r)/2],對區間[l,m]和[m+1,r]分治分解。當遞歸逐層深入直到區間長度縮小為1的時候,遞歸開始回升。
2. 對于一個區間[l,r] 我們可以維護四個量:
lSum表示[l,r]內以l為左端點的最大子段和;
rSum表示[l,r]內以r為右端點的最大子段和
msum表示[l,r]內的最大子段和
iSum表示[l,r]的區間和
以下簡稱[l,m]為[l,r]的左子區間,[m+1,r]為[l,r]的右子區間。且對于長度為1的區間[i,j],四個量的值都和nums[i]相等。

對于長度為1的區間:

  • 首先最好維護的是isum,區間[l,r]的iSum就等于[左子區間]的iSum加上[右子區間]的iSum。
  • 對于[l,r]的lSum,存在兩種可能,要么等于左子區間的lSum,要么等于左子區間的iSum加上右子區間的lSum,二者取大。
  • 對于[l,r]的rSum,同理,要么等于右子區間的rSum,要么等于右子區間的iSum加上左子區間的rSum,二者取大。
  • 當計算好上面的三個量之后,就很好計算[l,r]的mSum了。可以考慮[l,r]的mSum對應的區間是否跨越m——它可能不跨越m,,也就是[l,r]的mSum可能是左子區間的mSum和右子區間的mSum中的一個;它也可能跨越m,可能是左子區間的rSum和右子區間的lSum求和。三者取大。
    下面給出代碼:
class Solution{
public:struct Status{int lSum,rSum,mSum,iSum;};Status pushUp(Status l,Status r){int iSum = l.iSum + r.iSum;int lSum = max(l.lSum,l.iSum + r.lSum);int rSum = max(r.rSum,r.iSum+l.rSum);int mSum = max(max(l.mSum,r.mSum),l.rSum+r.lSum);return (Status) {lSum,rSum,mSum,iSum};};Status get(vector<int> &a,int l,int r){if(l==r){return (Status) {a[l],a[l],a[l],a[l]};}int m = (l+r)/2;Status lSub = get(a,l,m);Status rSub = get(a,m+1,r);return pushUp(lSub,rSub);}int maxSubArray(vector<int>& nums){return get(nums,0,nums.size()-1).mSum;}
};

合并區間

在這里插入圖片描述
在這里插入圖片描述

這道題的解題思路就是先將intervals內的區間按照左端點進行排序,再定義一個新的vector<vector<int>>數組merged,且如果下一個遍歷到的區間的左端點如果比 比merged最后一個區間的右端點還要大,則兩個區間就沒有交集了,否則就將merged最后一個區間的右端點設置為merged最后一個區間的右端點與intervals中的當前區間中右端點這兩者之間的最大值,以此循環即可。最后得到的merged數組便是最終的結果 。

下面給出代碼:

class Solution{
public:vector<vector<int>> merge(vector<vector<int>>& intervals){if(intervals.size()==0) return {};//這里默認排序是左端點遞增 左端點相同的話則按照右端點遞增的順序進行排序sort(intervals.begin(),intervals.end());vector<vector<int>> merged;for(int i=0;i<intervals.size();i++){int L = intervals[i][0], R = intervals[i][1];if(!merged.size()||merged.back()[1]<L){merged.push_back({L,R});}else{merged.back()[1] = max(merged.back()[1],R);}}return merged;}
}

輪轉數組

在這里插入圖片描述
在這里插入圖片描述

這里給出使用額外數組和翻轉數組的兩種方法


1.使用額外數組與原數組元素的位置對應關系為:原數組下標為i的元素放至新數組下標為(i+k)%n的位置
下面給出代碼:

class Solution{
public:void rotate(vector<int>& nums,int k){int n=nums.size();vector<int> newArr(n);//定義動態數組for(int i=0;i<n;i++){newArr[(i+k)%n] = nums[i];}nums.assign(newArr.begin(),newArr.end());//assign是STL的成員函數,用于替換容器中的元素,指定容器中的元素為新內容}
}

2.翻轉數組:將原數組的末尾元素放至在數組的頭部等價于是將整個數組進行翻轉,然后將前[0,k-1]個元素翻轉,再將[k,n-1]的元素進行翻轉,示例如下:
在這里插入圖片描述
下面給出代碼:

class Solution{
public:void reverse(vector<int>& nums,int start,int end){swap(nums[start],nums[end]);start++;end--;}void rotate(vector<int>& nums,int k){k %= nums.size();reverse(nums,0,nums.size()-1);reverse(nums,0,(k-1));reverse(nums,k,nums.size()-1);}
}

除自身以外數組的乘積

在這里插入圖片描述
在這里插入圖片描述

這道題按照你以為的常規的方法做會超時,筆者已經試過了類似下面這樣吧

        // int n = nums.size();// vector<int> answer(n);// for(int i=0;i<n;i++){//     int res=1;//     for(int j=0;j<n;j++){//         if(i!=j){//             res *=nums[j];//         }//     }//     answer[i] = res;// }// return answer;

這道題跟PAT算法題的"幾個PTA"這道例題很像,這里應該采用活用遞推的方法求解,即根據當前位置的數值應該是左邊的乘積乘以右邊數的乘積,對左右兩邊乘積可以用兩個數組存放
于是有了下面的做法

class Solution{
public:vector<int> productExcepSelf(vector<int>& nums){int n = nums.size();vector<int> answer(n);vector<int> L(n,0),R(n,0); //L,R代表左右兩側的乘積列表L[0] = 1;//索引為‘0’的元素,因為左側沒有元素 因此L[0] = 1;for(int i = 1;i<n;i++){L[i] = nums[i-1]*L[i-1];}R[n-1]=1;//最后一個元素的右側沒有元素 for(int i=n-2;i>=0;i--){R[i] = nums[i+1]*R[i+1];}//以上便定義好了兩個列表//對于索引i,除nums[i]之外其余各元素的乘積就是左側所有元素的乘積乘以右側所有元素的乘積for(int i=0;i<n;i++){answer[i] = L[i]*R[i];}return answer;}
}

此處為了降低空間的復雜度 先試用answer數組作為左側乘積的列表,answer[i]代表的是i左側乘積的列表。 不構造R數組,用一個遍歷跟蹤右側乘積并更新數組answer[i] = answer[i] * R,然后更新R = R*nums[i],其中變量R表示的就是索引右側數字的乘積。

class Solution {
public:vector<int> productExceptSelf(vector<int>& nums) {int length = nums.size();vector<int> answer(length);// answer[i] 表示索引 i 左側所有元素的乘積// 因為索引為 '0' 的元素左側沒有元素, 所以 answer[0] = 1answer[0] = 1;for (int i = 1; i < length; i++) {answer[i] = nums[i - 1] * answer[i - 1];}// R 為右側所有元素的乘積// 剛開始右邊沒有元素,所以 R = 1int R = 1;for (int i = length - 1; i >= 0; i--) {// 對于索引 i,左邊的乘積為 answer[i],右邊的乘積為 Ranswer[i] = answer[i] * R;// R 需要包含右邊所有的乘積,所以計算下一個結果時需要將當前值乘到 R 上R *= nums[i];}return answer;}
};

缺失的第一個正數

在這里插入圖片描述
在這里插入圖片描述

這道題直接秒了:
先看我的做法:

class Solution {
public:int firstMissingPositive(vector<int>& nums) {sort(nums.begin(),nums.end());int j=1;for(int i =0;i<nums.size();i++){if(j==nums[i]) j++;if(j<nums[i]) return j;}return j;}
};

下面還是給一個更加規范的做法:
對于一個長度為 N 的數組,其中沒有出現的最小正整數只能在 [1,N+1] 中。這是因為如果 [1,N] 都出現了,那么答案是 N+1,否則答案是 [1,N] 中沒有出現的最小正整數。這樣一來,我們將所有在 [1,N] 范圍內的數放入哈希表,也可以得到最終的答案。而給定的數組恰好長度為 N,這讓我們有了一種將數組設計成哈希表的思路:
對數組進行遍歷,對于遍歷到的數x,如果它在[1,N]的范圍內,那么就將數組中的第x-1個位置打上[標記](數組下標從0開始)。在遍歷結束之后,如果所有的位置都被打上了標記,那么答案是N+1,否則答案是最小的沒有打上標記的位置+1。
但問題是應該如何標記 考慮到不在1-N內的話 就是N+1;則考慮將所有非整數都變為N+1;然后遍歷數組中的每一個數x,他可能已經被打了標記,因此原本對應的數為|x|,其中| |為絕對值符號。如果|x|在[1,N],那么我們給數組中的第|x|-1個位置的數添加一個負號。
在這里插入圖片描述

class Solution {
public:int firstMissingPositive(vector<int>& nums) {int n = nums.size();for (int& num: nums) {if (num <= 0) {num = n + 1;}}for (int i = 0; i < n; ++i) {int num = abs(nums[i]);if (num <= n) {nums[num - 1] = -abs(nums[num - 1]);}}for (int i = 0; i < n; ++i) {if (nums[i] > 0) {return i + 1;}}return n + 1;}
};

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

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

相關文章

矩陣基礎+矩陣轉置+矩陣乘法+行列式與逆矩陣

GPU渲染過程 矩陣 什么是矩陣&#xff08;Matrix&#xff09; 向量 &#xff08;3&#xff0c;9&#xff0c;88&#xff09; 點乘&#xff1a;計算向量夾角 叉乘&#xff1a;計算兩個向量構成平面的法向量。 矩陣 矩陣有3行&#xff0c;2列&#xff0c;所以表示為M32 獲取固…

MySQL之text字段詳細分類說明

在 MySQL 中&#xff0c;TEXT 是用來存儲大量文本數據的數據類型。TEXT 類型可以存儲非常長的字符串&#xff0c;比 VARCHAR 類型更適合存儲大塊的文本數據。TEXT 數據類型分為以下幾個子類型&#xff0c;每個子類型用于存儲不同大小范圍的文本數據&#xff1a; TINYTEXT: 可以…

超詳細!Android 面試題大匯總與深度解析

一、Java 與 Kotlin 基礎 1. Java 的多態是如何實現的&#xff1f; 多態是指在 Java 中&#xff0c;同一個行為具有多個不同表現形式或形態的能力。它主要通過方法重載&#xff08;Overloading&#xff09;和方法重寫&#xff08;Overriding&#xff09;來實現。 方法重載&a…

如何提高webrtc操作跟手時間,降低延遲

第一次做webrtc項目&#xff0c;操作延遲&#xff0c;一直是個問題&#xff0c;多次調試都不能達到理想效果。偶爾發現提高jitterBuffer時間可以解決此問題。關鍵代碼 const _setJitter (values: number) > { const receives peerConnection.getReceivers();receives.f…

語音合成(TTS)從零搭建一個完整的TTS系統-第一節-效果演示

一、概述 語音合成又叫文字轉語音&#xff08;TTS-text to speech &#xff09;&#xff0c;本專題我們記錄從零搭建一個完整的語音合成系統&#xff0c;包括文本前端、聲學模型和聲碼器&#xff0c;從模型訓練到系統的工程化實現&#xff0c;模型可以部署在手機等嵌入式設備上…

實驗三 I/O地址譯碼

一、實驗目的 掌握I/O地址譯碼電路的工作原理。 二、實驗電路 實驗電路如圖1所示&#xff0c;其中74LS74為D觸發器&#xff0c;可直接使用實驗臺上數字電路實驗區的D觸發器&#xff0c;74LS138為地址譯碼器&#xff0c; Y0&#xff1a;280H&#xff5e;287H&…

Linux 使用Nginx搭建簡易網站模塊

網站需求&#xff1a; 一、基于域名[www.openlab.com](http://www.openlab.com)可以訪問網站內容為 welcome to openlab ? 二、給該公司創建三個子界面分別顯示學生信息&#xff0c;教學資料和繳費網站&#xff0c;基于[www.openlab.com/student](http://www.openlab.com/stud…

MyBatis 如何使用

1. 環境準備 添加依賴&#xff08;Maven&#xff09; 在 pom.xml 中添加 MyBatis 和數據庫驅動依賴&#xff1a; <dependencies><!-- MyBatis 核心庫 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId&g…

ArkTS組件的三個通用(通用事件、通用屬性、通用手勢)

文章目錄 通用事件點擊事件 onClick觸摸事件 onTouch掛載、卸載事件拖拽事件按鍵事件 onKeyEvent焦點事件鼠標事件懸浮事件組件區域變化事件 onAreaChange組件尺寸變化事件組件可見區域變化事件組件快捷鍵事件自定義事件分發自定義事件攔截 通用屬性尺寸設置位置設置布局約束邊…

智慧城市像一張無形大網,如何緊密連接你我他?

智慧城市作為復雜巨系統&#xff0c;其核心在于通過技術創新構建無縫連接的網絡&#xff0c;使物理空間與數字空間深度融合。這張"無形大網"由物聯網感知層、城市數據中臺、人工智能中樞、數字服務入口和安全信任機制五大支柱編織而成&#xff0c;正在重塑城市運行規…

【python】django sqlite版本過低怎么辦

方法一&#xff1a;下載最新版本 復制上面的內容的鏈接 在服務器上進行操作 wget https://sqlite.org/2025/sqlite-autoconf-3490100.tar.gz tar -zxvf sqlite-autoconf-3490100.tar.gz cd sqlite-autoconf-3490100 ./configure --prefix/usr/local make && make in…

PyTorch - Tensor 學習筆記

上層鏈接&#xff1a;PyTorch 學習筆記-CSDN博客 Tensor 初始化Tensor import torch import numpy as np# 1、直接從數據創建張量。數據類型是自動推斷的 data [[1, 2],[3, 4]] x_data torch.tensor(data)torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])輸出&am…

【技術派后端篇】ElasticSearch 實戰指南:環境搭建、API 操作與集成實踐

1 ES介紹及基本概念 ElasticSearch是一個基于Lucene 的分布式、高擴展、高實時的基于RESTful 風格API的搜索與數據分析引擎。 RESTful 風格API的特點&#xff1a; 接受HTTP協議的請求&#xff0c;返回HTTP響應&#xff1b;請求的參數是JSON&#xff0c;返回響應的內容也是JSON…

從標準九九表打印解讀單行表達式的書寫修煉(Python)

解讀單行表達式書寫&#xff0c;了解修習單行捷徑。 筆記模板由python腳本于2025-04-16 23:24:17創建&#xff0c;本篇筆記適合喜歡單行喜好python的coder翻閱。 【學習的細節是歡悅的歷程】 博客的核心價值&#xff1a;在于輸出思考與經驗&#xff0c;而不僅僅是知識的簡單復述…

深入解析布爾注入:原理、實戰與防御

目錄 一、布爾注入的原理與核心邏輯 二、布爾注入的實戰步驟 三、關鍵函數與繞過技巧 四、實戰案例&#xff1a;獲取數據庫名稱 五、防御策略與最佳實踐 六、總結 一、布爾注入的原理與核心邏輯 布爾注入&#xff08;Boolean-Based Blind SQL Injection&#xff09;是一種…

OpenGL學習筆記(幾何著色器、實例化、抗鋸齒)

目錄 幾何著色器爆破物體法向量可視化 實例化&#xff08;偏移量存在uniform中&#xff09;實例化數組&#xff08;偏移量存在頂點屬性中&#xff09;小行星帶 抗鋸齒SSAA&#xff08;Super Sample Anti-aliasing&#xff09;MSAA&#xff08;Multi-Sampling Anti-aliasing&…

idea報錯java: 非法字符: ‘\ufeff‘解決方案

解決方案步驟以及說明 BOM是什么&#xff1f;1. BOM的作用2. 為什么會出現 \ufeff 錯誤&#xff1f;3. 如何解決 \ufeff 問題&#xff1f; 最后重新編譯&#xff0c;即可運行&#xff01;&#xff01;&#xff01; BOM是什么&#xff1f; \ufeff 是 Unicode 中的 BOM&#xff0…

open webui 介紹 是一個可擴展、功能豐富且用戶友好的本地部署 AI 平臺,支持完全離線運行。

AI MCP 系列 AgentGPT-01-入門介紹 Browser-use 是連接你的AI代理與瀏覽器的最簡單方式 AI MCP(大模型上下文)-01-入門介紹 AI MCP(大模型上下文)-02-awesome-mcp-servers 精選的 MCP 服務器 AI MCP(大模型上下文)-03-open webui 介紹 是一個可擴展、功能豐富且用戶友好的…

Log4j2遠程命令執行(CVE-2021-44228)復現

這里選擇使用vulfocue的靶場來進行復現 描述: Apache Log4j2 是一個基于 Java 的日志記錄工具。該工具重寫了 Log4j 框架&#xff0c;并且引入了大量豐富的特性。該日志框架被大量用于業務系統開發&#xff0c;用來記錄日志信息。 在大多數情況下&#xff0c;開發者可能會將用…

模型提示詞

一 提示詞 &#xff08;一&#xff09; 提示詞&#xff08;Prompt&#xff09;是用戶發送給大語言模型的問題、指令或請求&#xff0c;** 1 來明確地告訴模型用戶想要解決的問題或完成的任務&#xff0c;是大語言模型理解用戶需求并據此生成相關、準確回答或內容的基礎。對于…