日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

day 2 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

發(fā)布時(shí)間:2024/5/14 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 day 2 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

學(xué)習(xí)鏈接

題目鏈接:

https://leetcode.cn/problems/squares-of-a-sorted-array/

https://leetcode.cn/problems/minimum-size-subarray-sum/

https://leetcode.cn/problems/spiral-matrix-ii/

文章鏈接:

https://programmercarl.com/0977.%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E7%9A%84%E5%B9%B3%E6%96%B9.html

https://programmercarl.com/0209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.html

https://programmercarl.com/0059.%E8%9E%BA%E6%97%8B%E7%9F%A9%E9%98%B5II.html

視頻鏈接:

https://www.bilibili.com/video/BV1QB4y1D7ep

https://www.bilibili.com/video/BV1tZ4y1q7XE

https://www.bilibili.com/video/BV1SL4y1N7mV/

第一想法

有序數(shù)組的平方

題目給出一個(gè)非遞減的整數(shù)型數(shù)組(可能包含負(fù)數(shù)),需要返回一個(gè)非遞減且原數(shù)組經(jīng)過平方之后的新數(shù)組。要求時(shí)間復(fù)雜度為O(n)。

初步想法:將數(shù)組中每個(gè)值平方得到一個(gè)新的數(shù)組,之后對(duì)數(shù)組進(jìn)行排序。

思考二:由于沒有內(nèi)存的限制,可以利用一個(gè)輔助數(shù)組。先對(duì)原數(shù)組中每個(gè)元素平方,同時(shí)將其排序后插入到新數(shù)組。

思考三:先對(duì)原數(shù)組中的值取絕對(duì)值,進(jìn)行一個(gè)非遞減排序后,再挨個(gè)平方組成新的數(shù)組。

長(zhǎng)度最小的子數(shù)組

這個(gè)問題一看就有點(diǎn)難。

思路一:暴力求解,相當(dāng)于雙指針求解。直接兩層for循環(huán),遍歷的找。第一層for循環(huán)決定起點(diǎn),第二層for循環(huán)看加到第幾個(gè)數(shù)。如果加起來超過了目標(biāo)值,則退出。如果沒超過目標(biāo)值,就往后移。等于目標(biāo)值的時(shí)候,記錄長(zhǎng)度。用一個(gè)變量來記錄最小長(zhǎng)度。

思路二:首先一個(gè)一個(gè)的看,是否有對(duì)應(yīng)的目標(biāo)值。之后兩個(gè)塊一起看,是否有滿足的序列,有則返回序列長(zhǎng)度,沒有則三個(gè)快一起看。兩個(gè)快可以用i 和i+1 ,這樣來表示。不知道這是不是滑動(dòng)窗口。

螺旋矩陣II

看完代碼隨想錄之后的想法

有序數(shù)組的平方

題目:給你一個(gè)按?非遞減順序?排序的整數(shù)數(shù)組?nums,返回?每個(gè)數(shù)字的平方?組成的新數(shù)組,要求也按?非遞減順序?排序。

最初實(shí)現(xiàn):

部分結(jié)果正確,但是提交會(huì)出現(xiàn)超時(shí)問題。排序算法可以優(yōu)化一下

class Solution { public:vector<int> sortedSquares(vector<int>& nums) {int length = nums.size();int middle;for(int i = 0; i < length; i++){nums[i] = nums[i] * nums[i]; }for(int j = 0; j < length; j++){for(int k = 0; k < length-1; k++){if(nums[k] > nums[k + 1]){middle = nums[k];nums[k] = nums[k + 1];nums[k + 1] = middle;}}}return nums;} };#優(yōu)化后的代碼: #(1)暴力破解法 時(shí)間復(fù)雜度是 O(n + nlogn) class Solution { public:vector<int> sortedSquares(vector<int>& nums) {for(int i = 0; i < nums.size(); i++){nums[i] *= nums[i];}sort(nums.begin(),nums.end()); //快速排序return nums;} };

利用雙指針法,兩個(gè)指針i和j,分別指向起始和結(jié)束位置,依次從數(shù)組兩端挑選最大的數(shù)。放到一個(gè)新的數(shù)組中,新數(shù)組的指針指向終止位置,以此從后往前填充。斯巴拉西。

雙指針法真好用。

