分析:
动态规划:设dp[i]表示总和为i的组合的个数,最终需要返回dp[target];初始条件:dp[0] = 1;转移方程:dp[i]等于所有dp[i - x]之和,x是nums中的元素。
代码:
class Solution {
public:
int combinationSum4(vector<int>& nums, int target) {
vector<long long> dp(target + 1);
dp[0] = 1;
for(int i = 1; i <= target; i++) {
for(int& x : nums) {
if(x <= i && dp[i] + dp[i - x] <= INT_MAX) {
dp[i] += dp[i - x];
}
}
}
return dp[target];
}
};
岛屿最大面积
分析:
双端队列deque:元素入队后如果队列长度大于滑动窗口长度,则队头元素出队。
代码:
class MovingAverage {
public:
/** Initialize your data structure here. */
long long sum = 0;
int max_cnt = 0;
deque<int> que;
MovingAverage(int size) {
max_cnt = size;
}
double next(int val) {
que.push_back(val);
sum += val;
if(que.size() > max_cnt) {
sum -= que.front();
que.pop_front();
}
// cout << sum << " " << que.size() << endl;
double x = (double)sum / que.size();
return x;
}
};
/**
* Your MovingAverage object will be instantiated and called as such:
* MovingAverage* obj = new MovingAverage(size);
* double param_1 = obj->next(val);
*/
分析:
并查集:对每一个节点的节点数组,如果存在一个跟该节点在一个集合的节点,说明一条边的两个节点在同一个集合里面,不是二分图,返回false;否则将节点数组里面的所有节点合并到一个集合里面。
代码:
class Solution {
private:
vector<int> par;
void init(int n) {
par.resize(n);
for(int i = 0; i < n; i++) {
par[i] = i;
}
}
int get_root(int x) {
if(par[x] != x) {
par[x] = get_root(par[x]);
}
return par[x];
}
void merge(int x, int y) {
par[get_root(x)] = get_root(y);
}
bool check(int x, int y) {
return get_root(x) == get_root(y);
}
public:
bool isBipartite(vector<vector<int>>& graph) {
int n = graph.size();
init(n);
for(int i = 0; i < n; i++) {
for(int& x : graph[i]) {
if(check(i, x)) {
return false;
}
}
for(int j = 1; j < graph[i].size(); j++) {
merge(graph[i][0], graph[i][j]);
}
}
return true;
}
};
分析:
二叉树的结点序号如果从0开始,则序号为i的左右子树结点(如果有的话)序号分别为2i+1和2i+2。
代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class CBTInserter {
public:
vector<TreeNode*> nodes;
CBTInserter(TreeNode* root) {
if(root == NULL) {
return;
}
//建树
queue<TreeNode*> que;
que.push(root);
while(!que.empty()) {
TreeNode* fr = que.front();
nodes.push_back(fr);
que.pop();
if(fr->left) {
que.push(fr->left);
}
if(fr->right) {
que.push(fr->right);
}
}
}
int insert(int val) {
TreeNode* x = new TreeNode(val);
nodes.push_back(x);
int ind = nodes.size() - 1;
int fa = 0;
if(ind & 1) {
//左子树
fa = (ind - 1) / 2;
nodes[fa]->left = x;
}else {
//右子树
fa = (ind - 2) / 2;
nodes[fa]->right = x;
}
return nodes[fa]->val;
}
TreeNode* get_root() {
return nodes.size() == 0 ? NULL : nodes[0];
}
};
/**
* Your CBTInserter object will be instantiated and called as such:
* CBTInserter* obj = new CBTInserter(root);
* int param_1 = obj->insert(val);
* TreeNode* param_2 = obj->get_root();
*/
01矩阵
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> largestValues(TreeNode* root) {
vector<int> res;
if(root == NULL) {
return res;
}
queue<TreeNode*> que;
que.push(root);
while(!que.empty()) {
int n = que.size();
int re = INT_MIN;
for(int i = 0; i < n; i++) {
TreeNode* fr = que.front();
que.pop();
re = max(re, fr->val);
if(fr->left) {
que.push(fr->left);
}
if(fr->right) {
que.push(fr->right);
}
}
res.push_back(re);
}
return res;
}
};
找树左下角的值
二叉树的右视图
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
TreeNode* pruneTree(TreeNode* root) {
if(root == NULL) {
return NULL;
}
TreeNode* lt = pruneTree(root->left);
TreeNode* rt = pruneTree(root->right);
if(root->val == 0 && lt == NULL && rt == NULL) {
return NULL;
}
root->left = lt;
root->right = rt;
return root;
}
};
分析:
求从一个状态变化到另一个状态的最短步骤,往往就会想到BFS,此题与2017蓝桥杯省赛:青蛙跳杯子(BFS求最短路径长度)类似。
代码:
class Solution {
public:
int openLock(vector<string>& deadends, string target) {
//bfs
queue<pair<string, int>> que;
unordered_set<string> dead(deadends.begin(), deadends.end());
unordered_set<string> st;
if(dead.count("0000")) {
return -1;
}
st.insert("0000");
que.push(make_pair("0000", 0));
int dirs[8][2] = {
{
0, 1}, {
0, -1}, {
1, 1}, {
1, -1}, {
2, 1}, {
2, -1}, {
3, 1}, {
3, -1}};
while(!que.empty()) {
auto p = que.front();
string x = p.first;
int step = p.second;
que.pop();
if(x == target) {
return step;
}
for(int k = 0; k < 8; k++) {
string t = x;
int i = dirs[k][0];
if(t[i] == '0' && dirs[k][1] == -1) {
t[i] = '9';
}else if(t[i] == '9' && dirs[k][1] == 1) {
t[i] = '0';
}else {
t[i] += dirs[k][1];
}
if(dead.count(t) == 0 && st.count(t) == 0) {
que.push(make_pair(t, step + 1));
st.insert(t);
}
}
}
return -1;
}
};
总结一下层序遍历的题目: