代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素
704.二分查找
链接:leecode704
思路:通过二分的方式把每次搜索的区间不断减半缩短,需要通过比较区间的中间元素和target比较来确定选取较小的区间还是较大的区间。需要注意的是循环的退出条件以及target出现在边界是否出现遗漏的情况。对于区间[left, right]我们选择当left <= right时,即区间合理时继续进行搜索。当left = right时,区间为单个点,所搜区间的最小粒度为单个点,所以不会存在遗漏搜索的情况。更新left = mid - 1, right = mid + 1 区间缩短为1所以不会存在无限循环的情况。
时间复杂度:O(N)
class Solution {
public:
int search(vector<int>& nums, int target) {
int n = nums.size();
//初始边界
int left = 0;
int right = n - 1;
int mid;
//区间合理时继续搜索
while (left <= right) {
mid = (left + right) / 2;
if (nums[mid] < target){
left = mid + 1;
}
else if (nums[mid] > target){
right = mid - 1;
}
else return mid;
}
return -1;
}
};
27.移除元素
链接:leecode27
思路:看到要求O(1)的空间要求就想到需要在原数组中进行操作,需要将数组分成两个部分,前面部分是valid值 (在这里是不等于val),后面部分是invliad值(等于val),我们可以将invalid的值通过交换的方式放到尾部。可以利用双指针来分别维护两个区间,i指针来维护valid区间,即i指针经过的区域是valid的,j指针维护invalid区间,即j指针经过的区域是invliad的。
要利用交换的方式来构建符合条件的数组,就要求i是指向invalid数值,j指向valid数值。
- j只能停留在valid数值,遇到invalid数值就向前移动。
- i如果指向valid数值不需要交换,直接向右移动即可
- i如果指向invliad数值则I,j数据交换
每种情况都单独操作,不要忘了continue
关于循环结束条件,[j + 1, N - 1]是invalid区间, [0, I -1] 是valid区间,当j + 1 = I - 1 + 1时覆盖整个数组完成遍历,此时 i = j + 1 , 即 i > j 恰好达成时结束循环,所以循环条件i <= j
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int i = 0;
int j = nums.size() - 1;
int temp;
//当 i >j 时, i指向的以及右边的值都是invalid, j指向的以左边的值都是valid的,此时数组是符合条件的
while (i <= j) {
// j只能停在valid值
if (nums[j] == val) {
--j;
continue;
}
//i只能停在invalid值
if (nums[i] != val) {
++i;
continue;
}
//
if (nums[i] == val){
temp = nums[i];
nums[i] =nums[j];
nums[j] = temp;
}
}
return i;
}
};