704二分查找
题目链接:力扣-704.二分查找
思路:
二分查找使用的前提条件:
- 有序数组
- 无重复元素
定义初始查找范围 [left,right],初始查找范围是整个数组。每次取查找范围的中点,比较其与目标元素的大小。
- 若target<middle,查找范围在左半边,查找区间为[left,middle-1],更新right的值。
- 若target>middle,查找范围在右半边,查找区间为[middle+1,right],更新left的值。
- 若target=middle,该点即为所求下标。
需要注意区间的闭合,一般有两种情况,[ left , right ] 或 [ left , right ),所对应的代码也不一样。
二分法第一种写法:
int search(int* nums, int numsSize, int target){
int left = 0;
int right = numsSize - 1;
int middle = 0;
while(left <= right){
middle = (left + right)/2;
if(target < nums[middle]){
right = middle - 1;
}
else if(target > nums[middle]){
left = middle + 1;
}
else if(target == nums[middle]){
return middle;
}
}
return -1;
}
二分法第二种写法:
int search(int* nums, int numsSize, int target){
int left = 0;
int right = numsSize - 1;
int middle = 0;
while(left < right){
middle = (left + right)/2;
if(target < nums[middle]){
right = middle;
}
else if(target > nums[middle]){
left = middle + 1;
}
else if(target == nums[middle]){
return middle;
}
}
return -1;
}
27.移除元素
题目链接:力扣-27.移除元素
思路:
- 暴力法:利用两层for循环,第一个for循环用于查找要移除的元素,第二个for循环用于删除元素(即进行元素覆盖)
- 双指针法:利用两个指针,快指针用于寻找新数组的元素,慢指针用来更新新数组的位置。
用一层for循环来时快指针移动,当找到移除元素时,跳过该值,慢指针此时指向的位置不变;当找到非移除元素时,将该元素赋值给慢指针所指向的位置,完成元素覆盖,随后慢指针向前移动。重复以上操作,直至快指针指向最后一个元素,最后慢指针的大小就是新的数组的大小。双指针法比暴力法效率更高,时间复杂度更低。
暴力法:
int removeElement(int* nums, int numsSize, int val){
int i, j;
for(i = 0; i < numsSize; i++){
if(nums[i] == val){
for(j = i + 1; j < numsSize; j++){
nums[j-1] = nums[j];
}
i--;
numsSize--;
}
}
return numsSize;
}
二分法:
int removeElement(int* nums, int numsSize, int val){
int fast = 0;
int slow = 0;
for(fast; fast < numsSize; fast++){
if(nums[fast] != val){
nums[slow++] = nums[fast];
}
}
return slow;
}
总结:
刷算法的第一天,感觉到了自己知识体系的匮乏,对于数据结构的基础打的并不好,除了移除元素用暴力法解出来了以外,其他的都是先去看了题解和视频,自己在动手写出来的。二分法曾经学过,但没有动手去做过该类的题目,导致写出了以下啼笑皆非的代码。双指针法第一次认识到,有一种打开新世界大门的感觉,接下来会花大量时间重新学习数据结构,继续力扣刷题,提高自己的算法能力!