题目链接:704.二分查找
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
while(left<=right){
int mid = (left + right) / 2;
if(target == nums[mid]){
return mid;
}else if (target > nums[mid]){
left = mid + 1;
}else{
right = mid - 1;
}
}
return -1;
}
};
左闭右闭写法:
while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
左闭右开写法:
while (left < right),这里使用 < ,因为left == right在区间[left, right)是没有意义的
if (nums[middle] > target) right 更新为 middle,因为当前nums[middle]不等于target,去左区间继续寻找,而寻找区间是左闭右开区间,所以right更新为middle,即:下一个查询区间不会去比较nums[middle]
情人节初遇vector:
vector类似于string类,也是一种动态数组,vector是 STL 的动态数组,可以在运行阶段根据需要改变vector对象的长度,可在末尾或中间插入数据元素。因为它以数组的形式储存,所以它的内存空间是连续的,与普通数组和array对象都可使用标准数组表示法来访问各个元素。
一般声明方法:
vector<typeName> vt(n_elem);
其中参数n_elem可以是整型变量或变量。
感想:
二分查找在408的复习中已经熟悉和掌握,解题也比较流畅,需要注意的是根据左闭右开还是左闭右闭情况选择判断条件。
希望在接下来的训练中熟练掌握STL的应用。
题目链接:27.移除元素
暴力解法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size();
for(int i = 0 ;i < len;i++){
if(nums[i] == val){
for(int j = i + 1;j < len;j++){
nums[j - 1] = nums[j];
}
len--;
i--;
}
}
return len;
}
};
双指针法
双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;
for (int fastIndex = 0;fastIndex < nums.size();fastIndex++){
//当所指元素不为val时,快慢指针同时移动
if (val != nums[fastIndex]) {
nums[slowIndex++] = nums[fastIndex];//fast将不为val的元素覆盖在slow所指元素上
}
//当fast指针所指元素为val,fast先走一步,在下一次循环中继续判断
}
//fast指针提前走完,多走的步数即val的个数(除最后一个元素等于val的情况)
return slowIndex;
}
};
![](https://img-blog.csdnimg.cn/img_convert/7ab3b38c498cafd8bc0aa21db606dfa4.gif)
优化:
/**
* 相向双指针方法,基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素
* 时间复杂度:O(n)
* 空间复杂度:O(1)
*/
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一定指向了最终数组末尾的下一个元素
}
};
感想:
该优化减少了移动元素的个数,作为新手还需要在代码随想录中积累和学习更多算法技巧,通过今日学习对数组和二分法理解更深了。