程式碼隨想錄演算法訓練營第一天|704二分查詢、27移除元素、977有序陣列的平方

小方呀0524發表於2024-10-16

程式碼隨想錄演算法訓練營第一天|704二分查詢、27移除元素、977有序陣列的平方

1 Leetcode 704 二分查詢

題目連結:[704.二分查詢](704. 二分查詢 - 力扣(LeetCode))

文章連結:[程式碼隨想錄](程式碼隨想錄 (programmercarl.com))

影片連結:[手把手帶你撕出正確的二分法 | 二分查詢法 | 二分搜尋法 | LeetCode:704. 二分查詢](手把手帶你撕出正確的二分法 | 二分查詢法 | 二分搜尋法 | LeetCode:704. 二分查詢_嗶哩嗶哩_bilibili)

狀態:知道題目思路,但是每次在判斷大於號和小於號需要思考一下,容易出錯,還有開閉區間容易出錯

思路:首先去找到一個陣列中間的數值,然後判斷中間數和目標數的大小,如果是比目標數小則移動左邊的索引,否則移動右邊索引,相等則返回中間值的索引

1.1這是一個左閉右閉的寫法

1.1.1python版本的程式碼
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left,right = 0,len(nums)-1
        while left<=right:
            middle = left+(right-left)//2
            if nums[middle]<target:
                left = middle+1
            elif nums[middle]>target:
                right = middle-1
            else:
                return middle
        return -1

左閉右閉區間在於其索引值與陣列下標索引值是一一對應的關係,所以有左邊的索引等於右邊的索引,程式碼內部的索引也是對應相等的

1.1.2 C++版本
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left= 0,right = nums.size()-1;
        while (left<=right){
            int middle = (left+right)/2;
            if (nums[middle]<target){
                left = middle+1;
            }
            else if (nums[middle]>target){
                right = middle-1;
            }
            else {return middle;}
        } 
        return -1;
    }
};

1.2 左閉右開區間的寫法

1.2.1 python版本
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left,right = 0,len(nums)
        while left<right:
            middle = left+(right-left)//2
            if nums[middle]<target:
                left = middle+1
            elif nums[middle]>target:
                right = middle
            else:
                return middle
        return -1
C++版本
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left= 0,right = nums.size();
        while (left<right){
            int middle = (left+right)/2;
            if (nums[middle]<target){
                left = middle+1;
            }
            else if (nums[middle]>target){
                right = middle;
            }
            else {return middle;}
        } 
        return -1;
    }
};

1.3小結

1.3.1 python注意細節

python內部需要注意最後返回值在迴圈以外,不然會有報錯的情況

1.3.2 C++注意細節

​ a.每行程式碼結束的時候是有英文狀態下的;的,每次忘記則會報錯

​ b.和python不同的點事python賦值是連結串列賦值,但是C++語言是一個一個給值的,所以如果想要一行賦值,則需要進行一句一句的等於,不然會報錯

2 Leetcode 27 移除元素

題目連結:27. 移除元素

文章連結:[移除元素](程式碼隨想錄 (programmercarl.com))

影片連結:[陣列中移除元素並不容易! | LeetCode:27. 移除元素](陣列中移除元素並不容易! | LeetCode:27. 移除元素_嗶哩嗶哩_bilibili)

思路:無從下手,,,

2.1 暴力搜尋

才開始沒看明白為什麼,然後紙上畫了一遍明白了這個是先搜尋數值,如果出現了預期值,則進行一個相加,否則的話就是繼續去尋找,陣列是覆蓋而不是刪除,用覆蓋的思想表示了刪除的意思

2.1.1 python版本

錯誤原因:開始的時候想用for迴圈,然後i從range裡面取值,進行i-=1後變成了-1,在進行下一輪的時候還是從range內取值,對其沒影響,導致錯誤

更改:將其轉換為while的時候,這個值是一個可控變數

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        i,n =0,len(nums)
        while i<n:
            if nums[i]==val:    
                for j in range(i+1,n):
                    nums[j-1]=nums[j]
                n -=1
                i -=1
            i +=1
        return n
