704. 二分查找
题目链接:
704. 二分查找 - 力扣(LeetCode)
解题思路:
//左闭右闭
int search(int* nums, int numsSize, int target) {
int length = numsSize;
int left = 0;
int right = length-1; //length比数组下标大1,故左闭右闭时right要length-1
int ret = -1;
int middle = 0;
while (left <= right) {
middle = (left + right)/2;
if (nums[middle] < target) {
left = middle + 1;
} else if (nums[middle] > target) {
right = middle - 1; //这里就要减一了,因为区间是[left,middle-1]
} else {
ret = middle;
break;
}
}
return ret;
}
//左闭右开
int search(int* nums, int numsSize, int target) {
int length = numsSize;
int left = 0;
int right = length;
int middle = 0;
int ret = -1;
while (left < right) { //这里因为右开left不能等于right,否则区间不合法
middle = (left+right)/2;
if (nums[middle] > target){
right = middle; //这里不减1,因为target在[left,middle)区间里
}else if (nums[middle] < target) {
left = middle + 1;
}else {
ret = middle;
break;
}
}
return ret;
}
该题总结:我是真正一点算法题都没做过,从零开始的小白,感觉这个二分查找的两种方法都蛮简单的,二分法的关键在于区间定义,只要脑子里想着保证区间合法,有没有等于号,要不要减一,就一目了然了。
35.搜索插入位置
解题思路:
//左闭右开二分法
int searchInsert(int* nums, int numsSize, int target) {
int left = 0;
int right = numsSize;
int mid = 0;
while (left < right) {
mid = left + (right - left)/2;
if (nums[mid] < target) {
left = mid + 1;
}else if (nums[mid] > target) {
right = mid;
}else {
return mid; //nums[mid] == target时该mid就是要插入的位置
}
}
return right; //没有找到时直接插入到最右边
}
该题总结:题是简单题,就是在想新的元素要放在哪的时候,也就是return什么的时候有点晕,要想一会儿。
34. 在排序数组中查找元素的第一个和最后一个位置
解题思路:
//这题用左闭右闭要比左闭右开容易思考
int searchLeftborder(int *nums,int numsSize,int target) { //找左边界
int left = 0;
int right = numsSize - 1;
int mid = 0;
int leftborder = -1;
while (left <= right) {
mid = left + (right - left)/2;
if (nums[mid] == target) {
leftborder = mid;
right = mid - 1;
} else if (nums[mid] >target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return leftborder;
}
//左右边界找法思路上是对称的
int searchRightborder(int *nums,int numsSize,int target) { //找右边界
int left = 0;
int right = numsSize - 1;
int mid = 0;
int rightborder = -1;
while (left <= right) {
mid = left + (right - left)/2;
if (nums[mid] == target) {
rightborder = mid;
left = mid + 1;
} else if (nums[mid] > target) {
right = mid -1;
} else {
left = mid + 1;
}
}
return rightborder;
}
int* searchRange(int* nums, int numsSize, int target, int* returnSize) {
int leftborder = searchLeftborder(nums,numsSize,target);
int rightborder = searchRightborder(nums,numsSize,target);
*returnSize = 2; //这里必须要定义返回数组的大小,虽然后面用不到
int *resNums = (int*)malloc(sizeof(int) * 2);
resNums[0] = leftborder;
resNums[1] = rightborder;
return resNums;
}
该题总结:这个中等题,一开始给哥们搞得焦头烂额的,他的左边界和右边界的算法,对于我这种小白来说真是费脑子,不过最后终于还是弄明白了,花了得有两个小时就这一道题。
27. 移除元素
题目链接:
27. 移除元素 - 力扣(LeetCode)
解题思路:
//双指针法是这题的精髓
int removeElement(int* nums, int numsSize, int val) {
int slow = 0;//慢指针
for (int fast = 0; fast < numsSize; fast++) { //快指针
if (nums[fast] != val) { //快指针所指元素非val时,将快指针所指的值赋给慢指针所指的值
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
该题总结:在刚才那道题烧了半天脑之后迎来一道思路很舒服的题,不管是暴力解法还是双指针法都很简单,主要还是要学习一下双指针法这种思路,真的很nice。
总耗时约5小时左右,主要是第一次写题,也是第一次写博客,花了好长时间