#依照雙指針?biāo)悸穼懙拇a 時(shí)間復(fù)雜度為O(n) class Solution { public:vector<int> sortedSquares(vector<int>& nums) {int length = nums.size()-1;int j = length;int i = 0;vector<int> result(nums.size(), 0);while(i <= j){int double_i = nums[i] * nums[i];int double_j = nums[j] * nums[j];if(double_i > double_j){result[length--] = double_i;i++;}else{result[length--] = double_j;j--;}}return result;} };

需要注意的點(diǎn)包括:雙指針?biāo)悸?#xff0c;vector 變量定義。(C++ 還是不熟,得加快學(xué)習(xí)速度)。

長(zhǎng)度最小的子數(shù)組

題目:

給定一個(gè)含有?n?****個(gè)正整數(shù)的數(shù)組和一個(gè)正整數(shù)?target?

找出該數(shù)組中滿足其和?****≥ target?**的長(zhǎng)度最小的?連續(xù)子數(shù)組?[numsl, numsl+1, ..., numsr-1, numsr]?,并返回其長(zhǎng)度。**如果不存在符合條件的子數(shù)組,返回?0?。

自己思路:

1)暴力解法—先兩個(gè)兩個(gè)加起來看超不超過,兩個(gè)沒有超過的,那就三個(gè)連續(xù)的加起來。可能會(huì)有多個(gè)符合的,但是只需要返回長(zhǎng)度,所以找到一個(gè)就行。有從小到大長(zhǎng)度去試和從大到小去試兩種思路。

2)暴力解法2:用兩個(gè)變量指示窗口,i,j。然后兩層for循環(huán)。

初始代碼:

顯示超過了時(shí)間限制,也不知道有沒有bug。(有的,當(dāng)不滿足,返回0)

class Solution { public:int minSubArrayLen(int target, vector<int>& nums) {int length = nums.size() - 1;int min = 1;int sum = 0;while(sum < target){for(int i = 0; i <= length; i++){int sum = 0;for(i = 0; i < min; i++){sum += nums[i];}if(sum >= target){break;}else{min++;}}}return min;} };#兩層for循環(huán),暴力解法 class Solution { public:int minSubArrayLen(int s, vector<int>& nums) {int result = INT32_MAX; // 最終的結(jié)果int sum = 0; // 子序列的數(shù)值之和int subLength = 0; // 子序列的長(zhǎng)度for (int i = 0; i < nums.size(); i++) { // 設(shè)置子序列起點(diǎn)為isum = 0;for (int j = i; j < nums.size(); j++) { // 設(shè)置子序列終止位置為jsum += nums[j];if (sum >= s) { // 一旦發(fā)現(xiàn)子序列和超過了s,更新resultsubLength = j - i + 1; // 取子序列的長(zhǎng)度result = result < subLength ? result : subLength;break; // 因?yàn)槲覀兪钦曳蠗l件最短的子序列,所以一旦符合條件就break}}}// 如果result沒有被賦值的話,就返回0,說明沒有符合條件的子序列return result == INT32_MAX ? 0 : result;} };

滑動(dòng)窗口:不斷調(diào)節(jié)子序列的起始位置和終止位置,從而得出我們想要的結(jié)果。

只用一個(gè)for循環(huán),應(yīng)該表示的是遍歷的終止位置。

我之前自己思考從大往小去找的思路跟這個(gè)很像。

窗口就是 滿足其和 ≥ s 的長(zhǎng)度最小的 連續(xù) 子數(shù)組。

窗口的起始位置如何移動(dòng):如果當(dāng)前窗口的值大于s了,窗口就要向前移動(dòng)了(也就是該縮小了)。

窗口的結(jié)束位置如何移動(dòng):窗口的結(jié)束位置就是遍歷數(shù)組的指針,也就是for循環(huán)里的索引。

牛逼!

class Solution { public:int minSubArrayLen(int target, vector<int>& nums) {int result = INT32_MAX;int sum = 0; //滑動(dòng)窗口中總數(shù)之和int i = 0; //滑動(dòng)窗口起始位置int sublength = 0; //滑動(dòng)窗口的長(zhǎng)度for(int j = 0; j < nums.size(); j++){sum += nums[j]; // 注意這里使用while,每次更新 i(起始位置),并不斷比較子序列是否符合條件while(sum >= target){sublength = (j - i + 1); // 取子序列的長(zhǎng)度result = result > sublength? sublength : result;sum -= nums[i++]; // 這里體現(xiàn)出滑動(dòng)窗口的精髓之處,不斷變更i(子序列的起始位置)}} // 如果result沒有被賦值的話,就返回0,說明沒有符合條件的子序列return result == INT32_MAX? 0 : result;} };
  • 時(shí)間復(fù)雜度:O(n)
  • 空間復(fù)雜度:O(1)

時(shí)間復(fù)雜度主要是看每一個(gè)元素被操作的次數(shù),每個(gè)元素在滑動(dòng)窗后進(jìn)來操作一次,出去操作一次,每個(gè)元素都是被操作兩次,所以時(shí)間復(fù)雜度是 2 × n 也就是O(n)。

螺旋矩陣II

給你一個(gè)正整數(shù)?n?,生成一個(gè)包含?1?到?n2?所有元素,且元素按順時(shí)針順序螺旋排列的?n x n?正方形矩陣?matrix?。

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-qstntN6u-1685171525400)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/1cb7305b-78a9-40f9-91bf-e052b105fa22/Untitled.png)]

自己思路:首先,生成1-n平方的所有元素,不難。關(guān)于排序,最初想法是找規(guī)律。但是針對(duì)奇偶數(shù),不同排的情況各不一樣,應(yīng)該不能這樣做。想了十分鐘,沒有思路,直接看解析。

代碼隨想錄思路:本題并不涉及到什么算法,就是模擬過程,但卻十分考察對(duì)代碼的掌控能力。一定要堅(jiān)持循環(huán)不變量原則

模擬順時(shí)針畫矩陣的過程:

  • 填充上行從左到右
  • 填充右列從上到下
  • 填充下行從右到左
  • 填充左列從下到上

由外向內(nèi)一圈一圈這么畫下去。

class Solution { public:vector<vector<int>> generateMatrix(int n) {vector<vector<int>> res(n, vector<int>(n,0)); // 使用vector定義一個(gè)二維數(shù)組int startx = 0, starty = 0; // 定義每循環(huán)一個(gè)圈的起始位置int loop = n / 2; // 每個(gè)圈循環(huán)幾次,例如n為奇數(shù)3,那么loop = 1 只是循環(huán)一圈,矩陣中間的值需要單獨(dú)處理int mid = n / 2; // 矩陣中間的位置,例如:n為3, 中間的位置就是(1,1),n為5,中間位置為(2, 2)int count = 1; // 用來給矩陣中每一個(gè)空格賦值int offset = 1; // 需要控制每一條邊遍歷的長(zhǎng)度,每次循環(huán)右邊界收縮一位int i, j;while(loop--){i = startx;j = starty;// 下面開始的四個(gè)for就是模擬轉(zhuǎn)了一圈// 模擬填充上行從左到右(左閉右開)for(j = starty; j < n -offset; j++){res[startx][j] = count++;}// 模擬填充右列從上到下(左閉右開)for(i = startx; i < n - offset; i++){res[i][j] = count++;}// 模擬填充下行從右到左(左閉右開)for(; j > starty; j--){res[i][j] = count++;}// 模擬填充左列從下到上(左閉右開)for(; i > startx; i--){res[i][j] = count++;} // 第二圈開始的時(shí)候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)startx++;starty++;offset += 1; // offset 控制每一圈里每一條邊遍歷的長(zhǎng)度}// 如果n為奇數(shù)的話,需要單獨(dú)給矩陣最中間的位置賦值if (n % 2 ){res[mid][mid] = count;}return res;}};
  • 時(shí)間復(fù)雜度 O(n^2): 模擬遍歷二維矩陣的時(shí)間
  • 空間復(fù)雜度 O(1)

這種模擬題得找到它的規(guī)律去做,我剛開始想得找每一行的規(guī)律,但這樣太復(fù)雜了。還要各種判斷,題目給出了順時(shí)針賦值,但是有很多圈。要想辦法找到能夠重復(fù)的模板,比如如何賦值一圈。

今日收獲

1、sort函數(shù)的排序方法類似于快排方法僅適用于普通數(shù)組和部分類型的容器,時(shí)間復(fù)雜度為n*log2(n)

sort(起始地址,結(jié)束地址,比較器); 其中比較器可以省略,默認(rèn)升序

**對(duì)vector排序:**sort(vec.begin(),vec.end())

其中vec.begin()返回的是一個(gè)迭代器,該迭代器指向vec的起始元素。

2、滑動(dòng)窗口

3、模擬題

總結(jié)

以上是生活随笔為你收集整理的day 2 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。