目录
1.跳台阶扩展问题
2.包含不超过两种字符的最长子串
3.字符串的排列
1.跳台阶扩展问题
链接https://www.nowcoder.com/practice/953b74ca5c4d44bb91f39ac4ddea0fee?tpId=230&tqId=39750&ru=/exam/oj
我是用动态规划解决的:
#include <iostream>
using namespace std;
int dp[30];
int main() {
int n;
cin >> n;
dp[1] = 1;
for (int i = 2; i <= n; ++i)
{
for (int j = 1; j <= i - 1; j++)
{
dp[i] += dp[i - j];
}
dp[i] += 1;
}
cout << dp[n] << endl;
return 0;
}
其实这是一道规律题:
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
cout << (1 << (n - 1)) << endl;
return 0;
}
2.包含不超过两种字符的最长子串
链接https://www.nowcoder.com/practice/90d6a362fa7d4c519d557da797bb02ce?tpId=196&tqId=40552&ru=/exam/oj
一道滑动窗口问题,难点是分析清楚进窗口和出窗口的条件:
若一个数从0 - > 1,那么则cnt++(cnt是窗口中字母的种类),若从1 - > 0,那么则cnt--。
当cnt > 2时,就得出窗口了。
然后就是找个合适的位置更新返回值。
#include <iostream>
#include <iterator>
using namespace std;
int a[26];
int main() {
string s;
cin >> s;
int cnt = 0, ret = 0;
int l = 0, r = 0, n = s.size();
while(r < n)
{
if(a[s[r] - 'a']++ == 0)
cnt++;
while(cnt > 2)
if(a[s[l++] - 'a']-- == 1)
cnt--;
ret = max(ret, r - l + 1);
r++;
}
cout << ret << endl;
return 0;
}
3.字符串的排列
链接https://www.nowcoder.com/practice/fe6b651b66ae47d7acce78ffdd9a96c7?tpId=13&tqId=11180&ru=/exam/oj
深度优先遍历问题(DFS):
首先需要排序,因为排完序之后可以更好的分析有两个一样的字符的情况。
当两字符一样时,就无需在递归一遍了,因为结果都是一样的。
class Solution {
public:
int n;
string s;
string tmp;
bool vis[11] = { false };
vector<string> ret;
void DFS(int pos)
{
if (pos == n)
{
ret.push_back(tmp);
return;
}
for (int i = 0; i < n; ++i)
{
if (!vis[i])
{
if (i - 1 >= 0 && s[i] == s[i - 1] && !vis[i - 1])
continue;// 剪枝
tmp.push_back(s[i]);
vis[i] = true;
// 递归
DFS(pos + 1);
// 回溯
tmp.pop_back();
vis[i] = false;
}
}
}
vector<string> Permutation(string str) {
s = str;
n = str.size();
sort(s.begin(), s.end());
DFS(0);
return ret;
}
};