代码随想录day01 二分,双指针
二分问题
二分模板
- 将区间分为[l, mid] [mid+1, r]
while (l < r)
{
int mid = l + r >> 1;
if (nums[mid] >= target) r = mid;
else l = mid + 1;
}
- 将区间分为[l, mid-1] [mid, r]
while (l < r)
{
int mid = l + r + 1 >> 1;
if (nums[mid] > target) r = mid -1;
else l = mid;
}
704. 二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
class Solution {
public:
int search(vector<int>& nums, int target) {
int l = 0, r = nums.size()-1;
while (l < r) {
int mid = l + r >> 1;
if (nums[mid] >= target) r = mid;
else l = mid + 1;
}
if (nums[l] == target) return r;
else return -1;
}
};
35. 搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1
示例 3:
输入: nums = [1,3,5,6], target = 7
输出: 4
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int len = nums.size();
if (target > nums[len-1]) return len;
int l = 0, r = len-1;
while (l < r)
{
int mid = l + r >> 1;
if (nums[mid] >= target) r = mid;
else l = mid + 1;
}
return l;
}
};
34. 在排序数组中查找元素的第一个和最后一个位置
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]
示例 3:
输入:nums = [], target = 0
输出:[-1,-1]
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
// 左边界
int len = nums.size();
vector<int> range = {-1, -1};
if (len == 0) return range;
int l = 0, r = len-1;
while (l < r)
{
int mid = l + r >> 1;
if (nums[mid] >= target) r = mid;
else l = mid + 1;
}
if (nums[l] != target) return range;
range[0] = l;
// 右边界
l = 0, r = len-1;
while (l < r)
{
int mid = l + r + 1 >> 1;
if (nums[mid] > target) r = mid -1;
else l = mid;
}
range[1] = l;
return range;
}
};
双指针问题
27. 移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。
示例 1:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2,_,_]
解释:你的函数函数应该返回 k = 2, 并且 nums 中的前两个元素均为 2。
你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。
示例 2:
输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3,_,_,_]
解释:你的函数应该返回 k = 5,并且 nums 中的前五个元素为 0,0,1,3,4。
注意这五个元素可以任意顺序返回。
你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int k = 0, i = 0;
while (i < nums.size())
{
if (nums[i] != val) nums[k ++] = nums[i ++];
else i ++;
}
return k;
}
};
977.有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
思路 :由于给定的数组是递增的并且可能有正有负,那么绝对值最大的肯定位于左右边界的其中一个。因此利用这样的思想结合双指针来解决。
示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
示例 2:
输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int l = 0, r = nums.size()-1;
vector<int> res = nums;
int k = r;
while (l <= r)
{
int ll = pow(nums[l], 2);
int rr = pow(nums[r], 2);
if (ll < rr)
{
res[k --] = rr;
r --;
}
else
{
res[k --] = ll;
l ++;
}
}
return res;
}
};