数组理论基础
数组是存放在连续内存空间上的相同类型数据的集合,今天刚学习了操作系统的相关知识,也放进来,为了使的CPU缓存命中率高,尽量保证数组连续
要注意vector 和 array的区别,vector的底层实现是array,严格来讲vector是容器,不是数组。
数组的元素是不能删的,只能覆盖。
看到题目的第一想法是暴力解法,但仔细一看发现数组是有序的,加上题目提示有二分查找,然后想到一个数除以2包含了奇数与偶数,先考虑一下奇数偶数的情况,然后再分析是否需要区分奇数偶数。二分法这里还需要注意的前提是再有序数组中使用。
还需要考虑循环以及退出循环操作,最开始想使用while(nums[tmp]!=target)然后发现不可行,因为进行多次二分查找后,无法比较好的表示左右区间。想到定义left和right进行解决。因此,首先想到的循环条件为while(left<right),然后想终止条件,虽然能跑出来,但是感觉是按照答案写题目了,会卡在循环终止的情况下。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0;
int right=nums.size();
int tmp=(right-left)/2;
if (nums[left] == target)return left;
while(left<right-1){
if(nums[tmp]>target){
right=tmp;
}
else if(nums[tmp]==target){
return tmp;
}
else{
left=tmp;
}
tmp = left + (right - left) / 2;
}
return -1;
}
};
看了一下解析,发现不必死死地卡在right=tmp上,因为本来就不相等,可以往前移一位。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left=0;
int right=nums.size();
int tmp=(right-left)/2;
while(left<right){
if(nums[tmp]>target){
right=tmp;
}
else if(nums[tmp]==target){
return tmp;
}
else{
left=tmp+1;
}
tmp = left + (right - left) / 2;
}
return -1;
}
};
需要理解并掌握二分法的相关知识,写二分法经常写乱,主要是因为对区间的定义没有想清楚,区间的定义就是不变量。二分法包含了两种情况,一种是左闭右开区间,还有一种是左闭右闭区间,上面这种做法属于左闭右开区间这种情况,因为right是无法取到的,只有[left,right),所以left不可以等于right,由于是左闭右开区间,进行下一次循环时,right还是无法取到,所以right不用-1,而left需要+1。同理,可以理解左闭右闭区间的情况。
//用双指针的方法,使用一个快指针核一个慢指针,快指针指向新数组所需要的元素。新数组的坐标值应该使用慢指针
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow{0};
for(int fast{0};fast<nums.size();fast++){
if(nums[fast]!=val){
nums[slow]=nums[fast];
slow++;
}
}
//最后输出不需要++slow,因为前面已经slow++了,说明以及那个大一位了
return slow;
}
};
// 传统的暴力法
/*class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size();
for (int i = 0; i < len; i++)
{
int flag = 0;
if (nums[i] == val)
{
for (int j = i; j < len && nums[j] == val; j++)
{
flag++;
}
len -= flag;
for (int j = i; j < len; j++)
{
nums[j] = nums[j + flag];
}
}
}
return len;
}
};*/