704.二分法查找
前提条件
- 使用二分法查找,需要提前将数组排序
- 可使用
Arrays.sort(数组名);
对数组进行排序 - 数组中没有重复的元素
题目
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/binary-search
过程:
- 设定左指针(left),右指针(right) 和 中间指针(middle)
- 定位中间位置(left + (right - left) / 2),并判断 下标值 == target
nums[middle] == target 则返回该位置下标
nums[middle] > target 则右侧指针移到中间
nums[middle] < target 则左侧指针移到中间
解法一(左闭右闭,left <= right)
- 时间复杂度:O(logN)
- 空间复杂度:O(1)
class Solution {
public int search(int[] nums, int target) {
if(nums == null || nums.length == 0) return -1;
// 避免多次循环运算
if(target > nums[nums.length - 1] || target < nums[0]) return -1;
//左指针
int left = 0;
//右指针
//数组长度减1才能定位到数组末尾下标的位置上
int right = nums.length - 1;
//循环,定义target在 [left, right] 左闭右闭的区间
while(left <= right){
//防止溢出,用(left + right) / 2会有溢出的现象
int middle = left + (right - left) / 2;
//判定target值的大小,定义值位置
if(target < nums[middle]){
//target在左区间 [left, middle - 1]
right = middle - 1;
}else if(target > nums[middle]){
//target在右区间 [middle - 1, right]
left = middle + 1;
}else{
//target == nums[middle],输出下标值
return middle;
}
}
//target不再数组nums[]范围内,输出-1
return -1;
}
}
解法二(左闭右开,left < right)
- 时间复杂度:O(logN)
- 空间复杂度:O(1)
class Solution {
public int search(int[] nums, int target) {
//左指针
int left = 0;
//右指针
//数组长度减1才能定位到数组末尾下标的位置上
int right = nums.length;
//循环,定义target在 [left, right) 左闭右开的区间
//当left == right 时,[left, right)时无效区间
while(left < right){
//防止溢出,用(left + right) / 2会有溢出的现象
int middle = left + (right - left) / 2;
//判定target值的大小,定义值位置
if(target < nums[middle]){
//target在左区间 [left, middle)
right = middle;
}else if(target > nums[middle]){
//target在右区间 [middle + 1, right)
left = middle + 1;
}else{
//target == nums[middle],输出下标值
return middle;
}
}
//target不再数组nums[]范围内,输出-1
return -1;
}
}
27.移除元素
题目
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-element
快慢指针法(双指针法)
- 时间复杂度:O(n)
- 空间复杂度:O(1)
class Solution {
public int removeElement(int nums[], int val) {
//慢指针
int slow = 0;
//快指针(fast),循环
for(int fast = 0; fast < nums.length; fast++){
//判断,val不等于nums[fast]时,将nums[fast]值传入到slow数组中
if(val != nums[fast]){
//slow++,将slow下一个下标位置腾出来
nums[slow++] = nums[fast];
//可以将nums[slow++]拆分
//nums[slow] = nums[fast];
//slow++;
}
}
return slow;
}
}
首尾双指针法
class Solution {
public int removeElement(int[] nums, int val) {
int left = 0;
int right = nums.length - 1;
// 让right从尾找到数值不为val的第一个元素
while(right >= 0 && nums[right] == val) right--;
while(left <= right){
if(nums[left] == val){
nums[left] = nums[right];
right--;
}
left++;
// 在将不为val的值赋给left之后,继续寻找下一个不为val的元素
while(right >= 0 && nums[right] == val) right--;
}
return left;
}
}