704:二分查找
思想:通过不断缩小区间范围来搜索target
注意事项:注意区间范围
如果是[left,right]区间的话,需要判断left和right下标对应的值是否满足条件,因此初始的时候left=0,right=len-1,每次二分的时候找left和right的中间下标index,如果target比nums[index]小,right-1,如果比nums[index]大,left+1,如果等于的话说明找到了下标,直接return就行。左右都是闭区间的话,left==right是有意义的,所以得是while (left <= right)。例如数组只有一个元素5,target=5,那么只有while (left <= right)时才能进入循环。
如果是[left,right)的话,初始条件right=len,而不是len-1,右边的开区间,因此每次更新的时候right不需要减1,left==right也是没有意义的,因此直接是while (left < right)
具体实现:i表示左边,j表示右边,index的中点,res是返回值
代码:
1、左闭右闭
class Solution {
public int search(int[] nums, int target) {
int len = nums.length;
int i = 0, j = len-1, res = -1;
while(i<=j){
int index = (j+i)/2;
if(target<nums[index]){
j = index - 1;
}else if(target>nums[index]){
i = index + 1;
}else{
res = index;
break;
}
}
return res;
}
}
2、左闭右开
class Solution {
public int search(int[] nums, int target) {
int len = nums.length;
int i = 0, j = len, res = -1;
while(i<j){
int index = (i+j)/2;
if(target<nums[index]){
j = index;
}else if(target>nums[index]){
i = index + 1;
}else{
res = index;
break;
}
}
return res;
}
}
35:搜索插入位置
思想:利用二分法的思想使得时间复杂度为O(logn)
关键:找到的话直接返回数组下标,如果没找到的话“返回它将会被按顺序插入的位置”。对于左闭右闭的情况,循环结束的条件要么是找到了下标,如果没找到下标的话就是left=right+1,left所处的小标就应该是target按顺序应该插入的位置,所以应该return left。对于左闭右开的情况下,如果没找到下标,要么left=right+1或者left=right,所以还是返回left位置。
代码:
class Solution {
public int searchInsert(int[] nums, int target) {
int len = nums.length;
int left = 0, right = len - 1;
while(left<=right){
int index = (left + right)/2;
if(target<nums[index]){
right = index - 1;
}else if(target>nums[index]){
left = index + 1;
}else{
return index;
}
}
return left;
}
}
方法:在二分法查找的基础上,先找到元素所在的位置,然后再通过左右滑动查找左边界和右边界。
代码:
class Solution {
public int[] searchRange(int[] nums, int target) {
int len = nums.length;
int left = 0, right = len - 1;
int[] res = {-1,-1};
while(left<=right){
int index = (left + right)/2;
if(target<nums[index]){
right = index - 1;
}else if(target>nums[index]){
left = index + 1;
}else{
for(int i =index;i>=left;i--){
if(nums[i]!=target){
res[0] = i+1;
break;
}else{
res[0] = left;
}
}
for(int j=index;j<=right;j++){
if(nums[j]!=target){
res[1] = j-1;
break;
}else{
res[1] = right;
}
}
break;
}
}
return res;
}
}
27:移除元素
思想:双指针法:通过快指针和慢指针把不等于val的元素往前靠。筛选掉val,val的位置空出来,就可以插入后面的值。
代码:
class Solution {
public int removeElement(int[] nums, int val) {
int len = nums.length;
int slowIndex=0;
for(int fastIndex=0;fastIndex<len;fastIndex++){
if(val!=nums[fastIndex]){
nums[slowIndex++]=nums[fastIndex];
}
}
return slowIndex;
}
}
今日感想:
算法思路理解和代码实现还是有一定区别的,再理清算法思路的基础上,代码实现还需要考虑更多的细节。