【leetcode】数组刷题记录
前言
本文是基于leetcode数组例题的学习记录
704. 二分查找
复习一下二分
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 >> 1;
if(nums[mid] <= target)l = mid;
else r = mid - 1;
}
return nums[l] == target ? l : -1;
}
};
这里有一个重要点,当是l = mid的时候,mid需要等于l + r + 1。如果是l = mid + 1,mid就等于l + r。我也不记得为什么了,当初就是这么背的~
贴个模板:
链接
版本1
当我们将区间[l, r]划分成[l, mid]和[mid + 1, r]时,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1。
C++ 代码模板:
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
版本2
当我们将区间[l, r]划分成[l, mid - 1]和[mid, r]时,其更新操作是r = mid - 1或者l = mid;,此时为了防止死循环,计算mid时需要加1。
C++ 代码模板:
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
27. 移除元素
链接
这应该算最简洁的吧~
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
vector<int> cp(nums.size());
int i = 0;
for(int num : nums)
if(num != val)
cp[i ++ ] = num;
nums = cp;
return i;
}
};
977. 有序数组的平方
链接
先来个暴力
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for (int i = 0; i < nums.size(); i++)
{
nums[i] *= nums[i];
}
sort(nums.begin(), nums.end());
return nums;
}
};
再来个双指针(数组题目常用做法)
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int k = nums.size() - 1;
vector<int> res(nums.size());
int i = 0, j = nums.size() - 1;
while(i <= j)
{
if (nums[i] * nums[i] < nums[j] * nums[j])
{
res[k--] = nums[j] * nums[j];
j--;
}
else
{
res[k--] = nums[i] * nums[i];
i++;
}
}
return res;
}
};
209. 长度最小的子数组
链接
跟上题一样,碰到数组想双指针(其实是滑动窗口,但这种也算是用两个变量去表示了)
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int l = 0;
int r = 0;
int cursum = 0;
int minlength = 0;
while(r <= nums.size()-1)
{
cursum += nums[r];
while(cursum >= target)
{
if(minlength >= r - l + 1 || minlength == 0)
minlength = r - l + 1;
cursum -= nums[l];
l++;
}
r++;
}
return minlength;
}
};
59. 螺旋矩阵 II
链接
很烂的写法:
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int offset = 0;
int num = 1;
vector<vector<int>> ans(n, vector<int> (n));
while(1)
{
for(int i = offset; i < n - offset; i ++ )
{
ans[offset][i] = num ++;
if(num > n * n)break;
}
if(num > n * n)break;
for(int i = offset + 1; i < n - offset; i ++ )
{
ans[i][n - offset - 1] = num ++;
if(num > n * n)break;
}
if(num > n * n)break;
for(int i = n - offset - 2; i >= offset; i -- )
{
ans[n - offset - 1][i] = num ++;
if(num > n * n)break;
}
if(num > n * n)break;
for(int i = n - offset - 2; i > offset; i -- )
{
ans[i][offset] = num ++;
if(num > n * n)break;
}
if(num > n * n)break;
offset ++;
}
return ans;
}
};
看了题解再写一遍
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int l = 0, r = n - 1, t = 0, b = n - 1;
vector<vector<int>> ans(n, vector<int> (n));
int num = 1, tar = n * n;
while(num <= tar)
{
for(int i = l; i <= r; i++) ans[t][i] = num++;
t++;
for(int i = t; i <= b; i++) ans[i][r] = num++;
r--;
for(int i = r; i >= l; i--) ans[b][i] = num++;
b--;
for(int i = b; i >= t; i--) ans[i][l] = num++;
l++;
}
return ans;
}
};
LCR 160. 数据流中的中位数
链接
这是比较特别的一道题,没写出来,看看题解了解一下小顶堆和大顶堆的做法
题解
class MedianFinder {
public:
priority_queue<int, vector<int>, greater<int>> A; // 小顶堆,保存较大的一半
priority_queue<int, vector<int>, less<int>> B; // 大顶堆,保存较小的一半
MedianFinder() { }
void addNum(int num) {
if(A.size() != B.size()) {
A.push(num);
B.push(A.top());
A.pop();
} else {
B.push(num);
A.push(B.top());
B.pop();
}
}
double findMedian() {
return A.size() != B.size() ? A.top() : (A.top() + B.top()) / 2.0;
}
};
总结
数组:总结篇
大多数数组题目无非就是用 二分、双指针、滑动窗口、模拟、前缀和
的方式去做