代码随想录算法训练营第一天 | 704二分查找、27移除元素

704:二分查找

题目链接:
704二分查找
视频
文字版
二分法特点:1)必须是有序
2)如有重复元素,返回值可能不唯一

文本区间的定义就是不变量。要在二分查找的过程中,保持不变量,就是在while寻找中每一次边界的处理都要坚持根据区间的定义来操作,这就是循环不变量规则。

两种情况,1)区间左闭右闭 2)左闭右开
易混淆点:1)while(left<right)还是while(left <= right)
2)if(num[middle] > target)
right=middle 还是 right= middle -1
第一种情况:区间左闭右闭
【1,1】

/*例如在【1,1】里寻找2
middle=(0+!)/2=0
num[0]=1<2,target在右半部分,修改左边界,
left=middle+1=1,此时right=1
left==right是有意义的
如果while的循环条件不包括等于号的话则不会判断num[1]的值是否是target
所以循环条件里必+=
*/
/*
若在修改边界条件时不+1或-1,则会把已经判断过的num[middle]包含在新的判断区间里,是无用功
*/
left=0;
right =num.size -1;
middle= (left + right) / 2
while(left <= right)
{
 	if (num[middle]>target)
 		right= middle-1;
 	else if( num[middle] < target )
 		left= middle+1;
 	else
 		return middle;
}
return -1;

java版本
在编写时犯了一处错误,middle的计算放在了循环外
第一个if避免了当 target 小于nums[0] nums[nums.length - 1]时多次循环运算,提高了效率

class Solution {
    public int search(int[] nums, int target) {
         if (target < nums[0] || target > nums[nums.length - 1]) {
            return -1;
        }
        int left=0;
        int right=nums.length-1;
        while(left<=right){
            int middle = left + ((right-left)>>1);
            if(nums[middle]<target)
                left=middle+1;
            else if(nums[middle]>target)
                right=middle-1;
            else
                return middle;
        }
        return -1;
    }
}

第二种情况:区间左闭右开

eg.[1,1)
区间既包含1,又不包含1,不合法
left和right相等的情况在这个区间无意义
即搜索区间永远不会包含right
left=0;
right =num.size;//第一处不同
middle= (left + right) / 2
while(left < right)//第二处不同
{
 	if (num[middle]>target)
 		right= middle;//第三处不同,仍是左闭右开
 	else if( num[middle] < target )
 		left= middle+1;
 	else
 		return middle;
}
return -1;
class Solution {
    public int search(int[] nums, int target) {
    if(target<nums[0] || nums[nums.length-1]<target)
        return -1;
    int left=0,right=nums.length;
    while(left<right){
        int middle=left +((right-left)>>1);
        if(nums[middle]>target)
            right=middle;
        else if(nums[middle]<target)
            left=middle+1;
        else
            return middle;
    }
    return -1;
    }
}

总结:
定义了什么样的区间,决定了我们如何处理边界
在循环中坚持根据查找区间的定义来做边界处理

27:移除元素

27移除元素
视频
文字版
方法一:暴力解法
两层for循环,第一层遍历,第二层把后面的元素覆盖到前一个元素上

方法二:快慢指针
复杂度O(n)
快指针代表新数组中的元素,慢指针代表新数组中需要更新的位置

slow = 0;
for( fast=0; fast< num.size;fast ++)
{
if(num[fast]!=val)
	{
	num[slow++]=num[fast];
	}
}
return slow;//这里比较巧
class Solution {
    public int removeElement(int[] nums, int val) {
        int slow=0,fast=0;
        for(;fast<nums.length;fast++){
            if(nums[fast]!=val){
                nums[slow++]=nums[fast];
            }
        }
        return slow;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值