2.1.2 C++版本
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int n =nums.size();
        for (int i=0;i<n;i++){
            if (nums[i]==val){
                for (int j =i+1;j<n;j++){
                    nums[j-1]=nums[j];
                }
                i--;
                n--;
            }
        }
        return n;
    }
};

2.2快慢指標的方法

2.2.1 python版本
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        slowind = 0
        for i in range(len(nums)):
            if nums[i] != val:
                nums[slowind] = nums[i]
                slowind +=1
        return slowind
2.2.2 C++版本
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowind = 0;
        for (int fastind=0;fastind<nums.size();fastind++){
            if (nums[fastind]!=val){
                nums[slowind++] = nums[fastind];
            }
        }
        return slowind;
    }
};

2.3小結

思路:雙指標的方法,本質是兩層for迴圈,但是迴圈的話對於時間複雜度會很高,就會造成報錯的情況,所以就想辦法看可不可以將一層迴圈轉換成資料標識,進行比較,如果有相等的,就去覆蓋數值,否則就繼續向前走的思路

遇到的問題:在理解了雙指標以後,就是不知道兩個指標的快慢應該怎麼選擇在這一塊卡了一下,然後根據已有程式碼進行繪製走的過程,使用pycharm進行debug了一下,就理解了這個思路

3 Leetcode 977 有序陣列的平方

題目連結:977. 有序陣列的平方 - 力扣(LeetCode)

文章連結:程式碼隨想錄 (programmercarl.com)

影片連結:雙指標法經典題目 | LeetCode:977.有序陣列的平方

3.1自己的思路和解題

先逐步求出他們的平方值,然後將其儲存,最後使用sort函式對列表進行排序即可

3.1.1python版本
class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        for i in range(len(nums)):
            nums[i]=nums[i]**2
        nums.sort()
        return nums
3.1.2C++版本

這種方法學習了C++排序的一個函式,sort函式,這個函式需要指定元素的起始和終止位置即可

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

3.2雙指標的思路

3.2.1python版本的思路
class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        i,j = 0,len(nums)-1
        result = list()
        while i<=j:
            if nums[i]**2<nums[j]**2:
                result.append(nums[j]**2)
                j -=1
            else:
                result.append(nums[i]**2)
                i +=1
        return result[::-1]
3.2.2C++版本

這道題就是讓我理解了C++裡面的,;的區別,有一種直白的說法就是,一句話沒說完就用,否則就用;,拿這道題來舉例在迴圈中對i和j進行賦值的時候,他倆都需要定義為整型,所以用,但是裡面一句話徹底結束,下一個不需要這個定義的時候就用分號

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

4 今日學習小結

4.1題目中的知識點

  1. 一些可以用指標思路做的題,其實也可以用最基礎的暴力搜尋的辦法去寫
  2. 手撕二分法,二分法的結構就是找中間數進行比較,如果是想要的數字就返回,否則繼續進行中間數查詢,迴圈這個過程
  3. 刪除元素裡面的知識點重點在於陣列內的資料不是直接刪除,而是透過移動替換的方式,即列表內資料是不可以直接刪除的
  4. 有序陣列平方的知識點在於一個有序列表,他們的最大值和最小值一定是在兩邊,所以可以直接比較

4.2一些寫程式碼掌握的知識

4.2.1python
  1. 在語句中注意for迴圈中的range函式的使用,這個函式的值是根據range的值走的,不會因為我對值進行改變他就會有大的變化
  2. 列表中使用sort函式,是直接對原始資料進行排序的,如果寫python return nums.sort() 不會輸出排序的結果,會報錯
4.2.2 C++
  1. 這裡面首先學習的就是兩種標點符號所表達的意思不同,在python中a,b=1,2是正確語法,但是在C++就需要寫成int a=1,b=2;
  2. C++的排序也是使用sort函式,但是這個sort函式寫的規則為sort(nums.begin(),nums.end())來表示其起始和終點的位置

相關文章