算法学习day01:二分查找,数组移除元素(Java)

本文介绍了在Java中使用二分查找算法的基本原理和两种常见实现方式(左闭右闭和左闭右开),以及如何使用for循环和快慢指针法移除数组元素。
摘要由CSDN通过智能技术生成

算法学习day01:二分查找,数组移除元素(Java)

二分查找

简介

二分查找是比较常见的查找方式,大概逻辑是:把一个递增/递减的数组从中间分成两半,找到有目标元素的一半数组 继续分开,一直循环,直到只剩下目标元素。

想使用二分查找,前提条件是:数组是递增/递减的,且数组没有重复的元素。

写法

二分查找的写法主流上有两种:左闭右开,左闭右闭,具体的解释建议配合下面代码看。

需要定义的变量有:left,right,middle,数组num,目标target(后两者是已知条件)

左闭右闭
public static void main(String[] args) {
    int[] num1 = {0,1,3,4,6,7,8,9,10,25,100};
    //使用前提:数组递增或递减,数组内没有重复的数字
    System.out.println(search01(num1, 6));
}
public static int search01(int[] num, int target){
    int left = 0;
    int right = num.length -1;
    int middle;
    while(left <= right){
        middle = left + (right-left)/2;
        if(target > num[middle]){
            left = middle + 1;
        }else if (target < num[middle]){
            right = middle - 1;
        }else return middle ;
    }
    return -1;
}


首先定义需要查找的左右区间。如数组{0,1,3,4,6,7,8,9,10,25,100}

左闭右闭相当于包含left和right,即类似数学中[1,3],所取的范围是包括1和3的

用这种思路,我们定义出left为0, righ为数组长度-1。left<=right时,开始二分查找

先定义middle,应该是(left+right)/2,但这样写在极端情况下容易出错,如left+right超过int最大值,所以建议使用middle = left + (right - left)/2的写法(int类型的数除以2会自动忽略小数,但问题不大)

用middle把数组分成两半之后,检查target在数组的左边还是右边

如果在左边的话,就更新右边的边界为middle-1,如果在右边就更新左边界为middle+1

注意:写成middle自然也没有太大问题,但会让你的边界出错。因为这是一个左闭右闭的区间,经过一次二分后,你已经知道middle不是target,所以要把target丢出去,这样做可以严格限制边界,思路清晰,也可以减少运行的时间。

以此类推,不停地更新左右边界,直到left = right,此时left和right划出的范围内只有一个元素,如果这个元素还不是target,说明这个数组里面没有目标元素,随着right或者left的更新(middle±1),跳出循环

如果找到了目标元素(middle = target),则返回middle。

左闭右开
public static void main(String[] args) {
	int[] num1 = {0,1,3,4,6,7,8,9,10,25,100}; 
 //使用前提:数组递增或递减,数组内没有重复的数字    
	System.out.println(search02(num1, 6)); 
}
public static int search02(int[] num, int target){
    int left = 0;
    int right = num.length ;
    int middle;
    while (left < right){
        middle = left+(right-left)/2;
        if(target < num[middle]){
            right = middle;
        }else if (target > num[middle]){
            left = middle + 1;
        }else return middle;
    }
    return -1;
}

左闭右开仍然用数学举例,区间[1,3)包含数字1,不包含3,代码也类似,right取数组长度即可

当left<right的时候,进入循环,开始二分查找

与左闭右闭不同的是,如果target在middle左侧,定义右区间的时候right = middle

并不需要死记硬背,这是闭和开的关系,right在这里为开区间,所以right = middle

剩下的与左闭右闭的逻辑基本相同,不再赘述

下面是力扣的例题,可以自己尝试写一个出来

二分查找例题

移除数组元素

数组在计算机中存储的地址一般是连续的,这就导致 如果我们要删除数组中的一个元素的话,并不能直接抹除该元素,还要把删除元素后面的所有元素往前移一位。

以下是删除的第一种方法:使用两个for循环,第一个for循环负责找到目标元素,第二个for循环负责把元素后面的所有元素向前移

注意:删除执行完后要把i和size都自减,否则会漏元素

public static void main(String[] args) {
    int[] arr = {1,2,3,4,3,2,1,5,3,0};
    delete01(arr, 3);
	}
public static void delete01(int[] arr, int target){
    int size = arr.length;
    for (int i = 0; i < size-1; i++){
        if(arr[i] == target){
            for (int j = i+1; j <size; j++) {
                arr[j-1] = arr[j];
            }
            i--;
            size--;
        }
    }
    System.out.println("新数组为"+Arrays.toString(arr));
}

第二种方法:快慢指针法

使用两个指针,在一个for循环内完成数组的删除

public static void main(String[] args) {
        int[] arr = {1,2,3,4,3,2,1,5,3,0};
        delete02(arr,3); 
}    
public static void delete02(int[] arr, int target){
        int slow = 0;
        for (int fast = 0; fast <arr.length; fast++) {
            if(arr[fast]!= target){
                arr[slow] = arr[fast];
                slow++;
            }
        }
        System.out.println("新数组为"+Arrays.toString(arr));
    }
}

第二种方法中,要理解fast指针和slow指针分别代表的含义。fast指针的作用是找符合新数组条件的元素(文中为除了3以外的所有元素),slow指针的作用是找到新数组元素的位置

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值