8.3 滑窗 |栈|阶乘判断
lc2106
k步定长滑动窗口
两种情况:start单侧 or 有折返
折返处理:
while ( (fruits[right][0] - fruits[left][0] + min(startPos - fruits[left][0], fruits[right][0] - startPos)) > k )
{
curSum -= fruits[left][1];
left++;
}
class Solution {
public:
int maxTotalFruits(vector<vector<int>>& fruits, int startPos, int k) {
int n = fruits.size();
int left = 0;
while (left < n && fruits[left][0] < startPos - k) {
left++;
}
int right = left;
int curSum = 0;
while (right < n && fruits[right][0] <= startPos) {
curSum += fruits[right][1];
right++;
}
int maxSum = curSum;
while (right < n && fruits[right][0] <= startPos + k)
{
curSum += fruits[right][1];
while ( (fruits[right][0] - fruits[left][0] + min(startPos - fruits[left][0], fruits[right][0] - startPos)) > k ) {
curSum -= fruits[left][1];
left++;
}
maxSum = max(maxSum, curSum);
right++;
}
return maxSum;
}
};
用双指针的方法,算从起点出发、最多走k步能捡到多少水果:
1. 先找左边最远能到的位置(离起点不超过k步),确定左指针起点
2. 先统计从左指针到起点范围内的所有水果
3. 然后右指针慢慢向右移(不超过起点+k步),每次加上新位置的水果
4. 过程中如果左右距离太远、超了k步,就把左指针右移,减去左边的水果
5. 随时记录能捡到的最多水果数,最后返回这个最大值
核心就是 用左右指针框出一个“在k步内”的范围,不断调整范围并算总数,找最大的那个。
lc32.括号
class Solution {
public:
int longestValidParentheses(string s)
{
int num = s.size();
int ans = 0;
int start = -1;
vector<int> stack;
for(int i = 0; i < num; i++)
{
if(s[i] == '('){
stack.push_back(i);
}
else
{
if(stack.empty())
{
start = i;
}
else{
stack.pop_back();
if(stack.empty())
{
ans = max(i - start, ans);
}
else{
ans = max(i - stack.back(), ans);
}
}
}
}
return ans;
}
};
lc60 排列序列
逐位确定每一位的数字:
- 按位确定1到n的第k个排列,每步用剩余位数的排列数(n-i)!
- 判断选哪个数,不够就减k,够就选定该数。
class Solution {
public:
string getPermutation(int n, int k)
{
string a;
vector<bool> u(10, false);
for (int i = 0; i < n; i++)
{
int f = 1;
for (int j = 1; j <= n - i - 1; j++)
f *= j;//阶乘计算
for (int j = 1; j <= n; j++)
{
if (!u[j])
{
if (f < k) k -= f;
//数字枚举
else
{
a += to_string(j);
u[j] = true;
break;
}
}
}
}
return a;
}
};