数组理论知识:从0开始,地址连续
只能覆盖不能删除
704. 二分查找
初步想法:遍历搜索数组,查找target;两端逼近搜索(二分)
阅读后想法:
1. 使用二分法,考虑采用左闭右闭的方式 [left, right],在区间范围内代表有意义的数(所寻找的target包含在其中),因此当 arr[mid]!=target的情况下,需要排除mid这个点,进行left=mid+1或者right=mid-1;
2. 当left==right的情况下,[left, right]是有意义的,还会进行点搜索;
3. 进行初始化的时候,right需有意义是考虑的点,因此right = arr.size()-1.
class Solution {
public:
int search(vector& nums, int target) {
int right = nums.size()-1;
int left = 0;
while(left<=right) {
int mid = (left+right)/2;
if(nums[mid]==target) {
return mid;
}else if(nums[mid]>target) {
right = mid-1;
}else {
left = mid+1;
}
}
return -1;
}
};
拓展题:35、34
27. 移除元素
初步想法:数组只能进行覆盖,发现元素整体(后方元素s)往前移动;双指针(类似快慢指针),一个指针搜索,一个指针记录索引位置,边寻找边插入
阅读后想法:使用双指针
a. 暴力解法(练习暴力)
1. size记录数组大小,当删除一个元素后size缩小;
2. i为遍历索引下标,当往前移时,i需要保持不变(新的arr[i]),i--;
class Solution {
public:
int removeElement(vector& nums, int val) {
int size = nums.size();
// 进行遍历
for(int i=0; i
b. 双指针(快慢指针应用)
class Solution {
public:
int removeElement(vector& nums, int val) {
// 快慢指针
int slow = 0; // 记录索引
int fast = 0; // 访问下标索引
int size = nums.size()-1;
while(fast<=size) {
if(nums[fast]==val) {
// 需要被覆盖,不被写入
fast++;
}else {
nums[slow++] = nums[fast++];
}
}
return slow;
}
};
拓展题:
35. 搜索插入位置
a. 暴力解法
想法:遍历的方式,寻找大于或等于的情况
思路:只有四种情况
1. 元素小于数组所有元素
2. 元素等于数组中某个元素
3. 元素插入到数组中某个下标
4. 元素大于数组中所有元素
class Solution {
public:
int searchInsert(vector& nums, int target) {
for(int i=0; i=target) {
return i;
}
}
return nums.size();
}
};
b. 二分法
循环不变量:在这个范围内[left, right]寻找target
class Solution {
public:
int searchInsert(vector& nums, int target) {
int left = 0;
int right = nums.size()-1;
while(left<=right) {
int mid = (left+right)/2;
if(nums[mid]target) {
right = mid-1;
}else {
return mid;
}
}
return right+1;
}
};
34. 在排序数组中查找元素的第一个和最后一个位置
想法:需要寻找第一个=target的下标,和第一个>=target的下标
范围:[left, right]
思路:
1. 第一个位置:左边寻找,缩小right(靠左)
当找到=target的位置,尽可能继续搜索左部分(改right),寻找第一个
2. 最后一个位置:右边寻找,扩大left(靠右)
当找到target的位置,尽可能继续搜索右部分(改left),寻找最后一个
class Solution {
public:
int findLastIndex(vector& nums, int target) {
int left = 0;
int right = nums.size()-1;
int rightBoard = -2;
while(left<=right) {
int mid = (left+right)/2;
if(nums[mid]>target) {
right = mid-1;
}else if(nums[mid]<=target) {
left = mid+1;
rightBoard = left;
}
}
return rightBoard;
}
int findOneIndex(vector& nums, int target) {
int left = 0;
int right = nums.size()-1;
int leftBoard = -2;
while(left<=right) {
int mid = (left+right)/2;
if(nums[mid]>=target) {
right = mid-1;
leftBoard = right;
}else if(nums[mid] searchRange(vector& nums, int target) {
int rightBoard = findLastIndex(nums, target);
int leftBoard = findOneIndex(nums, target);
if(rightBoard==-2 || leftBoard==-2) {
return {-1, -1};
}
if(rightBoard-leftBoard>1) {
return {leftBoard+1, rightBoard-1};
}
return {-1, -1};
}
};