代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素
Leetcode 704. 二分查找
问题简述:在无重复有序数组中找到目标值target的下标,若不存在返回-1。
算法思路:定义一个left和一个right变量分别指向数组的头和尾,每次循环比较target与mid对应元素的大小。
时间复杂度 O(log2n)
空间复杂度 O(1)
值得注意的是,我们要明确在每次循环中,要比较的元素范围是 [left,right] 还是 [left,right) 。当为前者时,循环条件为 left <= right ,因为当 left = right 时,依然存在范围,且当 target < mid 时,我们要把right的值改变成 mid - 1,因为我们已经明确 target < mid 了,在双闭区间内时,不需要再次把mid这个元素添加到比较范围之中。当 target > mid 同理,代码如下:
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
//循环中比较元素范围[left,right]
while (left <= right){
int mid = (left + right)/2;
if(target == nums[mid]){
return mid;
}else if(target > nums[mid]){
//我们已经明确 target > mid 了,在双闭区间内时,不需要再次把mid这个元素添加到比较范围之中
left = mid + 1;
}else {
right = mid - 1;
}
}
return -1;
}
}
而当选取范围为 [left,right) 时 。循环条件则为 left < right ,因为当 left = right 时,依然范围不存在,且当 target < mid 时,我们要把right的值改变成 mid ,因为我们已经明确 target < mid 了,在左开右闭的区间内,即使right = mid 比较区间仍不包含mid这个元素本身。当 target > mid 时和上一个方法同理,需要 left = mid + 1 代码如下:
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
//循环中比较元素范围[left,right)
while (left < right){
int mid = (left + right)/2;
if(target == nums[mid]){
return mid;
}else if(target > nums[mid]){
left = mid + 1;
}else {
//我们已经明确 target < mid 了,在左开右闭的区间内,即使right = mid 比较区间仍不包含mid这个元素本身
right = mid;
}
}
return -1;
}
}
Leetcode 27. 移除元素
问题简述:移除数组内所有的指定元素。
算法思路:定义一个快指针一个慢指针,快指针依次遍历数组中所有元素,慢指依次针指向删除指定元素后的新数组。
时间复杂度 O(n)
空间复杂度 O(1)
class Solution {
public int removeElement(int[] nums, int val) {
//定义慢指针
int p = 0;
int length = nums.length;
//快指针要遍历所有元素,i即位快指针
for(int i = 0;i < nums.length; i++){
if(nums[i] != val){
//将快指针元素赋值给慢指针
nums[p++] = nums[i];
}else{
length--;
}
}
return length;
}
感想
二分法写了半天写不明白,看了视频豁然开朗!快慢指针之前比较熟悉。坚持!加油!