题目描述:在一个有序无重复的数组nums里面,找到target的下标。
写前思考:查找就先想能不能二分,这个题显然可以。二分本质就是一个左右指针,不停的去控制边界。控制边界的依据就是mid和target进行比较。二分的两个写法就是左闭右开,还是左闭右闭,根据选择的不同,while的边界条件也要注意。
之前一直用的左闭右开,直接套模版。
class Solution {
public int search(int[] nums, int target) {
// 二分的关键 区间的设置
// 设置左闭右开 mid = (left + right/2)
int left = 0;
int right = nums.length;
// 由于是左闭右开,所以在left == right时,[left,right)是没有意义的
while(left < right){
int mid = left + (right - left)/2; // 防止溢出
if(nums[mid] == target){
return mid;
}else if(nums[mid] < target){
left = mid + 1;
}else{
right = mid;
}
}
return -1;
}
}
左闭右闭也不难写,为了以后不混淆,以后写二分只用左闭右开!
总结:首先二分肯定有适用条件,必须是有序且不重复的数组,以后看到这个条件,就要想往二分去套。套的时候思考几个点,while的条件是什么?left和right相等有没有意义?每一次缩小区间left和right如何变化?
看完这个,可以顺便回顾一下74、二维矩阵的搜索
题目描述:原地移除所有等于val的元素,要求不能使用额外的空间,空间复杂度为o(1)。最后返回新数组的长度。
写前思考:这里要求不能使用额外的空间,那么肯定只能原地修改,转换一下意思,这道题的意思就是把不是val的元素全往前平移。直接快慢指针即可。慢指针记录不等于val的值,快指针遍历数组即可。
快慢指针
class Solution {
public int removeElement(int[] nums, int val) {
int res = 0;
for(int i = 0;i < nums.length;i++){
if(nums[i] != val){
nums[res] = nums[i];
res ++;
}
}
return res;
}
}
总结:数组不像链表,不可以删除元素,只可以对元素进行覆盖!