LeetCode704 二分查找
题目链接:二分查找
左闭右闭写法
class Solution {
public:
int search(vector<int>& nums, int target) {
int low = 0;
int high = nums.size() - 1;
//左闭右闭
while(low <= high)
{
int middle = (low + high) / 2;
if(nums[middle] == target)
{
return middle;
}
else
{
if(nums[middle] > target)
{
high = middle - 1;
}
else
{
low = middle + 1;
}
}
}
return -1;
}
};
左闭右开写法:
class Solution {
public:
int search(vector<int>& nums, int target) {
int low = 0;
int high = nums.size();
//左闭右开
while(low < high)
{
int middle = (low + high) / 2;
if(nums[middle] == target)
{
return middle;
}
else
{
if(nums[middle] > target)
{
high = middle;
}
else
{
low = middle + 1;
}
}
}
return -1;
}
};
代码思路:
二分查找首先要保证数组必须是有序的,其次就是要确认区间的形式,区间也就是代码中的low和high(即数组下标)。其中左闭右闭表示的是判断target是否在[low, high]区间中,而左闭右开是判断target是否在[low, high)区间(即不包含nums[high]的区间)中。根据区间的不同,low和high的初始化以及while的条件都有可能发生改变。
快速判断不同区间对应的low和high的初始值以及while的条件,我们可以假设数组中只有一个元素,也就是只有唯一下标0。
①左闭右闭的情况,即区间为[0, 0],所以low = 0,high = size - 1,可知high = nums.size() - 1,由于low和high的值是可以相等的,可得到while的条件为low<=high。
②左闭右开的情况,即区间为[0, 1),所以low = 0,high = size,可知high = nums.size,由于high是开区间,所以low不可能出现等于high的情况,所以while的条件是low < high
LeetCode27 移除元素
题目链接:移除元素
暴力解法:
时间复杂度:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int k = nums.size();
for(int i = 0; i < k; i++)
{
if(nums[i] == val)
{
for(int j = i; j < k - 1; j++)
{
nums[j] = nums[j+1];
}
i--; // 此处的i--是因为当前位置的值虽然修改为后一个位置的值,但是仍然有可能等于val
k--;
}
}
return k;
}
};
暴力解法代码思路:
两层for循环,第一层for循环用来检查当前数组位置的值是否等于val,第二层循环用来移动数组的值,k用来记录移动后的数组的大小。
双指针法:
时间复杂度:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int fast = 0;
int slow = 0;
while(fast < nums.size())
{
if(nums[fast] != val)
{
nums[slow] = nums[fast];
slow++;
}
fast++;
}
return slow;
}
};
双指针法代码思路:
双指针法可以看成是一个数组当两个数组使用,其中fast指向的是原数组,slow指向的是经过删减后的新数组,如果原数组对应下标fast的值不等于val,就把nums[fast]的值添加到新数组中,即添加到nums[slow]。
双指针法的本质:新数组赋值
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int fast = 0;//记录nums的当前下标
int slow = 0;//记录new_nums的当前下标
vector<int> new_nums(nums.size());
while(fast < nums.size())
{
if(nums[fast] != val)
{
new_nums[slow] = nums[fast];//得到不包含val的新数组
slow++;
}
fast++;
}
for(int i = 0; i < slow; i++)
{
nums[i] = new_nums[i];//将新数组重新赋值给原数组
}
return slow;
}
};
LeetCode977 有序数组的平方
题目链接:有序数组的平方
双指针法:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int low = 0;
int high = nums.size() - 1;
vector<int> result(nums.size());
int result_loc = nums.size() - 1; //result数组当前的下标位置
while(low <= high)
{
int low_num = nums[low] * nums[low];
int high_num = nums[high] * nums[high];
if(low_num > high_num)
{
result[result_loc--] = low_num;
low++;
}
else
{
result[result_loc--] = high_num;
high--;
}
}
return result;
}
};
代码思路:
由于数组左边可能是负数,所以平方的最大值可能出现在左边或者右边,我们可以左右同时进行平方并比较,然后将大的值先写入新数组result,通过result_loc来记录新数组的下标,result_loc从result数组的最后一个位置开始不断往前移动。