491. Non-decreasing Subsequences
这道题容易想到用used[],但是这时不可以的,因为input的nums是没有顺序的,而且也不能排序
于是可以想到要检查每一层是否选过相同的数(for循环是横向(层),迭代是纵向)
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
void findPath(vector<int>& nums, int startIndex){
if(path.size() >= 2){
res.push_back(path);
}
unordered_set<int> oneLevelNums;
for(int i=startIndex; i<nums.size(); i++){
//判断大小是否为生序
if(!path.empty() && nums[i] < path.back()){
continue;
}
//判断一层是否选过同样的值
if(oneLevelNums.find(nums[i]) != oneLevelNums.end()){
continue;
}
path.push_back(nums[i]);
oneLevelNums.insert(nums[i]);
findPath(nums, i+1);
path.pop_back();
}
}
vector<vector<int>> findSubsequences(vector<int>& nums) {
if(nums.size() < 2) return res;
findPath(nums, 0);
return res;
}
};
1.这里不需要return,因为记录了之后还要接着看后面的值
2.unorder_set的位置
这里在for循环前面意味着,在迭代到下一层的时候会建立一个新的set,所以set记录的是每一层使用的值
同样的,迭代后是不需要删掉set最后一个元素
3.unordered_set一些用法
find() 如果找到返回该元素的位置,否则返回最后一个值的后一个位置(.end()位置)
46. Permutations(全排列)
class Solution {
public:
vector<vector<int>> res;
vector<int> perm;
void findPerm(vector<int>& nums, vector<bool>& used){
if(nums.size() == perm.size()){
res.push_back(perm);
return;
}
for(int i=0; i<nums.size(); i++){
if(used[i] == true) continue;
perm.push_back(nums[i]);
used[i] = true;
findPerm(nums,used);
perm.pop_back();
used[i] = false;
}
}
vector<vector<int>> permute(vector<int>& nums) {
vector<bool> used(nums.size(), false);
findPerm(nums, used);
return res;
}
};
47. Permutations II
两种去重方法都可以通过
class Solution {
private:
vector<vector<int>> res;
vector<int> perm;
void findPerm(vector<int>& nums, vector<bool>& used){
if(nums.size() == perm.size()){
res.push_back(perm);
return;
}
for(int i=0; i<nums.size(); i++){
if(used[i] ||(i>0 && nums[i] == nums[i-1] && used[i-1] == false)){
continue;
}
used[i] = true;
perm.push_back(nums[i]);
findPerm(nums,used);
perm.pop_back();
used[i] = false;
}
}
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<bool> used(nums.size(), false);
findPerm(nums, used);
return res;
}
};
class Solution {
private:
vector<vector<int>> res;
vector<int> perm;
void findPerm(vector<int>& nums, vector<bool>& used){
if(nums.size() == perm.size()){
res.push_back(perm);
return;
}
unordered_set<int> set;
for(int i=0; i<nums.size(); i++){
if(used[i] ||(!set.empty() && set.find(nums[i]) != set.end())){
continue;
}
used[i] = true;
set.emplace(nums[i]);
perm.push_back(nums[i]);
findPerm(nums,used);
perm.pop_back();
used[i] = false;
}
}
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<bool> used(nums.size(), false);
findPerm(nums, used);
return res;
}
};
复习二叉树
199. Binary Tree Right Side View(2)
1.层序的方法
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
vector<int> res;
queue<TreeNode*> que;
if(root == NULL) return res;
que.push(root);
while(!que.empty()){
int size = que.size();
for(int i=0; i<size; i++){
TreeNode* cur = que.front();
que.pop();
if(i == size-1) res.push_back(cur->val);
if(cur->left) que.push(cur->left);
if(cur->right) que.push(cur->right);
}
}
return res;
}
};
2.遍历
没有一下子想出来
要想到如何记录right side view的节点:先遍历右再遍历左,那么每层遍历的第一个节点就是需要的节点,然后想到res数目和深度的关系
class Solution {
private:
vector<int> res;
void traversal(TreeNode* root, int depth){
if(root == NULL) return;
if(res.size() == depth) res.push_back(root->val);
traversal(root->right, depth+1);
traversal(root->left, depth+1);
}
public:
vector<int> rightSideView(TreeNode* root) {
traversal(root, 0);
return res;
}
};
298. Binary Tree Longest Consecutive Sequence
class Solution {
private:
int maxLen = 0;
void traversal(TreeNode* root, int len, int parentVal){
if(root == NULL) return;
if(parentVal+1 == root->val){
len++;
}else{
len = 1;
}
maxLen = max(maxLen, len);
traversal(root->left, len, root->val);
traversal(root->right, len, root->val);
}
public:
int longestConsecutive(TreeNode* root) {
if(root == NULL) return maxLen;
int parentVal;
traversal(root, 0, parentVal);
return maxLen;
}
};
想到了用遍历,但一开始对于如何记录父节点的值有点懵,感觉直接写在函数里比单独列出来要方便非常多