数组基础知识:
1、数组的下标是从0开始
2、数组内存空间是连续的(对于一个int型的数组、其两个相邻元素的地址差4个字节)
3、数字不能直接删除、只能对其进行覆盖操作
题目描述
给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回 -1
。
视频讲解:手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找_哔哩哔哩_bilibili
个人思路:
因为题目提示了nums中所有的元素都是不重复的,所以第一想法就是利用for循环遍历数组元素,判断是否与target相等,如果相等则返回其下标;其代码实现如下:
class Solution {
public:
int search(vector<int>& nums, int target) {
for (int i = 0; i < nums.size(); ++i) {
if (nums[i] == target) {
return i; // 如果找到目标值,返回其索引
}
}
return -1; // 如果遍历完数组后仍未找到目标值,返回-1
}
};
这样方法实现确实比较简洁,但是相比于后面的二分法,其在时间复杂度上为O(n),空间复杂度O(1);
二分法实现:
二分法的使用前提:这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件,当大家看到题目描述满足如上条件的时候,可要想一想是不是可以用二分法了。
注意事项:
注意二分法的边界条件,其具体分为左闭右闭和左闭右开,不同的情况下对应的边界条件是不同的,个人感觉主要记住一种就行,以避免混淆,这里主要了解左闭右闭的这种情况,也就是[left, right] 。
区间的定义这就决定了二分法的代码应该如何写,因为定义target在[left, right]区间,所以有如下两点:
- while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
- if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1。
左闭右闭的代码实现
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0;
int 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 -1;
}
};
时间复杂度:O(logn)
空间复杂度:O(1)
视频讲解:数组中移除元素并不容易!LeetCode:27. 移除元素
题目描述:
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素。元素的顺序可能发生改变。然后返回 nums
中与 val
不同的元素的数量。
假设 nums
中不等于 val
的元素数量为 k
,要通过此题,您需要执行以下操作:
- 更改
nums
数组,使nums
的前k
个元素包含不等于val
的元素。nums
的其余元素和nums
的大小并不重要。 - 返回
k
。
个人思路:首先想到的肯定是用for循环去遍历,然后对每个数组元素进行判断,然后再用for循环对数组进行操作,这种暴力解法,原理上是可行的,但是可能会超出内存限制。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size=nums.size();
for(int i=0;i<size;i++){
if(nums[i]==val){
for(int j=i+1;j<size;j++){
nums[i]=nums[j];
}
size--;
i--;
}
}
return size;
}
};
时间复杂度:O(n^2)
空间复杂度:O(1)
双指针:通过快慢指针在一个for循环下面完成两个for循环的工作。
思路:
定义快慢指针
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新 新数组下标的位置
//双指针
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int left=0;
int right=nums.size();
for(int i=0;i<right;i++){
if(nums[i]!=val){
nums[left++]=nums[i];
}
}
return left;
}
};