代码随想录算法训练营第一天|704.二分查找、27. 移除元素、977.有序数组的平方
704.二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果 target 存在返回下标,否则返回 -1。
你必须编写一个具有 O(log n) 时间复杂度的算法。
思路:二分法,先设置一下初始值
left = 0,
right = nums.size()-1
然后就是设置middle,即二分法的核心,取中点值
middle = (left + right) / 2
现在就是要进行while循环求解了,那么什么时候要跳出循环,即设置边界值,这里有两种情况
- 左闭右闭,即循环内的middle可以取到左边界和右边界值
- 左闭右开,即循环内的middle可以取到左边界值,但不能取到右边界值(左开右闭类似)
首先是第一种情况,那么就是while (left <= right)
,因为当left = right时middle = left = right,此时是合法可以取到的
当nums[middle] > target时,即目标值在中点左边,更新右边界值,
right = middle - 1
(因为此时的nums[middle]不是解)
当nums[middle] < target时,同理,left = middle + 1
再更新下middle = (left + right) / 2
然后是第二种情况,那么就是while (left < right)
,因为当left = right时middle = right,但因为我们右开,不能取到右边界值,所以不合法,因此left不能等于right
当nums[middle] > target时,即目标值在中点左边,更新右边界值,
right = middle
(此时nums[middle]不是解,且我们不能取到右边界值,所以直接是right = middle)
当nums[middle] < target时,即目标值在中点右边,更新左边界值,
left = middle + 1
(这里是左闭,nums[middle]不是解,所以要加1)
再更新下middle = (left + right) / 2
但是第二个情况下有一种特殊情况需要特别处理,就是只有一个数的时候,比如[5],此时left = 0, right = 0,无法进入循环体,所以我们这里多加个语句判断下初始的右边界值是否=target即可
// 左闭右闭
class Solution {
public:
int search(vector<int>& nums, int target) {
int left_index = 0;
int right_index = nums.size() - 1;
int middle = (left_index + right_index) / 2;
while (left_index <= right_index) {
if (nums[middle] == target)
return middle;
else if (nums[middle] > target) {
right_index = middle - 1;
} else {
left_index = middle + 1;
}
middle = (left_index + right_index) / 2;
}
return -1;
}
};
// 左闭右开
class Solution {
public:
int search(vector<int>& nums, int target) {
int left_index = 0;
int right_index = nums.size() - 1;
int middle = (left_index + right_index) / 2;
if (nums[right_index] == target)
return right_index;
while (left_index < right_index) {
if (nums[middle] == target) {
return middle;
} else if (nums[middle] > target) {
right_index = middle;
} else {
left_index = middle + 1;
}
middle = (left_index + right_index) / 2;
}
return -1;
}
};
27. 移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。
思路:
暴力解法
:两层循环,外层循环遍历一遍整个数组,当遇到val时进行内层循环,将val后面的元素都往前推一格双指针法
,定义fastindex和slowindex,fastindex遍历一遍整个数组,当元素不等于val时用slowindex存储该元素,当元素等于val时跳过该元素
代码:
// 暴力解法
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[j-1] = nums[j];
}
size--;
i--;
}
}
return size;
}
};
//双指针法
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowindex = 0;
for (int fastindex = 0; fastindex < nums.size(); fastindex++) {
if (nums[fastindex] != val) {
nums[slowindex++] = nums[fastindex];
}
}
return slowindex;
}
};
977.有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
思路:双指针法,slowindex = 0, fastindex = nums.size()-1
,一个指向最左边,另一个指向最右边,然后创建一个新数组,不断比较slowindex和fastindex指向元素的平方谁大,大的那个元素值存进新数组,然后更新指向大元素的指针。注意临界条件是
while (slowindex <= fastindex)
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int slow_index = 0;
int fast_index = nums.size() - 1;
int size = nums.size();
vector<int> array(size);
while (slow_index <= fast_index) {
int left = nums[slow_index];
int right = nums[fast_index];
size--;
if (left*left < right*right) {
array[size] = right*right;
fast_index--;
} else {
array[size] = left*left;
slow_index++;
}
}
return array;
}
};