目录
704
代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
int n = nums.size(); // 数组长度
int left = 0, right = n - 1;
int mid;
while (left <= right) // 难点,这里的右边是数组的右端元素,所以要写等于
{
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;//找不到,返回-1
}
};
mid = left + (right - left) / 2; 和 mid = (left + right) / 2;
上面这两行代码在我们人眼中是一样的,但编译器不这么认为
采用第二种写法,很容易出现数据溢出现象
在C++中,int型数据的取值范围是:-2147483648 ~ 2147483647 大约就是-20E ~ +20E
举个例子,如left是15E,right是18E,那么left+right就是33E,超过了int的上限,即数据溢出了
数据溢出有什么后果呢?
通过下面的程序,我们可以看出,我们得不到想到的数据。至于为什么结果是 -994967296,这个就需要一些额外知识
在计算机中,任何数据都是以补码的形式存储的
int型 1500000000 补码:0101 1001 0110 1000 0010 1111 0000 0000
int型 1800000000 补码:0110 1011 0100 1001 1101 0010 0000 0000
然后把上面两个二进制数相加得:1100 0100 1011 0010 0000 0001 0000 0000 这是某个int型数的补码
我们把这个二进制补码转成十进制就是 -994967296
27
写一个从向量中移除所有等于val
的元素,并返回移除后向量的大小。
暴力解法
int removeElement(vector<int>& nums, int val)
{
int n = nums.size();
for (int i = 0; i < n; i++) //i会在循环结束后+1
{
if (nums[i] == val)
{
for (int j = i; j < n-1; j++)
{
nums[j] = nums[j+1]; // 前移一位
}
nums.pop_back();//要移除的元素已经被后面逐渐覆盖掉了,最后一个元素还是最后一个元素,所以要pop_back();
n--;
i--; //重新检查当前位置的元素是否等于要移除的值
}
}
return n;
}
快慢指针:
int removeElement(vector<int> &nums, int val)
{
int n = nums.size();
if (n == 0)
{
return 0;
}
int fast = 0, slow = 0;
while (fast < n)
{
if (nums[fast] != val)
{
nums[slow] = nums[fast];
slow++;
}
fast++;
}
int k = (fast - slow); // 要移除尾部k个元素
// 下面这个for循环是不是可以不要?
for (int i = 0; i < k; i++)
{
nums.pop_back();
}
return n - k;
}
// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
if (val != nums[fastIndex]) {
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
};