代碼隨想錄算法訓練營|第二天|977.有序數組的平方、209.長度最小的子數組、59.螺旋矩陣II。刷题心得(c++)

目录

讀題

977.有序数组的平方

自己看到题目的第一想法

209.长度最小的子数组

自己看到题目的第一想法

59.螺旋矩阵II

自己看到题目的第一想法

看完代码随想录之后的想法

實作

977.有序数组的平方

思路

Code

209.长度最小的子数组

思路

Code

59.螺旋矩阵II

思路

Code

總結

自己实现过程中遇到哪些困难

977.有序数组的平方

209.长度最小的子数组

59.螺旋矩阵II

今日收获,

總結: 數組


讀題

977.有序数组的平方

自己看到题目的第一想法

用雙指針想法的話,概念很快想出來,就是左右指針平方後比大小,大的依序放在新陣列的最後並更改指針的位置,

但自己想了一下想用in-place的方式進行,原本思路如下

  1. 使用雙指針的方式,因為左右指針所指到的數,逐步往中間前進,越往中間值越小
  2. 利用左右指針比大小,右指針大於左指針,如果不符合,則將左指針的值換到右指針
  3. 右指針持續往左指針走,左指針固定在0.

但後續完全沒有想到如果數組全部都是負數的狀況,所以還是出現了錯誤

並且因為是平方的關係,有去思考到overflow的狀況,但因為對c++不太熟悉,還需要摸索怎麼處理。

209.长度最小的子数组

自己看到题目的第一想法

思考了一陣,因為是要連續的子數組組,所以用途來說明會長這樣

  • 建立快慢指針、Sum、min=0並建立兩個迴圈
  • 第一個迴圈是快指針的移動,第二個迴圈是慢指針的移動
  • 第一個迴圈條件是Fast < nums.size(),第二個迴圈是Sum ≥ Target 則執行
  • 第二個迴圈中
    • 先比較min的大小,假設min為0則直接= Fast - Slow + 1 不為0則要比較min與Fast - Slow +1 誰比較小
    • Sum = Sum - nums[slow]
    • slow++;
[2, 3, 1, 2, 4, 3], target = 7;
[2] -> 第一次相加,總和為2,不符合條件,Fast往後移動,Slow不動
[2, 3] -> 第二次相加,總合為5,不符合條件,Fast往後移動,Slow不動
[2, 3, 1] -> 第三次相加,總合為6,不符合條件,Fast往後移動,Slow不動
[2, 3, 1, 2] -> 第四次相加,總合為8,符合條件,紀錄目前數組大小為Fast(3) - Slow(0) + 1 = 4,Slow往後更新,Fast不動
   [3, 1, 2] -> 第五次相加,總合為6,不符合條件,Fast往後移動,Slow不動
	 [3, 1, 2, 4] -> 第六次相加,總合為10,符合條件,紀錄目前數組大小為Fast(4) - Slow(1) + 1 = 4,Slow往後更新,Fast不動
			[1, 2, 4] -> 第七次相加,總合為7,符合條件,紀錄目前數組大小為Fast(4) - Slow(2) + 1 = 3,Slow往後更新,Fast不動
				 [2, 4] -> 第八次相加,總合為6,不符合條件,Fast往後移動,Slow不動
				 [2, 4, 3] -> 第九次相加,總合為9,符合條件,紀錄目前數組大小為Fast(5) - Slow(3) + 1 = 3,Slow往後更新,Fast不動
						[4, 3] -> 第十次相加,總合為7,符合條件,紀錄目前數組大小為Fast(5) - Slow(4) + 1 = 2,Slow往後更新,Fast不動
  					   [3] -> 第十一次相加,總合為3,Fast往後移動,Slow不動,Fast超出邊界,結束循環

59.螺旋矩阵II

自己看到题目的第一想法

看到程式碼第一個想法,有點矇,不知道如何下手,之前有看過一下代碼隨想錄,但對於這個題目的實現沒有去深究,目前想到的就是對於區間的處理,不處理每次的最後一個元素,留給下次當作頭元素處理,大致概念如下

while(number < n*n)
{
		第一層處理 [0][0] -> [0][n-1]
		第二層處理 [0][n] -> [n-1][n]
		第三層處理 [n][n] -> [n][1]
		第四層處理 [n][0] -> [1][0]
}

但大致這樣處理,還是沒有想到實作上該如何去實現,果斷選擇去看代碼隨想錄,

看完代码随想录之后的想法

看完代碼隨想錄之後,發現的確跟我之前記憶到的一樣,但真的到代碼實現的階段,就又是另外一回事了,但感到開心的一點是,我對於區間的定義是清晰的,但實踐能力還是需要一步步的琢磨下去

實作

977.有序数组的平方

思路

  • 原思路 -> 失敗

    1. 使用雙指針的方式,因為左右指針所指到的數,逐步往中間前進,越往中間值越小
    2. 利用左右指針比大小,右指針大於左指針,如果不符合,則將左指針的值換到右指針
    3. 右指針持續往左指針走,左指針固定在0. → [-5,-3,-2,-1]這個組合會被gank
  • 使用新的陣列來儲存最大值

    1. 使用雙指針,比較左右指針的值,較大的放到新陣列的最後一個數
    2. 如果左指針比較大,放入新陣列後,左指針++
    3. 如果右指針比較大,放入新陣列後,右指針--
    4. 直到循環結束,回傳新陣列

Code

class Solution {
public:
    vector sortedSquares(vector& nums) {
        int left = 0;
        int right = nums.size() - 1;
        vector result(nums.size());
        int k = nums.size() - 1;
        while(left <= right){
            if(nums[right]*nums[right] > nums[left]*nums[left]){
                result[k--] = nums[right] * nums[right];
                right--;
            }
            else{
                result[k--] = nums[left] * nums[left];
                left++;
            }
        }
        return result;
    }
};

209.长度最小的子数组

思路

  • 建立快慢指針、Sum、min=0並建立兩個迴圈
  • 第一個迴圈是快指針的移動,第二個迴圈是慢指針的移動
  • 第一個迴圈條件是Fast < nums.size(),第二個迴圈是Sum ≥ Target 則執行
  • 第一個迴圈中
    • 先將sum 加上nums[fast]的數值
    • fast++;
  • 第二個迴圈中
    • 先比較min的大小,假設min為0則直接= Fast - Slow + 1 不為0則要比較min與Fast - Slow +1 誰比較小
    • Sum = Sum - nums[slow]
    • slow++;
  • return min;

Code

class Solution {
public:
    int minSubArrayLen(int target, vector& nums) {
        int fast = 0;
        int slow = 0;
        int sum = 0;
        int min = 0;
        while(fast < nums.size()){
            sum += nums[fast];
            while(sum >= target){
                if(min == 0){
                    min = fast - slow + 1;
                }
                else if(min > (fast - slow + 1)){
                    min = fast - slow + 1;
                }
                sum -= nums[slow];
                slow++;
            }
            fast++;
        }
        return min;
    }
};

59.螺旋矩阵II

思路

  • 代碼隨想錄:

堅持一個原則去處理每一條邊,每一條的處理規則要統一

Code

class Solution {
public:
    vector> generateMatrix(int n) {
        vector> res(n, vector(n, 0)); 
        int startX = 0; //起始位置每一圈都會改變
        int startY = 0;
        int offset = 1; //因為offset也會根據每一圈而改變
        int count = 1;
        int loop = n / 2;
        int mid = n/2;
        int i, j;
        while(loop--){

            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++;
            }
            startX++; //控制X的起始位置
            startY++; //控制Y的起始位置 -> 因為每一圈的起始都不一樣
            offset++; //控制每一條邊的遍歷長度
        }

        if(n % 2){
            res[mid][mid]=count;
        }
        return res;

    }
};

總結

自己实现过程中遇到哪些困难

977.有序数组的平方

這個一開始有想到解法,但是自己實踐上還是出了點問題,不過最後還是靠自己解決了

209.长度最小的子数组

這個之前有寫過,這次重新寫一開始也想很久,但是將圖畫出來後,找出規律,訂出統一的處理標準,實踐起來就簡單許多

59.螺旋矩阵II

螺旋矩陣我看到時,只記得區間的定義清晰,但是實作上像是offset、startX、startY等等都沒有想到,其實很是慚愧,只能透過一次次的實踐,累積自己的經驗,來解決這樣子的問題

今日收获,

大約學了四個小時,但我覺得很有收穫,因為不斷的去思考自己的不足,以及實踐上看到的問題,自己也因為有作筆記,所以很直觀的去面對自己的不足

總結: 數組

在這一刷的過程中,主要有兩個概念要清楚

  1. 區間定義要明確,處理規則要統一
    • 在這幾次的寫題當中,其實感受很清楚,就是要把定義釐清,這樣對於寫題上其實會更輕鬆,前期思考的時間花的長,後續實作其實跟著思路走很快就出來了
  2. 雙指針
    • 不論是二分法、滑動窗口、快慢指針,就是根據不同題目的調性,去靈活運用兩個指針彼此的關係,回到第一點,只要定義清楚了,其實雙指針的做法很快就可以根據自己的思路進行設計。

你可能感兴趣的:(算法,c++,leetcode)