704. 二分查找
题目:给定一个
n
个元素有序的(升序)整型数组nums
和一个目标值target
,写一个函数搜索nums
中的target
,如果目标值存在返回下标,否则返回-1
。
二分法两种情况,区间左闭右闭&左闭右开
使用条件:数组为有序数组,且不存在重复元素。
1.左闭右闭 (右指针为nums.length - 1)
class Solution {
public int search(int[] nums, int target) {
if(target < nums[0] || target > nums[nums.length - 1]){
return -1;
}//确保target在[nums.min,nums.max]区间内,nums为有序数组,所以只需target大于首元素,小于尾元素。
int left = 0;//定义左指针
int right = nums.length - 1;//定义右指针,确定为左闭右闭区间
while(left <= right){//left == right在循环内,区间为[left, right]
int middle = left + (right - left)/2;//防止(right + left)整型溢出
if(target < nums[middle]){
right = middle - 1;//右闭区间,一定target != middle,直接指向middle左边一位
}else if(target > nums[middle]){
left = middle + 1;///左闭区间,一定target != middle,直接指向middle右边一位
}else
{
return middle;
}
}
return -1;
}
}
2.左闭右开(右指针为nums.length)
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;//区间右开
while(left < right){//左闭右开,left == right不在循环内
int middle = left + (right - left)/2;
if(target < nums[middle]){
right = middle;//因为右开区间,所以middle不减一,即target在[left,middle)中,也就是[left,middle - 1]
}else if(target > nums[middle]){
left = middle + 1;
}else
{
return middle;
}
}
return -1;
}
27.移除数组
题目:
给你一个数组
nums
和一个值val
,你需要 原地 移除所有数值等于val
的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用
O(1)
额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
方法: 1.暴力求解;2.快慢指针;3.双向指针
tips:数组地址连续,原地移除意味着不可跳过,即移除后,该位置之后的元素全部前移一位。
1.暴力求解
class Solution {
public int removeElement(int[] nums, int val) {
if (nums.length == 0){//确保不是空数组
return 0;
}
int length = nums.length;
for (int i = 0; i < length; i++){//从左到右遍历寻找值为val的元素
if (nums[i] == val){
for (int j = i + 1; j < length; j++){
nums[j - 1] = nums[j];
}//找到值val的元素之后,元素的位置是nums[i],将i后的元素遍历向前移动一位
i--;// 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
length--;//前移导致数组大小-1
}
}
return length;//全部遍历完之后,返回数组大小
}
}
2.快慢指针
class Solution {
public int removeElement(int[] nums, int val) {
if (nums.length == 0){
return 0;
}
int slow = 0;//定义慢指针
for (int fast = 0; fast < nums.length; fast++ ){定义快指针fast
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++;
}//快慢指针核心:如果没找到val,快慢指针保持同速递加;当快指针遇到val时,慢指针不再slow++
//下一轮迭代slow指向val所在的地址,fast指向下一个地址,将fast指针的值赋给slow指针完成前移。
}
return slow;//返回慢指针即数组大小
}
}
3.相向指针
class Solution {
public int removeElement(int[] nums, int val) {
if (nums.length == 0){
return 0;
}
int left = 0;//定义左指针
int right = nums.length - 1;//定义右指针
while (left <= right){//左右指针不相遇,循环一直执行。
if (nums[left] == val){
nums[left] = nums[right];
right--;
}else{
left++;
}//左指针不与val相遇,一直保持右移;相遇时,直接把右指针的值赋给left指针的值,同时右指针左移。最终完成遍历。
}
return left;
}
}