重点:区分两种写法,并理解其本质(边界条件的处理)
1.左闭右闭
package day1;
public class 二分查找1左闭右闭 {
public static void main(String[] args) {
int[] arr = {-1,0,3,5,9,12};
int target = 9;
int i = find(arr, target);
System.out.println(i);
}
public static int find(int[] arr,int target) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
//1定义区间时,左临界和右临界是包括再内的,因此两者相等有意义
int mid = (left + right)/2;
if (target < arr[mid]){
right = mid - 1;
//因为右临界已经判断过不等于target了,因此右临界更新为mid-1,下面左邻界也同理
}else if(target > arr[mid]){
left = mid + 1;
}else {
return mid;
}
}
return -1;
}
}
2.左闭右开
package day1;
public class 二分查找0左闭右开 {
public static void main(String[] args) {
int[] arr = {-1,0,3,5,9,12};
int target = 9;
int i = find(arr, target);
System.out.println(i);
}
public static int find(int[] arr,int target) {
int left = 0;
int right = arr.length;
//1定义区间时,右临界不包括在内,想要查找整个数组,就应该让右临界取最大索引加一,即数组长度
while (left < right) {
//2定义区间时,左临界包括再内的,而右临界不包括在内,两者相等无意义,因此不取等
int mid = (left + right)/2;
if (target < arr[mid]){
right = mid;
//3右临界不在区间内,因此就算右临界不等于target,让右临界等于mid也无妨
}else if(target > arr[mid]){
left = mid + 1;
}else {
return mid;
}
}
return -1;
}
}
方法1.单指针双循环
package day1;
import java.util.Arrays;
public class 移除元素0单指针 {
public static void main(String[] args) {
int[] nums = {0,1,2,2,3,0,4,2};
int val = 2;
int newLen = updateArrLenth(nums, val);
System.out.println(Arrays.toString(nums));
System.out.println(newLen);
}
public static int updateArrLenth(int[] nums, int val) {
int len = nums.length;
for (int i = 0; i < len; i++) {
//1指针指向索引0,向后移动
if (nums[i] == val) {
//2如果指针指到要删除的值,就把数组后面的数全部向前覆盖一位
for (int i1 = i; i1 < nums.length - 1; i1++) {
nums[i1] = nums[i1 + 1];
}
len--;
i--;//注意覆盖完后,指针不要动,继续下个循环判断
}
}
return len;
}
}
方法2.双指针单循环
package day1;
import java.util.Arrays;
public class 移除元素1双指针 {
public static void main(String[] args) {
int[] nums = {0, 1, 2, 2, 3, 0, 4, 2};
int val = 2;
int newLen = updateArrLenth(nums, val);
System.out.println(Arrays.toString(nums));
System.out.println(newLen);
}
public static int updateArrLenth(int[] nums, int val) {
int len = nums.length;
int slowIndex = 0;
//1定义两个指针:快指针,慢指针,都指向索引0,快指针向后移动
for (int fastIndex = 0; fastIndex < len; fastIndex++) {
if (nums[fastIndex] != val) {
//2如果快指针指向的数不是要被删除的,就让这个数覆盖掉慢指针指向的数
nums[slowIndex] = nums[fastIndex];
slowIndex ++;//慢指针向后移动一位继续等着被覆盖
}//该方法相当于在原来的数组上拷贝
}
return slowIndex;//此时慢指针的值就是删除元素后数组的长度
}
}