leetcode201
给定范围 [m, n],其中 0 <= m <= n <= 2147483647(2^2-31,即INT_MAX),
返回此范围内所有数字的按位与(包含 m, n 两端点)。
输入: [5,7]
输出: 4
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
// 排除移位误操作
if(m == 0 && n == 2147483647) return m;
// 求取区间长度的2对数
int len = n - m + 1, k = ceil(log(len) / log(2));
// 区间头尾互与,先右移出再左还原
return (m&n)>>(k)<<(k);
}
};
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
int shift = 0;
// 找到公共前缀{当m=n)
while (m < n) {
m >>= 1;
n >>= 1;
++shift;
}
return m << shift;
}
};
class Solution {
public:
int rangeBitwiseAnd(int m, int n) {
while (m < n) {
// 抹去最右边的 1,Brian算法
n = n & (n - 1);
}
return n;
}
};
给定一个整数类型的数组 nums,请编写一个能够返回数组 “中心索引” 的方法。
我们是这样定义数组 中心索引 的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。
如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。
输入:nums = [1, 7, 3, 6, 5, 6]
输出:3
输入:nums = [1, 2, 3]
输出:-1
class Solution {
public:
int pivotIndex(vector<int>& nums) {
int len = nums.size();
if(len < 2){
return -1;
}
int suml = 0;
int sumr = 0;
// 可以从零开始,特例:[2,0],[0,2]
for(int i=0; i<len; i++){
sumr += nums[i];
}
// 法一:删一,比较,添一
for(int i=0; i<len; i++){
sumr -= nums[i];
if(suml == sumr){
return i;
}
suml += nums[i];
}
// 法二:翻倍加中心比较,添一
for(int i=0; i<len; i++){
if(suml*2 + nums[i] == sumr){
return i;
}
suml += nums[i];
}
return -1;
}
};
class Solution(object):
def pivotIndex(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
suml = 0
S = sum(nums)
# enumerate 取序号和值
for i, x in enumerate(nums):
if suml == (S-x-suml):
return i
suml += x
return -1
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
可以假设数组中无重复元素。
输入: [1,3,5,6], 5
输出: 2
输入: [1,3,5,6], 7
输出: 4
输入: [1,3,5,6], 0
输出: 0
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int len = nums.size();
// 初始判断,可不加
if(len == 0) return 0;
int left = 0;
int right = len-1;
// 二分查找通用模板
while(left <= right){
// 取中值
int mid = left +((right-left)>>1);
// 符合则输出
if(nums[mid] == target) return mid;
// 过大则取左
if(nums[mid] > target){
right = mid-1;
continue;
}
// 过小则取右
if(nums[mid] < target){
left = mid+1;
continue;
}
}
// 取左侧点
//(因为循环条件。取左:会让右=左,实现右插入;取右:则不能左插入)
return left;
}
};
给出一个区间的集合,请合并所有重叠的区间。
约束:区间左界不大于右界
输入: intervals = [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
输入: intervals = [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。
(法一:比较算法:简易压入)
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
// 保存最后结果和单位结果存储buff
vector<vector<int>> results;
vector<int> ele(2, 0);
int len = intervals.size();
// 容器为空,返回空集{}
if(len==0) return {
};
// 容器尺寸为1,返回原值
if(len==1) return intervals;
// 容器排序(按容器单元内最左值)
sort(intervals.begin(), intervals.end());
// 将第0个区间样本放入buff
ele = intervals[0];
// 开始区间合并处理
for(int i=1; i<len; i++){
// 内右大于等于外右
if(ele[1]>=intervals[i][1]){
continue;
// 内右大于等于外左,合并保存
}else if(ele[1]>=intervals[i][0]){
ele[1] = intervals[i][1];
// 内右小于外左,压入更新
}else if(ele[1]<intervals[i][0]){
results.push_back(ele);
ele = intervals[i];
}
}
// 将最后一个区间压入
results.push_back(ele);
return results;
}
};
(法二:比较算法:简易压入)
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
if (intervals.size() == 0) {
return {
};
}
sort(intervals.begin(), intervals.end());
vector<vector<int>> merged;
for (int i = 0; i < intervals.size(); ++i) {
// 取左右值
int L = intervals[i][0], R = intervals[i][1];
// merge非空 或者 merge尾项右值 不包括 当前左值
if (!merged.size() || merged.back()[1] < L) {
// 压入
merged.push_back({
L, R});
}
else {
// merge尾项右值更新
merged.back()[1] = max(merged.back()[1], R);
}
}
return merged;
}
};
(法三:桶排序:垃圾算法的空间复杂度爆炸)
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end());
int len = intervals.size();
vector<vector<int> > results;
vector<int> ele(2, 0);
// if(len == 0) return results.push_back(ele);
if(len == 1) return intervals;
int start = intervals[0][0];
int limit = intervals[len-1][1];
vector<int> bottle(limit+1, 0);
for(int i=0; i<len; i++){
for(int j=intervals[i][0]; j<=intervals[i][1]; j++){
bottle[j] = 1;
}
}
int flag = 0;
for(int i=start; i<=limit; i++){
if(flag==0 && bottle[i]==1){
ele[0] = i;
flag = 1;
}
if(flag==1 && bottle[i]==0){
ele[1] = i-1;
flag = 0;
results.push_back(ele);
}
if(flag==1 && bottle[i]==1 && i==limit){
ele[1] = limit;
results.push_back(ele);
}
}
return results;
}
};
给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
注意:可以认为区间的终点总是大于它的起点。
区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。
输入: [ [1,2], [2,3], [3,4], [1,3] ]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。
输入: [ [1,2], [1,2], [1,2] ]
输出: 2
解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。
输入: [ [1,2], [2,3] ]
输出: 0
解释: 你不需要移除任何区间,因为它们已经是无重叠的了。
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
// 走个流程
int len = intervals.size();
if(len == 0) return 0;
// sort排序,(适用范围:数组、链表、向量)
// 参数(首地址,首地址+长度)
sort(intervals.begin(), intervals.end());
// 记录:至i处的最多不重叠区间树
vector<int> dp(len, 1);
int ans = 1;
// 开始记录各dp:
for(int i=1; i<len; i++){
// 比较i与i之前所有区间是否重叠
for(int j=0; j<i; j++){
// 不重叠则比较当前dp[i]与dp[j]+1,取较大
if(intervals[i][0] >= intervals[j][1]){
dp[i] = max(dp[i], dp[j]+1);
// [[4,5],[5,6],[6,7],[1,2],[2,3],[7,8]]
// 1 2 3 1 2 4(不会被更新成3)
ans = max(dp[i], ans);
}
}
}
// 最小剔除个数 == 原区间数 - 最大不重叠区间个数
return len-ans;
}
};
给定一个无序的整数数组,找到其中最长上升子序列的长度。
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
说明:可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。
进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int len = nums.size();
if(len==0) return 0;
vector<int> dp(len, 1);
int ans = 1;
for(int i=1; i<len; i++){
for(int j=0; j<i; j++){
if(nums[i]>nums[j]){
dp[i] = max(dp[i], dp[j]+1);
ans = max(ans, dp[i]);
}
}
}
return ans;
}
};
/*解法二:贪心法*/
// 定义sort升序规则
bool cmp(vector<int> vec1,vector<int> vec2){
return vec1[0]<vec2[0];
}
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
// 按照起始点从小到大排序
std::sort(intervals.begin(),intervals.end(),cmp);
// 存放不重叠的区间
vector<vector<int>> Temp;
// 记录与Temp不重叠的备选压入区间
int last=0;
for(int i=1;i<intervals.size();++i){
// 若备选区间与新区间不重叠
if(intervals[last][1]<=intervals[i][0]){
// 压入备选区间(判断不重叠才会被压入)
Temp.push_back(intervals[last]);
// 刷新尾部号(新区间成为备选区间)
last=i;
}
else if(intervals[last][1]>=intervals[i][1]){
// 若备选区间包含新区间
// 原备选区间被新区间所替代,继续观察
last=i;
}
}
// 备选区间转正
if(last<intervals.size())
Temp.push_back(intervals[last]);
return intervals.size()-Temp.size();
}
};
给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 90 度。
给定 matrix = [
[1,2,3],
[4,5,6],
[7,8,9]],
原地旋转输入矩阵,使其变为:[
[7,4,1],
[8,5,2],
[9,6,3]]
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int len = matrix.size();
// 保存参考信息
// 可用auto buff = matrix;
vector<vector<int>> buff = matrix;
for(int i=0; i<len; i++){
for(int j=0; j<len; j++){
// 利用参考信息改变原矩阵,枚举一行出规律
matrix[i][j] = buff[len-1-j][i];
}
}
}
};
编写一种算法,若M × N矩阵中某个元素为0,则将其所在的行与列清零。
输入:[
[0,1,2,0],
[3,4,5,2],
[1,3,1,5]]
输出:[
[0,0,0,0],
[0,4,5,0],
[0,3,1,0]]
class Solution {
public:
void setZeroes(vector<vector<int>>& matrix) {
int x = matrix.size();
if(x==0) return;
int y = matrix[0].size();
vector<int> x_buff(x, 0);
vector<int> y_buff(y, 0);
// 取样
for(int i=0; i<x; i++){
for(int j=0; j<y; j++){
if(matrix[i][j] == 0){
x_buff[i] = 1;
y_buff[j] = 1;
}
}
}
// 刷新
for(int i=0; i<x; i++){
for(int j=0; j<y; j++){
if(x_buff[i]==1 || y_buff[j]==1){
matrix[i][j] = 0;
}
}
}
}
};
class Solution {
public:
vector<int> findDiagonalOrder(vector<vector<int>>& matrix) {
vector<int> nums;
// 获得行列数(下标)
int m = matrix.size();
// 针对[],[[]]的万能答案
if(m==0) return {
};
int n = matrix[0].size();
int i = 0; // i 是 x + y 的和
// 前提:对角线上x,y下标之和相同
while (i < m + n)
{
// 第 (下标和为)1 3 5 ... 趟(i-j+)
// 确定 x y 的初始值
int x1 = (i < m) ? i : m - 1;
int y1 = i - x1;
// 行不等0 且 列不到底
while (x1 >= 0 && y1 < n)
{
nums.push_back(matrix[x1][y1]);
x1--;
y1++;
}
// 下一条对角线
i++;
// 没有下一条线了
if (i >= m + n) break;
// 第 (下标和为)2 4 6 ... 趟(j-i+)
// 确定 x y 的初始值
int y2 = (i < n) ? i : n - 1;
int x2 = i - y2;
// 列不等0,行不到底
while (y2 >= 0 && x2 < m)
{
nums.push_back(matrix[x2][y2]);
x2++;
y2--;
}
i++;
}
return nums;
}
};
*子串,比较操作,连接操作
赋值:
string s1 = "Hello World!";
string s2 = s1;
string s3(s1);
比较:
bool (s1==s3)
bool s1.compare(s3)
字符串是否可以改变:
可以直接赋值改变:C++
不可以直接赋值改变:Python,Java
编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:
输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。
时间复杂度
空间复杂度
class Solution {
public:
string longestCommonPrefix(vector<string>& strs) {
int len = strs.size();
if(len == 0) return "";
string prefix = strs[0];
for(int i=1; i<len; i++){
int cnt = min(prefix.size(), strs[i].size());
int index = 0;
while(index < cnt && prefix[index]==strs[i][index]){
++index;
}
prefix = prefix.substr(0, index);
}
return prefix;
}
};
时间复杂度
空间复杂度
class Solution {
public:
string longestCommonPrefix(vector<string>& strs){
int len = strs.size();
if(len==0) return "";
string prefix = strs[0];
int cnt = prefix.size();
for(int i=0; i<cnt; i++){
for(int j=1; j<len; j++){
if(i==strs[j].size()) return strs[j];
if(prefix[i] != strs[j][i]) return prefix.substr(0,i);
}
}
return prefix;
}
};
时间复杂度
空间复杂度
class Solution {
public:
string longestCommonPrefix(const vector<string>& strs) {
int len = strs.size();
if(len==0) return "";
int op = 0;
int ed = len-1;
// 分治入口
return merge(strs, op, ed);
}
string merge(const vector<string>& strs, int op, int ed){
// 分治(叶子)出口
if(op==ed) return strs[op];
// 3种(混淆)取区间内中值
// 1. 较慢
// int mid = op + (ed-op)/2;
// 2. 溢出错误做差后千万不要右移
// int mid = op + (ed-op)>>1;
// 3. 最快
int mid = (op+ed)>>1;
// 分治获得左右公共prefix
string leftpub = merge(strs, op, mid);
string rightpub = merge(strs, mid+1, ed);
// 获得最终公共prefix
return Compare(leftpub, rightpub);
}
string Compare(const string left, const string right){
// 决定右值的上界
int cnt = min(left.length(), right.size());
// 判断右值的下界
for(int i=0; i<cnt; i++){
if(left[i]!=right[i]){
return left.substr(0, i);
}
}
return left.substr(0, cnt);
}
};
给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。
输入:“abc” 输出:3
解释:三个回文子串: “a”, “b”, “c”
输入:“aaa” 输出:6
解释:6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”
提示:输入的字符串长度不会超过 1000 。
class Solution {
public:
int countSubstrings(string s) {
int len = s.length();
// 除空字符串
if(len==0)
return 0;
// 初始化置0
int dp[len][len];
memset(dp, 0, sizeof(dp));
// 对角线填1
for(int i=0; i<len; i++)
dp[i][i] = 1;
int nums = len;
// 动态规划填dp矩阵
// 行为串首,列为串尾
for(int j=1; j<len; j++){
for(int i=0; i<j; i++){
// 子串长度大于2,掐头去尾是回文,头尾相等
if(j>i+1 && dp[i+1][j-1]==1 && s[i]==s[j]){
dp[i][j] = 1;
nums++;
}
// 子串长度等于2,且回文
if(j==i+1 && s[i]==s[j]){
dp[i][j] = 1;
nums++;
}
}
}
return nums;
}
};
给定一个字符串 s,找到 s 中最长的回文子串。
你可以假设 s 的最大长度为 1000(潜台词:可用动态规划)。
示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:
输入: “cbbd”
输出: “bb”
用到 < string > 库中的.substr(start, len);
class Solution {
public:
string longestPalindrome(string s) {
int len = s.size();
if(len==0) return "";
int dp[len][len];
memset(dp, 0, sizeof(dp));
for(int i=0; i<len; i++){
dp[i][i] = 1;
}
// 设置初值
int maxlen = 1;
int begin = 0;
for(int j=1; j<len; j++){
for(int i=0; i<j; i++){
// 当子串长为2时
if(j==i+1 && s[i]==s[j]){
dp[i][j] = 1;
maxlen = max(maxlen, j-i+1);
if(maxlen == j-i+1) begin = i;
}
// 当子串长大于2时
if(j>i+1 && dp[i+1][j-1]==1 && s[i]==s[j]){
dp[i][j] = 1;
maxlen = max(maxlen, j-i+1);
if(maxlen == j-i+1) begin = i;
}
}
}
return s.substr(begin, maxlen);
}
};
level 1:
输入: “the sky is blue”
输出: “blue is sky the”
level 2:
输入: " hello world! "
输出: “world! hello”
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
level 3:
输入: “a good example”
输出: “example good a”
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
时间复杂度:O(N)
空间复杂度:O(N)
class Solution {
public:
string reverseWords(string s) {
int len = s.length();
if(len==0) return "";
// 定义取单词指示符
int L = len-1;
int R = L;
string rev = "";
// 遍历字符串
while(L>=0){
// 1.清除空字符:
// 因为在2后进行该判断会刷新LR,永久跳过3操作
while(L>=0 && s[L]==' '){
L--;
R = L;
}
// 2.定位单词头部
while(L>=0 && s[L]!=' '){
L--;
}
// 3.取单词
if(L!=R){
rev += s.substr(L+1, R-L) + " ";
L--;
R = L;
}
}
// 若原字符串不是“ ”形式,则消除3.最后一次操作出现多加一个空字符的bug
if(!rev.empty()){
rev.pop_back();
}
return rev;
}
};
时间复杂度:O(N)
空间复杂度:O(1)
class Solution {
public:
string reverseWords(string s) {
// 反转整个字符串
reverse(s.begin(), s.end());
int n = s.size();
int idx = 0;
for (int start = 0; start < n; ++start) {
if (s[start] != ' ') {
// 填一个空白字符然后将idx移动到下一个单词的开头位置
if (idx != 0) s[idx++] = ' ';
// 循环遍历至单词的末尾
int end = start;
while (end < n && s[end] != ' ') s[idx++] = s[end++];
// 反转整个单词
reverse(s.begin() + idx - (end - start), s.begin() + idx);
// 更新start,去找下一个单词
start = end;
}
}
s.erase(s.begin() + idx, s.end());
return s;
}
};
1、用栈FILO
class Solution {
public:
string reverseWords(string s) {
stack<string> stk;
string rev = "";
string x;
stringstream ss(s);
while(ss >> x){
stk.push(x);
}
while(!stk.empty()){
rev += stk.top() + " ";
stk.pop();
}
if(!rev.empty()){
rev.pop_back();
}
return rev;
}
};
2、不用栈字符串前置叠加
class Solution {
public:
string reverseWords(string s) {
string rev, x;
stringstream ss(s);
while(ss >> x){
rev = x + " " + rev;
}
// 依旧需要去空格(因为开头rev为空)
return rev.substr(0, rev.size()-1);
}
};
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,必须原地修改输入数组、使用 O(1)的额外空间解决这一问题。
假设数组中的所有字符都是 ASCII 码表中的可打印字符。
输入:[“h”,“e”,“l”,“l”,“o”]
输出:[“o”,“l”,“l”,“e”,“h”]
输入:[“H”,“a”,“n”,“n”,“a”,“h”]
输出:[“h”,“a”,“n”,“n”,“a”,“H”]
class Solution {
public:
void reverseString(vector<char>& s) {
int len = s.size();
if(!len) return;
// 声明字节指针变量:
char *p1 = &s[0];
char *p2 = &s[len-1];
// 移动字节指针(p1,p2保存指向变量空间的地址)
while(p1<p2){
// 字节指针变量*p1作为右值:所取指向的变量空间的值
char temp = *p1;
// 字节指针变量*p1作为左值:将右值入指向的变量空间
*p1 = *p2;
*p2 = temp;
// 地址+-(仅适用于字节数组的地址)
p1++;
p2--;
}
return;
}
};
给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。
函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
说明:
返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
输入: numbers = [2, 7, 11, 15], target = 9
输出: [1,2]
解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
for(int i=0; i<numbers.size(); i++){
// 固定左值
int low = i+1;
// 从终点开始对右值进行二分查找
int high = numbers.size()-1;
while(low<=high){
int middle = low + (high-low)/2;
if(numbers[middle] == target - numbers[i]){
return {
i+1, middle+1};
}else if(numbers[middle] > target - numbers[i]){
high = middle-1;
}else{
low = middle+1;
}
}
}
// 无正确结果时的输出
return {
-1, -1};
}
};
class Solution {
public:
vector<int> twoSum(vector<int>& numbers, int target) {
// 头尾设置指针
int i = 0;
int j = numbers.size()-1;
while(i<j){
if(numbers[i]+numbers[j]==target){
return {
i+1, j+1};
}else if(numbers[i]+numbers[j]<target){
i++;
}else{
j--;
}
}
// 无正确结果时的输出
return {
-1,-1};
}
};
有一个数组 nums 和一个值 val,请 原地移除所有数值等于val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
给定 nums = [0,1,2,2,3,0,4,2], val = 2,
函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
注意这五个元素可为任意顺序。
你不需要考虑数组中超出新长度后面的元素。
class Solution {
public:
// & 引用将改变所调用数组的布局
int removeElement(vector<int>& nums, int val) {
int slow=0;
int fast=0;
while(fast < nums.size()){
// 当fast遇到指定值时:
slow留在指定位置处不动
fast向前移动一位
// 当fast再次遇到非指定值时
slow保存fast当前值,并前移一位
fast向前移动一位
if(nums[fast]!=val){
nums[slow] = nums[fast];
slow++;
}
fast++;
}
// 输出最终位数
return slow;
}
};
给定一个二进制数组, 计算其中最大连续1的个数。
输入: [1,1,0,1,1,1]
输出: 3
解释: 开头的两位和最后的三位都是连续1,所以最大连续1的个数是 3.
注意: 输入的数组只包含 0 和1。输入数组的长度是正整数,且不超过 10,000。
class Solution {
public:
int findMaxConsecutiveOnes(vector<int>& nums) {
int len = nums.size();
int max1 = 0;
int j = 0;
int m = 0;
while(j<len){
// 局部连续记录
if(nums[j]==1)
m++;
// 局部长度记录与更新
if(nums[j]!=1 && m!=0){
max1 = max(m, max1);
m = 0;
}
j++;
}
// 防止数组仅为1项且存在最大连续紧挨终点的情况
return max(m, max1);
}
};
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int len = nums.size();
if(!len) return 0;
int i = 0;
int j = 0;
int res = 65535;
int temp = 0;
while(j<len){
// 向后更新
temp += nums[j];
// 局部和达到要求
while(temp>=s){
// 局部求和并剔除头部
temp -= nums[i];
res = min(res, j-i+1);
i++;
}
// 局部求和未达到要求,向后移动
j++;
}
if(res==65535) return 0;
return res;
}
};
private:
vector<int> data;
int head;
int tail;
int size;
public:
/** Initialize your data structure here. Set the size of the queue to be k. */
MyCircularQueue(int k) {
data.resize(k);
head = -1;
tail = -1;
size = k;
}
/** Insert an element into the circular queue. Return true if the operation is successful. */
/** 入队 */
bool enQueue(int value) {
if (isFull()) {
return false;
}
if (isEmpty()) {
head = 0;
}
// 循环方式队尾向后移动一位并赋值
tail = (tail + 1) % size;
data[tail] = value;
return true;
}
/** Delete an element from the circular queue. Return true if the operation is successful. */
/** 出队 */
bool deQueue() {
if (isEmpty()) {
return false;
}
// 如果头尾相等,则等价于队列清零
if (head == tail) {
head = -1;
tail = -1;
return true;
}
// 队首向后移动一位
head = (head + 1) % size;
return true;
}
/** Get the front item from the queue. */
int Front() {
if (isEmpty()) {
return -1;
}
return data[head];
}
/** Get the last item from the queue. */
int Rear() {
if (isEmpty()) {
return -1;
}
return data[tail];
}
/** Checks whether the circular queue is empty or not. */
bool isEmpty() {
// 队首为-1则为空
return head == -1;
}
/** Checks whether the circular queue is full or not. */
bool isFull() {
// 队尾向后移动一位遇到队首则为满
return ((tail + 1) % size) == head;
}
队列实用操作:
queue<> q
q.push(k)
q.pop()
q.front()
q.back()
q.size()
q.empty()