「程式碼隨想錄演算法訓練營」第一天(補) | 陣列 part1

云雀AC了一整天發表於2024-07-07

704. 二分查詢

題目連結:https://leetcode.cn/problems/binary-search/
題目難度:簡單
文章講解:https://programmercarl.com/0704.二分查詢.html
影片講解: https://www.bilibili.com/video/BV1fA4y1o715
題目狀態:透過

個人思路:

就是簡單的二分查詢思路,判斷陣列中間的值是否等於目標值,不等於就更新範圍。

具體程式碼:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int low = 0, high = nums.size() - 1;
        return Binary(nums, low, high, target);
    }
    int Binary(vector<int> &nums, int low, int high, int target) {
        if(low > high) return -1;

        int mid = low + (high - low) / 2;
        if(nums[mid] == target) {
            return mid;
        }
        else if(nums[mid] > target) {
            return Binary(nums, low, mid - 1, target);
        }
        else {
            return Binary(nums, mid + 1, high, target);
        }
    }
};

27. 移除元素

題目連結:https://leetcode.cn/problems/remove-element/
題目難度:簡單
文章講解:https://programmercarl.com/0027.移除元素.html
影片講解: https://www.bilibili.com/video/BV12A4y1Z7LP
題目狀態:透過

個人思路:

一開始要打算直接用erase函式的,但是感覺這應該不是考察的重點,然後就使用了雙指標。

  1. 當左邊指標i對應的值等於要刪除的元素時,將位於右邊的指標j的值覆蓋到左邊指標,並且j++
  2. 當左邊指標i對應的值不等於要刪除的元素時,i++

具體程式碼:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int i = 0, j = nums.size();
        while(i < j) {
            if(nums[i] == val) {
                nums[i] = nums[j - 1];
                j--;
            }
            else {
                i++;
            }
        }
        return j;
    }
};

卡哥思路我還真沒想過,使用快慢指標

實現程式碼:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int n = nums.size();
        int i = 0;
        for(int j = 0; j < n; ++j) {
            if(val != nums[j]) {
                nums[i] = nums[j];
                i++;
            }
        }
        return i;
    }
};

26. 刪除有序陣列中的重複項

題目連結:https://leetcode.cn/problems/remove-duplicates-from-sorted-array/
題目難度:簡單
題目狀態:透過

個人思路:

學習卡哥上題的思路,使用快慢指標

具體程式碼:

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int slow = 0;
        for(int fast = 1; fast < nums.size(); ++fast) {
            if(nums[slow] != nums[fast]) {
                slow++;
                nums[slow] = nums[fast];
            }
        }
        return slow + 1;
    }
};

283. 移動零

題目連結:https://leetcode.cn/problems/move-zeroes/
題目難度:簡單
題目狀態:透過

個人思路:

快慢指標太好用了,一次過。

  1. 使用快指標遍歷;
  2. 當慢指標的值為0,且快指標的值不為0時,快慢指標對應的值交換;
  3. 當慢指標的值不為0時,將慢指標移動到下一個。

具體程式碼:

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int i = 0;
        for(int j = 0; j < nums.size(); ++j) {
            if(nums[i] == 0 && nums[j] != 0) {
                swap(nums[i], nums[j]);
            }
            if(nums[i] != 0) i++;
        }
    }
};

844. 比較含退格的字串

題目連結:https://leetcode.cn/problems/backspace-string-compare/
題目難度:簡單
題目狀態:沒有思路,看題解

當我感覺自己會使用雙指標的時候,想法破裂了……

力扣官方題解

1. 棧

當判斷一個陣列中的元素不為#時,將該元素入棧;而該元素為#且棧不為空時,出棧。最終判斷兩個字串的棧是否相同。

實現程式碼如下:

class Solution {
public:
    bool backspaceCompare(string s, string t) {
        return build(s) == build(t);
    }
    string build(string s) {
        string res;
        for(auto i : s) {
            if(i != '#') {
                res.push_back(i);
            }
            else if(!res.empty()) {
                res.pop_back();
            }
        }
        return res;
    }
};

2. 雙指標法

先看圖解(來自力扣官方):

一個字元是否會被刪掉,只取決於該字元後面的退格符,而與該字元前面的退格符無關。因此當我們逆序地遍歷字串,就可以立即確定當前字元是否會被刪掉。

具體地,我們定義 skip 表示當前待刪除的字元的數量。每次我們遍歷到一個字元:

  • 若該字元為退格符,則我們需要多刪除一個普通字元,我們讓 skip 加 1;

  • 若該字元為普通字元:

    • skip 為 0,則說明當前字元不需要刪去;
    • skip 不為 0,則說明當前字元需要刪去,我們讓 skip 減 1。

這樣,我們定義兩個指標,分別指向兩字串的末尾。每次我們讓兩指標逆序地遍歷兩字串,直到兩字串能夠各自確定一個字元,然後將這兩個字元進行比較。重複這一過程直到找到的兩個字元不相等,或遍歷完字串為止。

class Solution {
public:
    bool backspaceCompare(string S, string T) {
        int i = S.length() - 1, j = T.length() - 1;
        int skipS = 0, skipT = 0;

        while (i >= 0 || j >= 0) {
            while (i >= 0) {
                if (S[i] == '#') {
                    skipS++, i--;
                } else if (skipS > 0) {
                    skipS--, i--;
                } else {
                    break;
                }
            }
            while (j >= 0) {
                if (T[j] == '#') {
                    skipT++, j--;
                } else if (skipT > 0) {
                    skipT--, j--;
                } else {
                    break;
                }
            }
            if (i >= 0 && j >= 0) {
                if (S[i] != T[j]) {
                    return false;
                }
            } else {
                if (i >= 0 || j >= 0) {
                    return false;
                }
            }
            i--, j--;
        }
        return true;
    }
};

977. 有序陣列的平方

題目連結:https://leetcode.cn/problems/squares-of-a-sorted-array/
題目難度:簡單
題目狀態:之前做過,且已透過

個人思路:

建立一個新陣列res,用來儲存結果。
使用雙指標分別指向有序陣列的兩端,並建立一個指標指向res的尾部。
判斷雙指標所指的值的平方哪個更大,並將更大的值存入res

實現程式碼:

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int n = nums.size();
        vector<int> res(n);
        int i = 0, j = n - 1, k = n - 1;
        while(i <= j)
        {
            if(nums[i] * nums[i] > nums[j] * nums[j])
            {
                res[k] = nums[i] * nums[i];
                i++;
            }
            else
            {
                res[k] = nums[j] * nums[j];
                j--;
            }
            k--;
        }
        return res;
    }
};

相關文章