简单记录
题目来源:leetcode
刷题顺序:代码随想录
刷题工具:VSCode+leetcode插件
补充:延毕时间充裕,会结合LeetCode 101: A LeetCode Grinding Guide (C++ Version)相似题目一起做。
还是双指针类型的题目。
题目:
给你一个按非递减顺序排序的整数数组 nums,返回 每个数字的平方组成的新数组,要求也按非递减顺序排序。
示例:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]
代码:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int l =0, r = nums.size()-1, n = nums.size();
vector<int> res(nums.size(),0);
while (l <= r){
if (abs(nums[r]) >= abs(nums[l])){
res[--n] = pow(nums[r--],2);
}
else{
res[--n] = pow(nums[l++],2);
}
}
return res;
}
};
题目:
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
代码:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int l =0, r = 0, sum =0;
int min_size = nums.size()+1;
for (r=0; r < nums.size(); ++r){
sum+= nums[r];
while (sum >= target){
min_size = (r-l+1) < min_size? (r-l+1) : min_size;
sum-=nums[l++];
}
}
return min_size <(nums.size()+1)?min_size:0;
}
};
只用一个for循环,那么这个循环的索引,一定是表示滑动窗口的终止位置。
题目:
你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。
你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必须按照要求采摘水果:
你只有 两个 篮子,并且每个篮子只能装 单一类型 的水果。每个篮子能够装的水果总量没有限制。
你可以选择任意一棵树开始采摘,你必须从 每棵 树(包括开始采摘的树)上 恰好摘一个水果 。采摘的水果应当符合篮子中的水果类型。每采摘一次,你将会向右移动到下一棵树,并继续采摘。
一旦你走到某棵树前,但水果不符合篮子的水果类型,那么就必须停止采摘。
给你一个整数数组 fruits ,返回你可以收集的水果的 最大 数目。
示例:
输入:fruits = [0,1,2,2]
输出:3
解释:可以采摘 [1,2,2] 这三棵树。
如果从第一棵树开始采摘,则只能采摘 [0,1] 这两棵树。
代码(题解方法):
class Solution {
public:
int totalFruit(vector<int>& fruits) {
unordered_map <int, int> cla;
int l = 0, r = 0, max_size = 0;
for (r = 0; r < fruits.size(); ++r){
++cla[fruits[r]];
while (cla.size() >2){
if(--cla[fruits[l]] == 0){
cla.erase(fruits[l]);
}
++l;
}
max_size = max(r-l+1,max_size);
}
return max_size;
}
};
该方法采用哈希表+滑动窗口。
代码(讨论里的方法):
class Solution {
public:
int totalFruit(vector<int>& fruits) {
int l = 0, r = 0, max_size = 0;
int lbasket = fruits[l], rbasket = fruits[r]; //篮子一号和二号
while ( r < fruits.size()){
if (fruits[r] == lbasket || fruits[r] == rbasket){//属于篮子某个种类
max_size = max(max_size, r-l+1); //更新结果,每次取一个数就更新一下
++r;
}
//如果遇到第三种,把慢指针移动到快指针前一步,该步的水果种类必然不同于快指针,此时慢指针慢慢回退齐所有的连续同类。
else{
rbasket = fruits[r];
l= r-1;
lbasket = fruits[l]; //更新第一个篮子
while (l >= 1 && fruits[l-1] == lbasket){
--l;
}
max_size = max(max_size, r-l+1);
}
}
return max_size;
}
};
只用了滑动窗口,太厉害了,我自己的思路也是这样,但就是写不出来。
题目:
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:
对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
如果 s 中存在这样的子串,我们保证它是唯一的答案。
示例:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
代码:
class Solution {
public:
string minWindow(string s, string t) {
vector<int> ch(128,0);
vector<bool> ap(128,false);
for (size_t i = 0; i != t.size(); ++i){
ap[t[i]] = true;
++ch[t[i]];
}
//滑动窗口,一左一右两个指针
int l = 0, cnt = 0 , min_l = 0, min_size = s.size()+1;
for (size_t r = 0; r != s.size(); ++r){
if (ap[s[r]]){
if (--ch[s[r]] >= 0){
++cnt;
}
}
while (cnt == t.size()){
if (r-l+1 < min_size){
min_size = r-l+1;
min_l = l;
}
if (ap[s[l]] && ++ch[s[l]] > 0){
--cnt;
}
++l;
}
}
return min_size>s.size()?"":s.substr(min_l,min_size);
}
};
这道题在leetcode101做过,这次换了个while的写法结果没写出来,太糟糕了,为了图代码简洁写成ap[s[r++]],没注意到这样的话后面所有的r都加了一位。可惜可惜。
好讨厌做这种题目!!
题目:
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
示例:
示例 1:
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
vector<vector<int>> res (n, vector<int> (n,0));
int i =0, j = 0, num =2;
res[0][0] =1;
while(num<= n*n){
while (j < n-1 && res[i][j+1] == 0){
res[i][++j] = num++;
}
while (i < n-1 && res[i+1][j] == 0 ){
res[++i][j] = num++;
}
while (j > 0 && res[i][j-1] == 0){
res[i][--j] = num++;
}
while (i > 0 && res[i-1][j] == 0){
res[--i][j] = num++;
}
}
return res;
}
};
太恶心了,做过类似的了,然后对着答案做都做不对!!!
题目:
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
代码:
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int raws = matrix.size(); //行
int cols =matrix[0].size(); //列
int n = min(raws,cols)/2;
vector<int> res;
int i =0, j = 0, offset =1;
int startx =0, starty =0;
while (n--){
for (j = starty; j < cols-offset; ++j){
res.push_back(matrix[startx][j]);
}
for (i = startx; i < raws-offset; ++i){
res.push_back(matrix[i][j]);
}
for (; j > starty; --j){
res.push_back(matrix[i][j]);
}
for (; i >startx; --i){
res.push_back(matrix[i][j]);
}
++startx;
++starty;
++offset;
}
if(min(raws,cols)%2 == 1){ //小的那个值如果是奇数,就要额外输出一行或一列
if (raws > cols){
for (i = startx; i< raws-offset+1; ++i){
res.push_back(matrix[i][starty]);
}
}
if (cols > raws){
for (j = starty; j< cols-offset+1; ++j){
res.push_back(matrix[startx][j]);
}
}
if (raws == cols && raws%2 ==1){
res.push_back(matrix[startx][starty]);
}
}
return res;
}
};
牛逼,功夫不负有心人,看了讨论区后想到一种方法。给每一个要输出的值立一个flag,初始化为false。在螺旋循环过程中,如果是遇到false,就输出他并将它的flag改为1,否则就不输出了。(虽然我发现空间时间复杂度都很垃圾,但好歹是自己好理解的方法。)
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
int raws = matrix.size(); //行
int cols =matrix[0].size(); //列
int n = raws*cols;
int i =0, j= 0;
vector<int> res;
vector<vector<bool>> flag (raws,vector<bool>(cols,false));
res.push_back(matrix[0][0]);
flag[0][0] = true;
while (n-1 > 0){
while (j< cols-1 && !flag[i][j+1]){
flag[i][j+1] =true;
res.push_back(matrix[i][++j]);
--n;
}
while (i< raws-1 && !flag[i+1][j]){
flag[i+1][j] =true;
res.push_back(matrix[++i][j]);
--n;
}
while (j> 0 && !flag[i][j-1]){
flag[i][j-1] =true;
res.push_back(matrix[i][--j]);
--n;
}
while (i> 0 && !flag[i-1][j]){
flag[i-1][j] =true;
res.push_back(matrix[--i][j]);
--n;
}
}
return res;
}
};
今天做的特别慢感觉,处理边界情况真的太烦了,痛苦。还有两道扩展题目还在想。
我要是面到螺旋矩阵我螺旋放弃。(又不想放弃了)