6. Z 字形变换
class Solution {
public:
string convert(string s, int numRows) {
int n=s.size();
int r=numRows;
if(r<2) return s;
vector<string> res(r);
int i=0;
int flag=-1;
for(char ch:s){
… return ans;
}
};
100. 相同的树
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
// bfs一个队列:
if(p==NULL&&q==NULL){
return 1;
}
queue<TreeNode*> qu;
qu.push(p);
qu.push(q);
while(!qu.empty()){
auto nodep=qu.front();
qu.pop();
auto nodeq=qu.front();
qu.pop();
if(nodep==NULL&&nodeq==NULL){
continue;
}
if(nodep==NULL||nodeq==NULL||nodep->val!=nodeq->val){
return 0;
}
qu.push(nodep->left);
qu.push(nodeq->left);
qu.push(nodep->right);
qu.push(nodeq->right);
}
return 1;
// bfs两个队列:
// if(p==NULL&&q==NULL){
// return 1;
// }
// else if(p==NULL||q==NULL){
// return 0;
// }
// queue<TreeNode*> q1,q2;
// q1.push(p);
// q2.push(q);
// while(!q1.empty()&&!q2.empty()){
// auto node1=q1.front();
// q1.pop();
// quto node2=q2.front();
// q2.pop();
// if(node1->val!=node2->val){
// return 0;
// }
// auto l1=node1->left,r1=node1->right;
// auto l2=node2->left,r2=node2->right;
// if((l1==NULL)^(l2==NULL)){
// return 0;
// }
// if((r1==NULL)^(r2==NULL)){
// return 0;
// }
// if (l1!=nullptr) {
// q1.push(l1);
// }
// if (r1!=nullptr) {
// q1.push(r1);
// }
// if (l2!=nullptr) {
// q2.push(l2);
// }
// if (r2 != nullptr) {
// q2.push(r2);
// }
// }
// dfs:
// if(p==NULL&&q==NULL){
// return 1;
// }
// else if(p==NULL||q==NULL){
// return 0;
// }
// else if(p->val!=q->val){
// return 0;
// }
// else{
// return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);
// }
}
};
103. 二叉树的锯齿形层序遍历
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
queue<TreeNode*> q;
if(root!=nullptr){
q.push(root);
}
vector<vector<int>> res;
bool flag=1;
while(!q.empty()){
int size=q.size();
deque<int> level;
for(int i=0;i<size;++i){
auto cur=q.front();
q.pop();
if(flag){
level.push_back(cur->val);
}
else{
level.push_front(cur->val);
}
if(cur->left) q.push(cur->left);
if(cur->right) q.push(cur->right);
}
res.push_back(vector<int>{level.begin(),level.end()});
flag=!flag;
}
return res;
}
};
2100. 适合打劫银行的日子
动态规划
class Solution {
public:
vector<int> goodDaysToRobBank(vector<int>& security, int time) {
int n=security.size();
vector<int> left(n,0);
vector<int> right(n,0);
for(int i=1;i<n;++i){
if(security[i]<=security[i-1]){
left[i]=left[i-1]+1;
}
if(security[n-i-1]<=security[n-i]){
right[n-i-1]=right[n-i]+1;
}
}
vector<int> ans;
for(int i=time;i<n-time;++i){
if(left[i]>=time&&right[i]>=time){
ans.push_back(i);
}
}
return ans;
}
};
前缀和
class Solution {
public:
vector<int> goodDaysToRobBank(vector<int>& security, int time) {
int n=security.size();
vector<int> g(n);
for(int i=1;i<n;++i){
if(security[i]==security[i-1]) continue;
g[i]=security[i]>security[i-1]?1:-1;
}
vector<int> a(n+1);
vector<int> b(n+1);
for(int i=1;i<=n;++i){
a[i]=a[i-1]+(g[i-1]==1?1:0);
}
for(int i=1;i<=n;++i){
b[i]=b[i-1]+(g[i-1]==-1?1:0);
}
vector<int> ans;
for(int i=time;i<n-time;++i){
int c1=a[i+1]-a[i+1-time];
int c2=b[i+1+time]-b[i+1];
if(c1==0&&c2==0) ans.push_back(i);
}
return ans;
}
};
504. 七进制数
class Solution {
public:
string convertToBase7(int num) {
if(num==0){
return "0";
}
int n=abs(num);
string seven;
while(n>0){
seven.push_back(n%7+'0');
n/=7;
}
reverse(seven.begin(),seven.end());
return num<0?'-'+seven:seven;
}
};
130. 被围绕的区域
bfs
emplace???
class Solution {
public:
const int dx[4]={1,-1,0,0};
const int dy[4]={0,0,1,-1};
void solve(vector<vector<char>>& board) {
int n=board.size();
if(n==0){
return;
}
int m=board[0].size();
queue<pair<int,int>> q;
for(int i=0;i<n;++i){
if(board[i][0]=='O'){
q.emplace(i,0);
board[i][0]='.';
}
if(board[i][m-1]=='O'){
q.emplace(i,m-1);
board[i][m-1]='.';
}
}
for(int i=1;i<m-1;++i){
if(board[0][i]=='O'){
q.emplace(0,i);
board[0][i]='.';
}
if(board[n-1][i]=='O'){
q.emplace(n-1,i);
board[n-1][i]='.';
}
}
while(!q.empty()){
int x=q.front().first;
int y=q.front().second;
q.pop();
for(int i=0;i<4;++i){
int tx=x+dx[i];
int ty=y+dy[i];
if(tx<0||tx>=n||ty<0||ty>=m||board[tx][ty]!='O'){
continue;
}
q.emplace(tx,ty);
board[tx][ty]='.';
}
}
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
if(board[i][j]=='.') board[i][j]='O';
else if(board[i][j]=='O') board[i][j]='X';
}
}
}
};
dfs
class Solution {
public:
int n,m;
void dfs(vector<vector<char>>& board,int x,int y){
if(x<0||x>=n||y<0||y>=m||board[x][y]!='O'){
return ;
}
board[x][y]='.';
dfs(board,x+1,y);
dfs(board,x,y+1);
dfs(board,x-1,y);
dfs(board,x,y-1);
}
void solve(vector<vector<char>>& board) {
n=board.size();
m=board[0].size();
if(n==0) return ;
for(int i=0;i<n;++i){
dfs(board,i,0);
dfs(board,i,m-1);
}
for(int j=1;j<m-1;++j){
dfs(board,0,j);
dfs(board,n-1,j);
}
for(int i=0;i<n;++i){
for(int j=0;j<m;++j){
if(board[i][j]=='.'){
board[i][j]='O';
}
else if(board[i][j]=='O'){
board[i][j]='X';
}
}
}
}
};
207. 课程表
拓扑排序
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
int n=numCourses;
vector<vector<int>> side(n);
vector<int> in(n);
for(auto t:prerequisites){
side[t[1]].push_back(t[0]);
++in[t[0]];
}
queue<int> q;
for(int i=0;i<n;++i){
if(in[i]==0) q.push(i);
}
int vis=0;
while(!q.empty()){
++vis;
int cur=q.front();
q.pop();
for(int s:side[cur]){
--in[s];
if(in[s]==0){
q.push(s);
}
}
}
return vis==n;
}
};
2055. 蜡烛之间的盘子
前缀和+预处理
class Solution {
public:
vector<int> platesBetweenCandles(string s, vector<vector<int>>& queries) {
int n=s.size();
vector<int> pre(n);
int sum=0;
//计算前缀和
for(int i=0;i<n;++i){
if(s[i]=='*') sum++;
pre[i]=sum;
}
//预处理,存放左边离i最近的蜡烛
vector<int> left(n);
for(int i=0,l=-1;i<n;++i){
if(s[i]=='|') l=i;
left[i]=l;
}
//同理,存放右边离i最近的|
vector<int> right(n);
for(int i=n-1,r=-1;i>=0;--i){
if(s[i]=='|') r=i;
right[i]=r;
}
vector<int> ans;
for(auto q:queries){
int x=right[q[0]];//存放左端点右边的最近蜡烛位置
int y=left[q[1]];//右端点左边的最近位置
ans.push_back(x==-1||y==-1||x>=y?0:pre[y]-pre[x]);//=-1说明无封闭区间
}
return ans;
}
};
210. 课程表 II
class Solution {
public:
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
int n=numCourses;
vector<vector<int>> side(n);//存有向图
vector<int> in(n);//入度
vector<int> ans;//存储结果
//预处理图和入度表
for(auto t:prerequisites){
side[t[1]].push_back(t[0]);
++in[t[0]];
}
queue<int> q;
//入度为0的点先入队
for(int i=0;i<n;++i){
if(in[i]==0) q.push(i);
}
//bfs
while(!q.empty()){
int cur=q.front();
q.pop();
ans.push_back(cur);
for(int s:side[cur]){
--in[s];
if(in[s]==0){
q.push(s);
}
}
}
//返回合法答案
if(ans.size()!=n) return {};
return ans;
}
};
226. 翻转二叉树
递归dfs:
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
//递归终止条件,节点为空返回
if(root==NULL){
return NULL;
}
//先存储左右节点
TreeNode* left=invertTree(root->left);
TreeNode* right=invertTree(root->right);
//交换左右节点
root->left=right;
root->right=left;
return root;
// //另一种写法
// TreeNode* tmp = root->right;
// root->right = root->left;
// root->left = tmp;
// //递归交换当前节点的左右子树
// invertTree(root->left);
// invertTree(root->right);
// return root;
}
};
迭代bfs
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root==nullptr){
return nullptr;
}
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
auto cur=q.front();
q.pop();
//交换当前出队列的cur节点的左右节点
auto tmp=cur->left;
cur->left=cur->right;
cur->right=tmp;
//如果当前节点的左右子树不为空,则入队列等待循环处理
if(cur->left!=NULL) q.push(cur->left);
if(cur->right!=NULL) q.push(cur->right);
}
return root;
}
};
279. 完全平方数
动态规划:
class Solution {
public:
int numSquares(int n) {
vector<int> f(n+1);
for(int i=1;i<=n;++i){
int minn=INT_MAX;
for(int j=1;j*j<=i;++j){
minn=min(minn,f[i-j*j]);//求已求过的最小次数
}
f[i]=minn+1;//递推
}
return f[n];
}
};
bfs:
class Solution {
public:
int numSquares(int n) {
queue<int> q;
vector<bool> vis(n+1,0);//剪枝用到的哈希数组
q.push(0);
vis.push_back(0);
int num=0;//记录所需平方数的数量
//bfs
while(!q.empty()){
num++;
int size=q.size();
for(int i=0;i<size;++i){
int cur=q.front();
q.pop();
for(int j=1;cur+j*j<=n;++j){//cur+j*j<=n剪枝
int sum=cur+j*j;//存放已获得的平方和
if(sum==n) return num;
if(sum<n&&!vis[sum]){//!vis[sum]剪枝
q.push(sum);
vis.push_back(sum);
}
}
}
}
return num;
}
};
https://blog.csdn.net/qq_43309286/article/details/93191767
https://blog.csdn.net/lxiao428/article/details/83831316
2049. 统计最高分的节点数目
class Solution {
public:
vector<vector<int>> g;//存放子树关系
int n;//节点总数量
long long best_score=0;//最高分数
int ans=0;//最高分数个数
//dfs:
//求节点下的所有结点数量,包括自己
//顺便计算该节点的得分
int dfs(int i){
long long score=1;//ll满足题目数据需要
int cnt=1;//记录子节点总数,起始为自己1
for(auto child:g[i]){//依次计算该点的各个子节点
int branch=dfs(child);//记录一个分支的节点数量
score*=branch;//各分支节点数量相乘得分数
cnt+=branch;//记录每个分支的节点数量和
}
//若不是根节点,得分还需乘节点上方的总数
if(i!=0){
score*=n-cnt;
}
//记录最大得分,维护ans
if(score>best_score){
ans=1;
best_score=score;
}
//得分相同,ans++
else if(score==best_score){
ans++;
}
return cnt;//返回该分支的总结点数
}
int countHighestScoreNodes(vector<int>& parents) {
n=parents.size();
g.resize(n,vector<int>());
//建图
for(int i=1;i<n;++i){
g[parents[i]].push_back(i);
}
dfs(0);//递归计算各点分数,更新ans
return ans;
}
};
393. UTF-8 编码验证
class Solution {
public:
bool validUtf8(vector<int>& data) {
//总共只有四种情况:0xxxxxxx, 110xxxxx, 1110xxxx, 11110xxx
int another=0;//记录第一个字节后还有多少个字节
for(int num:data){
if(another==0){//刚开始为0
if(num>>5==0b110) another=1;
else if(num>>4==0b1110) another=2;
else if(num>>3==0b11110) another=3;
else if(num>>7) return 0;//没有1xxxxxxx的情况
}
else{//进入else说明不止1字节
if(num>>6!=0b10) return 0;//判断第一个字节后面字节前两位是否为10
--another;//每判断一个-1,用于最后返回值判断
}
}
return another==0;
}
};
310. 最小高度树
反向层序遍历,由外往里一层一层删除,最终剩下的就是root,一层一层排尽量接近满二叉树即为最小高度
class Solution {
public:
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
if(n==1) return {0};
vector<int> degree(n);//度
vector<vector<int>> nb(n);//邻接表
vector<int> res;
//建无向图
for(int i=0;i<n-1;++i){
int u=edges[i][0];
int v=edges[i][1];
degree[u]++;
degree[v]++;
nb[u].push_back(v);
nb[v].push_back(u);
}
queue<int> q;
//叶子节点入栈
for(int i=0;i<n;++i){
if(degree[i]==1){
q.push(i);
}
}
while(!q.empty()){
res.clear();//把上一层的叶子节点清除
int size=q.size();
for(int i=0;i<size;++i){
int cur=q.front();
q.pop();
res.push_back(cur);
//外层叶子出队列,内层叶子进队列
for(auto j:nb[cur]){
degree[j]--;//使之成为叶子节点
if(degree[j]==1){
q.push(j);
}
}
}
}
return res;
}
};
599. 两个列表的最小索引总和
class Solution {
public:
vector<string> findRestaurant(vector<string>& list1, vector<string>& list2) {
map<string,int> index;//hash记录数组1元素与下标的对应关系
for(int i=0;i<list1.size();++i){
index[list1[i]]=i;
}
vector<string> ans;
int imin=INT_MAX;//最小索引总和
for(int i=0;i<list2.size();++i){
if(index.count(list2[i])>0){//count函数求是否存在,返回次数
int j=index[list2[i]];//存放该餐厅名称
if(i+j<imin){//判断是否更新最小索引总和
ans.clear();
ans.push_back(list2[i]);
imin=i+j;
}
else if(i+j==imin){//无需更新,直接插入
ans.push_back(list2[i]);
}
}
}
return ans;
}
};
2044. 统计按位或能得到最大值的子集数目
位运算
class Solution {
public:
int countMaxOrSubsets(vector<int>& nums) {
int n=nums.size();
int bigg=0;//按位与的最大值
int cnt=0;//记录不同非空子集的数目
int state=1<<n;//二进制状态,表示各元素的取舍,即各个子集
for(int i=0;i<state;++i){//遍历各个子集
int cur=0;//设置按位与的初始值为0不影响结果
for(int j=0;j<n;++j){//每次循环取一位出来
if(((i>>j)&1)==1){//判断此子集是否存在nums[j],存在则加入运算
cur|=nums[j];
}
}
if(cur==bigg){//和最大值相同则数目+1
cnt++;
}
else if(cur>bigg){//更新最大值
bigg=cur;
cnt=1;//重置为1
}
}
return cnt;//返回数目
}
};
dfs
class Solution {
public:
int n;
int ans=0;
int bigg=0;//按位与最大值即为每个数都参与的情况
void dfs(vector<int>& nums,int i,int v){
if(v==bigg){//若此刻已经满足最大值,再加其他数也一样
ans+=1<<(n-i);//2的n-i次方种情况
return;//剪枝终止返回
}
if(i==n){//最坏情况
return;
}
dfs(nums,i+1,v|nums[i]);//选当前元素加入运算
dfs(nums,i+1,v);//不选
}
int countMaxOrSubsets(vector<int>& nums) {
n=nums.size();
for(int num:nums){//求按位与最大值
bigg|=num;
}
dfs(nums,0,0);
return ans;
}
};
720. 词典中最长的单词
class Solution {
public:
string longestWord(vector<string>& words) {
string ans = "";
//用set存放words的元素,方便O(1)查找
unordered_set<string> h;
for(auto word:words){
h.insert(word);
}
for(auto word:words){
int n=word.size();
int m=ans.size();
if(n<m) continue;//剪枝,题目求最大长度
//长度相同的答案,取字典序最小的,此处即把字典序大的或完全无关的情况去掉
if(n==m&&word>ans) continue;
bool flag=true;//判断答案是否合法为逐渐加一个字母起来的
for(int i=1;i<=n;++i){
if(!h.count(word.substr(0,i))){
flag=0;
break;
}
}
if(flag) ans=word;//更新最大长度
}
return ans;
}
};
牛客网
单位的换算
#include<bits/stdc++.h>
using namespace std;
int main(){
string s;
cin>>s;
s+="*";//在字符串末尾加上*,方便对最后一个字符的哈希
int n=s.size();
map<string,int> upper,under;//分别用两个map记录分子分母
string tmp="";//临时量用于哈希的标识
bool mtp=1;
//哈希统计分子和分母
//最终除了的符号字符数量
for(int i=0;i<n;++i){
if(s[i]=='*'||s[i]=='/'){//字符为运算符
if(mtp){//该步骤为乘法
if(under[tmp]){//若分母中有相同的,则抵消
under[tmp]--;
}
else upper[tmp]++;//无,则分子中该计算量++
}
else{//除法
if(upper[tmp]){
upper[tmp]--;
}
else under[tmp]++;
}
mtp=(s[i]=='*'?1:0);//更新下一步为乘还是除
tmp="";//清空
}
else tmp+=s[i];//字符为计算量,赋值给tmp
}
//输出分子:
mtp=0;//第一个不需要加乘号
for(auto i:upper){
while(i.second){
if(mtp){
cout<<'*';
}
cout<<i.first;
mtp=1;
i.second--;
}
}
if(!mtp) cout<<1;
cout<<endl;
//输出分母:
mtp=0;
for(auto i:under){
while(i.second){
if(mtp){
cout<<'*';
}
cout<<i.first;
mtp=1;
i.second--;
}
}
if(!mtp) cout<<1;
cout<<endl;
}
瓜瓜打游戏(EASY)
动态规划
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll dp[5010][5010];
//dp[i][j]的含义是第i关得到j个徽章的路径和
//dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*a[i];
//dp路径有两个来源:
//一个是达到徽章数的上一关跳过当前关卡的dp
//一个是上一关正常到当前关卡的dp
int main(){
int n;
ll p;
cin>>n>>p;
dp[0][0]=1;
for(int i=1;i<=n;++i){
int a;
cin>>a;
dp[i][0]=dp[i-1][0];//相当于初始化,先考虑直接跳过没获得徽章的情况
for(int j=1;j<=n;++j){
dp[i][j]=(dp[i-1][j]+dp[i-1][j-1]*a)%p;//*a:乘a[i]种通关方法;%p:取模
}
}
for(int i=0;i<=n;++i){
cout<<dp[n][i]<<" ";//输出n+1个数,分别是通关后获得0-n个徽章的可能路径数
}
}
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m,k;
cin>>n>>m>>k;
int x,y,c;
while(k--){
cin>>x>>y>>c;
}
cout<<n+m-1<<" "<<c;
}
暴力:
#include<bits/stdc++.h>
using namespace std;
int g[5010][5010];
int main(){
memset(g,0,sizeof(g));
int n,m,k;
cin>>n>>m>>k;
while(k--){
int c,x,y;
cin>>x>>y>>c;
for(int i=1;i<=n;++i){
g[i][y]=c;
}
for(int i=1;i<=m;++i){
g[x][i]=c;
}
}
int cnt=0;
int num=0;
int mp[5010]={0};
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
mp[g[i][j]]++;
}
}
for(int i=1;i<=5000;++i){
if(mp[i]>cnt){
cnt=mp[i];
num=i;
}
}
cout<<cnt<<" "<<num;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int a[100005],b[100005],c[100005];
bool cmp(int x,int y){
return x>y;
}
int main(){
int n,k;
cin>>n>>k;
long long num=0;
for(int i=0;i<n;++i){
cin>>a[i];
num+=a[i];
}
for(int i=0;i<n;++i){
cin>>b[i];
if(a[i]>b[i]){//剪枝,只记录需要换的
c[i]=a[i]-b[i];
}
}
sort(c,c+n,cmp);//***最重点的排序,差值从大到小
for(int i=0;i<k;++i){//题目说至多k次,若不需要k次,减掉的是0
num-=c[i];
}
cout<<num;
}
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,k;
string s;
cin>>n>>k>>s;
int n0=0,n1=0;
//统计0和1的数目
for(int i=0;i<n;++i){
if(s[i]=='0') n0++;
else n1++;
}
int ans=0;
//原状态进行操作
if(k<=n1){
ans=max(ans,n0+k);
}
else{
ans=max(ans,n-(k-n1)%2);
}
//交换01后的状态进行操作
int tmp=0;
tmp=n0;n0=n1;n1=tmp;
k--;//次数要减掉1
if(k>0){
if(k<=n1){//直接1->0
ans=max(ans,n0+k);
}
else{
ans=max(ans,n-(k-n1)%2);//%2中一个2包含两次翻转即操作一,结果不变,余数即全0需要变成1的数目
}
}
cout<<ans;
}
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
pair<int,int> p[200010];//存放x,y
int main(){
int t;
cin>>t;
while(t--){
cin>>n>>m>>k;
for(int i=1;i<=k;++i){
cin>>p[i].first>>p[i].second;
}
sort(p+1,p+1+k);
int flag=1;
for(int i=2;i<=k;++i){
if(p[i].second<p[i-1].second){//x已经排好序,若后面的y还小于前面的y,不可能走得回去
flag=0;
break;
}
}
if(flag) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}