写好的博客因为电脑卡死没保存上,不得已又写了一遍(怒)
今日任务
数组理论基础,704. 二分查找,27. 移除元素
附加任务:35.搜索插入位置、34. 在排序数组中查找元素的第一个和最后一个位置
数组理论基础
文章链接:https://programmercarl.com/%E6%95%B0%E7%BB%84%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
704. 二分查找
// 二分查找(左闭右闭)
class Solution {
public int search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right){
int mid = (right-left)/2 + left;
int num = nums[mid];
if (num == target){
return mid;
}else if(num < target){
left = mid+1;
}else
right = mid-1;
}
return -1;
}
}
题目链接:https://leetcode.cn/problems/binary-search/
文章讲解:https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html
视频讲解:https://www.bilibili.com/video/BV1fA4y1o715
复杂度分析
时间复杂度:O(log n) ,其中 n 是数组的长度。
空间复杂度:O(1) 。
35.搜索插入位置
class Solution {
public int searchInsert(int[] nums, int target) {
int left=0,right=nums.length-1;
while(left<=right){
int mid=(right-left)/2+left;
int num=nums[mid];
if(num==target){
return mid;
}else if(num>target){
right=mid-1;
}else
left=mid+1;
}return left;
}
}
力扣官方给出的答案比较麻烦,实际上直接返回left即可,这里借用评论区用户munpf的话:
不需要ans变量,最后直接返回left就可以了,根据if的判断条件,left左边的值一直保持小于target,right右边的值一直保持大于等于target,而且left最终一定等于right+1,这么一来,循环结束后,在left和right之间画一条竖线,恰好可以把数组分为两部分:left左边的部分和right右边的部分,而且left左边的部分全部小于target,并以right结尾;right右边的部分全部大于等于target,并以left为首。所以最终答案一定在left的位置。
34. 在排序数组中查找元素的第一个和最后一个位置
class Solution {
public int[] searchRange(int[] nums, int target) {
int l=search(nums,target);
int r=search(nums,target+1);
if(l==nums.length||nums[l]!=target)
return new int[]{-1,-1};
return new int[]{l,r-1};
}
public int search(int[] nums,int target){
int l=0,r=nums.length;
while(l<r){
int mid=(r-l)/2+l;
int num=nums[mid];
if (num>=target){
r=mid;
}else
l=mid+1;
}
return l;
}
}
关于这里r=nums.length而不是nums.length-1,因为这里是一个左闭右开区间,这个题需要我们寻找两个num,一个是第一个等于target的num,另一个是大于target的第一个num,在寻找大于target的第一个num时,我们需要假设num>=target,开始的情况为num>target,我们把mid的值不断赋给r来缩小范围,直到num=target的瞬间,此时赋给r的mid值即是大于target的第一个num。
27. 移除元素
// 移除元素(双指针)
class Solution {
public int removeElement(int[] nums, int val) {
int n=nums.length;
int left=0;
for(int right=0;right<n;right++){
if (nums[right]!=val){
nums[left++]=nums[right];
}
}return left;
}
}
==题目链接:https://leetcode.cn/problems/remove-element/ ==
文章讲解:https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html
视频讲解:https://www.bilibili.com/video/BV12A4y1Z7LP