c++写算法 5月篇
二进制无连续的1
解题思路:
法一:动态规划
由于第i位置要么是0,要么是1,因而定义数组dp[i][j]
,表示在第i位置时,当前位值为j时的情况有多少种,则有状态转移方程dp[i][j]={j=0: dp[i-1][1]+dp[i-1][0]; j=1: dp[i-1][0]}
,此时代码如下:
#include<iostream>
using namespace std;
int main() {
int n;
cin>>n;
long long dp[100][100]={0};
dp[1][0]=dp[1][1]=1;
for(int i=2;i<=n;i++){
for(int j=0;j<=1;j++){
if(j==0)
dp[i][j]=dp[i-1][0]+dp[i-1][1];
else dp[i][j]=dp[i-1][0];
}
}
cout<<dp[n][0]+dp[n][1]<<endl;
return 0;
}
法二:空间优化的dp
换个角度想,当dp[i][j]
的第i位的数值j=0时,此时的情况和i-1位的情况相同;若当dp[i][j]
的第i位的数值j=1时,则第i-1位必定为0,此时和i-2的情况相同,则有状态转移方程:dp[i]=dp[i-1]+dp[i-2]
,代码如下:
#include<iostream>
using namespace std;
int main() {
int n;
cin>>n;
long long *a = new long long[n+1]{0,2,3};
for(int i=3;i<=n;i++) {
a[i]=a[i-1]+a[i-2];
}
cout<<a[n]<<endl;
return 0;
}
codevs 1098 均分纸牌
从左到右遍历数组,若不等于平均值,则把差值累加在下一位,此题代码如下:
#include<iostream>
using namespace std;
int main(){
int n,a[105],ans=0,sum=0;
cin>>n; // 输入数组长度
// 初始化数组
for(int i=0;i<n;i++){
cin>>a[i];
sum+=a[i];
}
int average=sum/n; // 平均数
for(int i=0;i<n;i++){
int t=0;
if(a[i]!=average){
t=a[i]-average; // 把不符合的牌数通通移到右边
a[i+1]+=t;
ans++; // 步数+1
}
}
cout<<ans<<endl;
return 0;
}
codevs 1065 01字符串
思路同本篇第一题一样,定义dp[i]
代表在第i位置上,满足情况的的可能性有多少种。代码如下
#include<iostream>
#include<string.h>
using namespace std;
int main() {
int n;
cin>>n;
int dp[1000];
dp[1]=2;dp[2]=4;dp[3]=6;
for(int i=4;i<=n;i++)
dp[i]=dp[i-1]+dp[i-2];
cout<<dp[n]<<endl;
}
1024. Video Stitching
思路:遍历数组,首先有个要点,也就是必须找到连续的才可以,在满足连续的条件下(例如(a,b),(c,d),只需要满足b>=c即可
)我们尽可能大的扩展边界,对应状态转移方程有
dp[i]=max(dp[i-1],clips[i][1])
,当且仅当dp[i-1]>=clips[i][0]
时.
代码如下:
class Solution {
public:
int videoStitching(vector<vector<int>>& clips, int T) {
int n = clips.size();
int i, j;
/*
dp[i] refers to the furthest valid duration that could be gained with i clips
dp[i] = max(dp[i-1], clips[j][1] which clips[j][0] <= dp[i])
*/
vector<int> dp = vector<int>(n + 1, -1);
dp[0] = 0;
for (i = 1; i <= n; i++) {
dp[i] = dp[i-1];
for (j = 0; j < n; j++) {
if (clips[j][0] <= dp[i-1]) {
dp[i] = max(dp[i], clips[j][1]);
}
}
}
/*
we get the smallest i such that dp[i] >= T
*/
for (i = 1; i <= n; i++) {
if (dp[i] >= T) {
return i;
}
}
return -1;
}
};
958. Check Completeness of a Binary Tree
思路:
此题要求我们判断一棵树是否是完全二叉树,对于完全二叉树,易知完全二叉树在出现第一个空结点后,后面全都是空节点
代码如下,提供了bfs版本和一种简化版本:
class Solution {
public:
// bool isCompleteTree(TreeNode* root) {
// queue<TreeNode*> q;
// q.push(root);
// while (!q.empty()) {
// TreeNode* tmp = q.front();
// q.pop();
// if (tmp) {
// q.push(tmp->left);
// q.push(tmp->right);
// } else {
// while (!q.empty()) {
// if (q.front()) return false;
// q.pop();
// }
// return true;
// }
// }
// return true;
// }
bool isCompleteTree(TreeNode* root) {
vector<TreeNode*> bfs;
bfs.push_back(root);
int i = 0;
while (i < bfs.size() && bfs[i]) {
bfs.push_back(bfs[i]->left);
bfs.push_back(bfs[i]->right);
i++;
}
while (i < bfs.size() && !bfs[i])
i++;
return i == bfs.size();
}
};