刷算法,冲秋招,酱紫~
1. 二分查找
二分查找是一种高效的搜索算法,用于在有序数组中查找特定元素。该算法将搜索范围逐渐缩小一半,直到找到目标元素或确定不存在。
两个二分查找的实现示例,它们都采用了不同的处理边界和更新指针的方式。第一个示例中的 search
函数使用闭区间 [left, right]
进行搜索,而第二个示例中的 Division
函数使用左闭右开区间 [left, right)
进行搜索。这两种方式都是有效的,关键是正确地更新指针和边界,以确保不会陷入死循环并找到目标值。
cpp
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;
cout<<middle<<endl;
if(nums[left]==target) return left;
if(nums[right]==target) return right;
if(nums[middle]==target) return middle;
if (nums[middle] > target) {
right = middle - 1; // target 在左区间,所以[left, middle - 1]
} else if (nums[middle] < target) {
left = middle + 1; // target 在右区间,所以[middle + 1, right]
} else { // nums[middle] == target
return middle; // 数组中找到目标值,直接返回下标
}
}
// 未找到目标值
return -1;
}
};
cpp
class Solution {
public:
int Divsion(vector<int>& nums,int target){
int left=0,right=nums.size()-1;
while(left<right){
int middle=(left+right)/2;
cout<<middle<<endl;
if(nums[left]==target) return left;
if(nums[right]==target) return right;
if(nums[middle]==target) return middle;
if (nums[middle] > target) {
right = middle; // target 在左区间,左闭右开,所以[left, middle ]
} else if (nums[middle] < target) {
left = middle + 1; // target 在右区间,所以[middle + 1, right]
} else { // nums[middle] == target
return middle; // 数组中找到目标值,直接返回下标
}
}
// 未找到目标值
return -1;
}
};
2. 字符串反转
字符串反转是一种常见的操作,用于颠倒字符串中字符的顺序。提供了三种不同的实现方式,它们分别是:
- 使用双指针法:从字符串两端向中间遍历,交换字符。
- 使用标准库函数
reverse
:直接调用标准库提供的字符串反转函数。(纯脑瘫) - 基于之前提供的反转方法。
这些方法都可以有效地反转字符串,关键是理解双指针法的原理以及如何正确地交换字符。
cpp
class Solution{
public:
void reverses(vector<char>& s){
for(int i=0,j=s.size()-1;i<s.size()/2;i++,j--){
swap(s[i],s[j]);
}
}
};
cpp
class Solution{
public:
string reverseString(string s)
{
int i = 0, j = s.size() - 1;
while (i < s.size()/2)
{
swap(s[i++], s[j--]);
}
return s;
}
};
cpp
class Solution{
public:
void reverseString(vector<char>& s){
//use reverse
reverse(s.begin(), s.end());
}
};
3. 移除元素
移除元素是指从数组中删除特定值的所有实例。提供了两种不同的实现方式,它们分别是:
- 使用两个指针:一个快指针用于遍历数组,一个慢指针用于指向下一个非目标值的位置,将非目标值覆盖到慢指针所指的位置。
- 使用单指针:遍历数组,当遇到非目标值时,将其复制到慢指针位置,并将慢指针右移。
这两种方式都是有效的,关键是正确地更新指针和数组元素,以达到移除目标元素的目的。
cpp
class Solution{
public:
int removeElement(vector<int>& nums,int val){
int size=nums.size();
for(int i=0;i<size;i++){
if(nums[i]==val){
for(int j=i+1;j<size;j++){
nums[j-1]=nums[j];
}
i--;
size--;
}
}
}
};
cpp
class Solution{
public:
int removeElement(vector<int>& nums,int val){
int slow=0;
for(int fast=0;fast<nums.size();fast++){
if(nums[fast]!=val){
nums[slow++]=nums[fast];
}
return slow;
}
};
cpp
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int leftIndex = 0; // 左指针从数组开头开始
int rightIndex = nums.size() - 1; // 右指针从数组末尾开始
while (leftIndex <= rightIndex) {
// 找左边等于val的元素,一直移动左指针
while (leftIndex <= rightIndex && nums[leftIndex] != val) {
++leftIndex;
}
// 找右边不等于val的元素,一直移动右指针
while (leftIndex <= rightIndex && nums[rightIndex] == val) {
--rightIndex;
}
// 如果左指针指向的位置在右指针左侧,将右指针指向的不等于val的元素覆盖左指针指向的等于val的元素
if (leftIndex < rightIndex) {
nums[leftIndex++] = nums[rightIndex--];
}
}
return leftIndex; // leftIndex 现在指向了最终数组末尾的下一个位置
}
};
4. 爬楼梯
爬楼梯是一个经典的动态规划问题,其中你需要计算爬到第 n 级楼梯的不同方法数。你提供了两种不同的实现方式,它们都使用动态规划来计算不同方法数。
第一个示例中的 climbStairs
函数使用数组来存储中间结果,从而避免重复计算。第二个示例中的 climbStairs
函数使用滚动数组的方式,只存储最近两个状态,进一步优化了空间复杂度。
cpp
class Solution {
public:
int climbStairs(int n) {
if (n <= 1) return n; // 因为下面直接对dp[2]操作了,防止空指针
vector<int> dp(n + 1);
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= n; i++) { // 注意i是从3开始的
dp[i] = dp[i - 1] + dp[i - 2];
}
return dp[n];
}
};
cpp
class Solution {
public:
int climbStairs(int n) {
if (n <= 1) return n;
int dp[3];
dp[1] = 1;
dp[2] = 2;
for (int i = 3; i <= n; i++) {
int sum = dp[1] + dp[2];
dp[1] = dp[2];
dp[2] = sum;
}
return dp[2];
}
};
5. 二叉树构建
用了前序遍历进行构造
cpp
class TreeNode{
public:
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x):val(x),left(NULL),right(NULL){}
void traversal(TreeNode* cur,vector<int> & vec){
if(cur==NULL)return;
vec.push_back(cur->val);
preorderTraversal(cur->left);
preorderTraversal(cur->right);
}
vector<int> preorderTraversal(TreeNode *root){
vector<int> vec;
traversal(root,vec);
return vec;
}
};