Day1-数组part01
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- Day1-数组part01
- 704. [二分查找](https://leetcode.cn/problems/binary-search/)
- 一、官方题解
- 二、实现代码
- 27. [移除元素](https://leetcode.cn/problems/remove-element/)
- 二、实现代码
- 35. [搜索插入位置](https://leetcode.cn/problems/search-insert-position/)
- 二、实现代码
- 34. [在排序数组中查找元素的第一个和最后一个位置](https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/)
- 二、实现代码
- 总结
704. 二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
一、官方题解
二、实现代码
1.代码
class Solution:
def search(self, nums: List[int], target: int) -> int:
n = len(nums)
left,right = 0,n - 1
while left <= right:
# mid = (left + right)//2
mid = left + (right - left)//2
if nums[mid] > target:
right = mid - 1
elif nums[mid] < target:
left = mid + 1
else:
return mid
return -1
2.bug
- 多个变量名赋值 left,right = 0,n - 1
- 循环while条件不需要括号(),也不需要大括号{};
- if循环 if;elif:else
- 运算符除法为‘//’而不是‘/’
- c++使用if {}else if{} else{}
27. 移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
二、实现代码
1.代码
- 暴力前移
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int ans = nums.size();
for(int i = 0;i < ans;i++){
if(nums[i] == val)
{
for(int j = i+1;j < ans;j++){
nums[j-1] = nums[j];
}
i--;
ans--;
}
}
return ans;
}
};
- 双指针法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
//双指针
int left = 0,right = 0;
for(int right = 0;right < nums.size();right++){
if(nums[right] != val){
nums[left++] = nums[right];
}
}
return left;
}
};
2.bug
- 循环的时候设置边界为nums.size()不合理,因为已经移除了前面的val了
- 所有元素前移一位以后,判断也要前移 i–
35. 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
二、实现代码
1.代码
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while(left <= right){
int mid = left + ((right - left)/2);
if(nums[mid] > target)
right = mid - 1;
else if(nums[mid] < target)
left = mid + 1;
else
return mid;
}
return left;
}
};
2.bug
- 目标值在数组中返回mid即可,没在数组中总结两种特殊情况得知插入位置为left下标。
34. 在排序数组中查找元素的第一个和最后一个位置
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
二、实现代码
1.代码
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int s = 0, t = 0;
int len = nums.size() ;
if(len == 0)
return {-1, -1};
int left = 0,right = nums.size() - 1;
while(left <= right){
int mid = left + ((right - left)/2);
if(nums[mid] > target)
right = mid - 1;
else if(nums[mid] < target)
left = mid + 1;
else{
//记录下此刻的l,r
s = left;
while(nums[s] < target && s < len){
s++;
}
if(nums[s] == target && nums[right] == target)
return {s,right};
t = s;
//出问题了
// while(nums[t] == target && t < len - 1){
// t++;
// }
while(t < len - 1){
t++;
if(nums[t] > target)
break;
}
if(s == t) return {s,t};
else return {s,t-1};
}
}
return {-1, -1};
}
};
2.bug
- 锁定范围在[left,right]但却没有判断好边界条件 改进:二分法找到范围以后,while判断指针下一个值eg.nums[t+1] == target来进行边界处理
总结
- 在升序数组中查找目标值target,我们知道当当前值小于target,那么target所处位置下标在其右端区间,当当前值大于target,那么target所处位置下标在其左端区间,故我们使用二分法,在给定区间[letf,right]内取其中点下标mid,比较mid所在值和target大小,如果相等就是我们要查找的目标值,如果mid所在值>target,说明目标值在mid的左边区间,如果mid所在值<target,说明目标值在mid的右边区间
- 两个临界点:while和区间取值。
- 如果是左闭右闭,那么while要取小于等于,由于区间为闭区间代表端点处已经参与比较,故取端点-1,+1;