704.二分查找
题目链接: 704.二分查找
方法一:直接遍历
for( i = 0; i <= nums.length-1; i++){
if(nums[i] == target){
return i;
}
}
return -1;
}
方法二:二分查找
适用前提:
1.数组内部已经是有序序列
2.数组中无重复元素,因为有重复元素的情况下,二分法所返回的元素下标不唯一
二分法还需要注意的一点是target所在区间两端是闭还是开,区别主要在于while寻找中每一次边界的处理,即循环不变量原则。
首先是左闭右闭区间(即**[left,right]**)的写法。
int search(int* nums, int numsSize, int target){
int left = 0, right = numsSize-1, middle = 0;
while(left <= right){ //定义target在左闭右闭区间,即[left,right]
middle = ( left + right )/2;//这里应该可以改进为middle = left + ((right - left)) / 2 可以防止溢出
if ( nums[middle] < target ){
left = middle + 1; //target位于右区间,更新left,即查询[middle+1,right]
}else if( nums[middle] > target ){
right = middle - 1;//target位于左区间,更新right,即查询[left,middle-1]
}else{//nums[middle] == target
return middle;//返回下标
}
}
//未找到目标值
return -1;
}
再给出左闭右开(即**[left,right)**)的写法,需要注意的是,由于区间是[left,right),则二分法的边界处理方式会有所不同。
具体体现在如下两点:
- while(left < right),这里只能用<,因为对该区间而言left==right是毫无意义的。
- if(nums[middle] > target)的情况下,right更新为middle,因为当前的nums[middle]不等于target,要到middle的左边区间寻找,因为寻找的区间是左闭右开区间,所以right需要更新为middle,也就是使得下一个查询区间不会比较nums[middle]的值。
int search(int* nums, int numsSize, int target){
int left = 0, right = numsSize-1, middle = 0;
while(left < right){//定义target在左闭右开区间,即[left,right)
middle = left +(( right - left )/2);
if ( nums[middle] < target ){
left = middle + 1;//target位于右区间,更新left,即查询[middle+1,right]
}else if( nums[middle] > target ){
right = middle;//target位于左区间,更新right,即查询[left,middle]
}else{//nums[middle] == target直接返回下标
return middle;
}
}
//未找到目标值
return -1;
}
题目链接: 27.移除元素
方法一:暴力解法
使用两个for循环,第一个用来循环遍历数组元素,第二个则负责循环更新数组。显然暴力解法的时间复杂度伟O(n^2)
代码如下
int removeElement(int* nums, int numsSize, int val){
int size = numsSize;
for(int i = 0; i < size; i++){
if(nums[i] == val){
for(int j = i; j < numsSize-1; j ++){//若j初值赋为i+1,则判断条件要改为j<size,移动元素语句改为nums[j-1] = nums[j];
nums[j] = nums[j+1];
}
i--;
size--;
}
}
return size;
}
方法二:双指针法
即快慢指针法:通过一快一慢两个指针,在一个for循环下完成暴力解法中两个for循环的工作。
int removeElement(int* nums, int numsSize, int val){
int size = numsSize;
int fast = 0, slow = 0;//定义快慢两个指针,快指针用于遍历数组找出新数组所需元素,满指针用于存放新数组元素
for(fast = 0; fast < size; fast ++){
if(nums[fast] != val){//新数组所需元素
nums[slow] = nums[fast];//将新数组所需元素放到新数组中
slow++;//元素存入新数组后慢指针向后移
}
}
return slow;//slow恰好是新数组的长度
}
双指针法的时间复杂度为O(n)。