程式碼隨想錄演算法訓練營第一天|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題目中的知識點
- 一些可以用指標思路做的題,其實也可以用最基礎的暴力搜尋的辦法去寫
- 手撕二分法,二分法的結構就是找中間數進行比較,如果是想要的數字就返回,否則繼續進行中間數查詢,迴圈這個過程
- 刪除元素裡面的知識點重點在於陣列內的資料不是直接刪除,而是透過移動替換的方式,即列表內資料是不可以直接刪除的
- 有序陣列平方的知識點在於一個有序列表,他們的最大值和最小值一定是在兩邊,所以可以直接比較
4.2一些寫程式碼掌握的知識
4.2.1python
- 在語句中注意for迴圈中的range函式的使用,這個函式的值是根據range的值走的,不會因為我對值進行改變他就會有大的變化
- 列表中使用sort函式,是直接對原始資料進行排序的,如果寫
python return nums.sort()
不會輸出排序的結果,會報錯
4.2.2 C++
- 這裡面首先學習的就是兩種標點符號所表達的意思不同,在python中
a,b=1,2
是正確語法,但是在C++就需要寫成int a=1,b=2;
- C++的排序也是使用sort函式,但是這個sort函式寫的規則為
sort(nums.begin(),nums.end())
來表示其起始和終點的位置