704原文:代码随想录 (programmercarl.com)
27原文:代码随想录 (programmercarl.com)
二分查找
题目简述
一个有序数组中找到目标值,返回其位置
思路
先设定初始区间,左和右。
闭区间
先找中间值,如果中间值大于目标值,目标值在左边,中间值也比过了,right变成middle-1。如果中间值小于目标值,目标值在右边,中间值也比了,left变成middle+1。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right]
while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=
int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
if (nums[middle] > target) {
right = middle - 1; // target 在左区间,所以[left, middle - 1]
} else if (nums[middle] < target) {
left = middle + 1; // target 在右区间,所以[middle + 1, right]
} else { // nums[middle] == target
return middle; // 数组中找到目标值,直接返回下标
}
}
// 未找到目标值
return -1;
}
};
左闭右开
先找中间值,如果中间值大于目标值,目标值在左边,中间值没比过,right变成middle。如果中间值小于目标值,目标值在右边,中间值比了,left变成middle+1。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right)
while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 <
int middle = left + ((right - left) >> 1);
if (nums[middle] > target) {
right = middle; // target 在左区间,在[left, middle)中
} else if (nums[middle] < target) {
left = middle + 1; // target 在右区间,在[middle + 1, right)中
} else { // nums[middle] == target
return middle; // 数组中找到目标值,直接返回下标
}
}
// 未找到目标值
return -1;
}
};
遇到的困难
找中间值时,避免超出范围,不建议写左加右除以二,建议使用左边值加区间一半写法。因为int有范围,两个大数相加可能超过范围就变成负数了,第二种也存在这种情况,但是发生概率会小点。
跳出while循环后,就是没找到,返回-1。
移除元素
题目简述
删掉(准确说是覆盖)数组中指定的元素,其他元素可以保留,只要求前面的对就行,后面元素可以不用管。
思路
方法一:暴力求解
两层循环,第一层遍历数组中的每个元素,检查是不是和目标数值一致,第二层循环把后面的元素挨个往前移动,直到外循环没有一样的数就结束。
方法二:双指针法
上面的时间复杂度较大,我们可以加大空间复杂度以减小时间复杂度。
选用两个指针。快指针作用是遍历每一个元素,看看是否有和目标一样的数。慢指针作用是记录删除数据后的位置,保证之前的数据都是对的。
当快指针指向一个数,判断它是否和目标数一样。最开始时,两个一起走,若不一样,快指针前进下一格,慢指针也向下走一步,当遇到一样的时候,快指针向下走,慢指针停下来不动。他俩就错开走了。当遇到不一样的时候,慢指针的值变成快指针的值。若一样,慢指针不懂,快指针走下一格。
最后当快指针遍历完,慢指针指向的位置就是新数组的下一个位置,也就是新数组长度,即可返回。
遇到的困难
数组不能删除,只能覆盖。
num[slow++]:可以简写是因为slow++先对slow进行运算,算完后再对slow+1。
c++的for循环是分号,不是逗号。每句结尾都要加分号。
class Solution {
public int removeElement(int[] nums, int val) {
// 快慢指针
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
if (nums[fastIndex] != val) {
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex;
}
}
感受
还是python代码更简洁。
看都第一眼思路就是for循环暴力求解,哈哈。
时间上花费较多,以后尽量写快点。
今日时长3h