思想:
双指针:采用头尾指针,利用最大值一定是数组最左端或者最右端的思想
977. 有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
/*
* @lc app=leetcode.cn id=977 lang=cpp
*
* [977] 有序数组的平方
*/
// @lc code=start
class Solution {
public:
vector sortedSquares(vector& nums) {
int i = 0;
int j = nums.size() - 1;
int k = nums.size() - 1;
vector result(nums.size(), 0);
while (i <= j) {
long long left = nums[i] * nums[i];
long long right = nums[j] * nums[j];
if (left < right) {
result[k--] = right;
j--;
} else {
result[k--] = left;
i++;
}
}
return result;
}
};
// @lc code=end
思想:
滑动窗口:本质上也是一种双指针思想,用于寻找符合条件的一个区间
209. 长度最小的子数组
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
/*
* @lc app=leetcode.cn id=209 lang=cpp
*
* [209] 长度最小的子数组
*/
// @lc code=start
class Solution {
public:
int minSubArrayLen(int target, vector& nums) {
int j = 0;
int sum = 0;
int result = nums.size() + 1;
for (int i = 0; i < nums.size(); i++) {
sum += nums[i];
while (sum >= target) {
int len = i - j + 1;
result = len < result? len: result;
sum -= nums[j++];
}
}
return result == nums.size() + 1? 0: result;
}
};
// @lc code=end
904. 水果成篮
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits
表示,其中 fruits[i]
是第 i
棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
给你一个整数数组 fruits
,返回你可以收集的水果的 最大 数目。
自己写的思想:
- 两种水果篮子类型一样时:
- 新采摘的水果,和篮子水果类型不一样时,记录新的水果类型
- 数量++
- 两种水果篮子类型不一样时:
- 新采摘水果和前一个篮子水果类型一样
- 数量++
- 新采摘水果和前一个篮子水果类型不一样
- 新采摘水果和两种水果篮子之一一样时
- 记录采摘水果的位置k,数量++
- 新采摘水果和两种水果篮子不一样时
- 重新利用下标位置k计算两个篮子之间的数量
- 记录采摘水果的位置k
- 重新标记水果篮子的种类
初始化:
位置都标记在0位置,数量为1;
特殊情况:
水果为[],直接返回0;
/*
* @lc app=leetcode.cn id=904 lang=cpp
*
* [904] 水果成篮
*/
// @lc code=start
class Solution {
public:
int totalFruit(vector& fruits) {
int i = 0;
int j = 0;
int k = 0;
int res = 0;
int sum = 1;
int first = fruits[i];
int second = fruits[j];
for (int i = 1; i < fruits.size(); i++) {
if (first == second) {
if (fruits[i] != first) {
k = i;
first = fruits[i];
}
sum++;
}
else {
if (fruits[i] == fruits[i-1])
sum++;
else {
if(fruits[i] == second || fruits[i] == first) {
k = i;
sum++;
}
if(fruits[i] != second && fruits[i] != first){
j = k;
res = res < sum? sum: res;
sum = i - j + 1;
k = i;
second = fruits[j];
first = fruits[i];
}
}
}
}
res = res < sum? sum: res;
return res;
}
};
// @lc code=end
虽然通过了,写的太麻烦了,看看答案
答案借助了一个哈希表:
- 哈希表数量小于等于2
移动right
- 哈希表数量大于2
不断移动left,减少哈希表值,直到某个键值为0,移除此键值对
map常见函数:
find()函数:返回一个迭代器指向键值为key的元素it,没找到返回指向map尾部的迭代器erase(it)函数:it为需要删除的元素的迭代器
map可以使用it->first来访问键,it->second来访问值
/*
* @lc app=leetcode.cn id=904 lang=cpp
*
* [904] 水果成篮
*/
// @lc code=start
class Solution {
public:
int totalFruit(vector& fruits) {
unordered_map cnt;
int result = 0;
int sum = 0;
int j =0;
for (int i = 0; i < fruits.size(); i++) {
cnt[fruits[i]]++;
while (cnt.size() > 2) {
auto it = cnt.find(fruits[j]);
it->second--;
if (it->second == 0)
cnt.erase(it);
j++;
}
result = max(result, i - j + 1);
}
return result;
}
};
// @lc code=end
76. 最小覆盖子串
给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
自己写的思路:
右指针不断移动
当t中所有字符在哈希表中都只有一次,记录子串长度,比较
当t中存在字符在哈希表中超过一次,移动左指针,直到没有这个字符只有一次
答案思路:
右指针不断移动,直到覆盖所有字符
左指针移动,记录子串长度,比较,直到超出必要字符
重复
/*
* @lc app=leetcode.cn id=76 lang=cpp
*
* [76] 最小覆盖子串
*/
// @lc code=start
class Solution {
public:
unordered_map cnt, ori;
bool check() {
for (auto o: ori){
if (cnt[o.first] < o.second)
return false;
}
return true;
}
string minWindow(string s, string t) {
for (char c: t) {
ori[c]++;
}
int j = 0;
int len = s.size() + 1;
int ansL = -1;
for (int i = 0;i < s.size(); i++) {
if (ori.find(s[i]) != ori.end())
cnt[s[i]]++;
while (check() && (j <= i)) {
if ((i - j + 1) < len) {
len = (i - j + 1);
ansL = j;
}
if (ori.find(s[j]) != ori.end())
cnt[s[j]]--;
j++;
}
}
return ansL == -1? "": s.substr(ansL,len);
}
};
// @lc code=end
59. 螺旋矩阵 II
给你一个正整数 n
,生成一个包含 1
到 n2
所有元素,且元素按顺时针顺序螺旋排列的 n x n
正方形矩阵 matrix
思考:
循环次数:n/2
从左到右:
从上到下:
从右到左:
从下到上:
考虑整数奇偶
/*
* @lc app=leetcode.cn id=59 lang=cpp
*
* [59] 螺旋矩阵 II
*/
// @lc code=start
class Solution {
public:
vector> generateMatrix(int n) {
int startx = 0;
int starty = 0;
int loop = n / 2;
int mid = n / 2;
int offset = 1;
int count = 1;
vector> num(n, vector(n, 0));
int i,j;
while (loop--) {
for (j = starty; j < n - offset; j++)
num[startx][j] = count++;
for (i = startx; i < n - offset; i++)
num[i][j] = count++;
for (; j > starty; j--)
num[i][j] = count++;
for (; i > startx; i--)
num[i][j] = count++;
startx++;
starty++;
offset++;
}
if (n % 2)
num[mid][mid] = count;
return num;
}
};
// @lc code=end