回溯
class Solution {
public:
int numTilePossibilities(string tiles) {
vector<int>count(26,0);
for(char& ch:tiles){//统计字符频次
count[ch-'A']++;
}
return dfs(count);
}
int dfs(vector<int>&count){
int res=0;
for(int i=0;i<26;++i){
if(count[i]==0)continue;
res++;
count[i]--;
res+=dfs(count);
count[i]++;
}
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) {}
* };
*/
//DFS后序遍历
class Solution {
public:
bool issufficient(TreeNode* root, int presum, int limit){
//如果为空,也视为不足结点
if(!root) return true;
//如果左右孩子都为空
if (root->left == NULL && root->right == NULL) {
return presum + root->val < limit; //告诉上一层该结点是否为不足结点
}
//如果左右孩子不空
bool left = issufficient(root->left, presum+root->val, limit); //去判断左孩子是否是不足结点
bool right = issufficient(root->right, presum+root->val, limit); //判断右孩子是否是不足结点
//如果左边是不足结点,删除左边
if(left) root->left=NULL;
//如果右边是不足结点,删除右边
if(right) root->right=NULL;
//返回值为当前结点是否为不足结点:如果左右孩子都是不足结点,当前肯定也是不足结点
return left&&right;
}
TreeNode* sufficientSubset(TreeNode* root, int limit) {
TreeNode* dummy = new TreeNode(0); //哑结点
dummy->left = root;
bool flag = issufficient(root, 0, limit); //检查以root为根结点的子树
if(flag) dummy->left=NULL; //如果root自己都不满足,那就删掉
return dummy->left; //如果root自己都被删了,那就相当于返回空
}
};
# Write your MySQL query statement below
select
product_id,
product_name
from product
where product_id in (
select
product_id
from sales
group by product_id
having max(sale_date) <= '2019-03-31'
and min(sale_date) >= '2019-01-01'
)
记录多余的数即可,更好的方法是用双指针,不需要额外内存。
class Solution {
public:
void duplicateZeros(vector<int>& arr)
{
int nSize = arr.size();
queue<int> changeQueue;
for (int i = 0; i < nSize; ++i)
{
if (changeQueue.size())
{
if (changeQueue.front() == 0)
{
changeQueue.push(arr[i]);
arr[i] = 0;
if (i + 1 == nSize) break;
changeQueue.push(arr[i + 1]);
arr[i + 1] = 0;
changeQueue.pop();
i++;
}
else
{
changeQueue.push(arr[i]);
arr[i] = changeQueue.front();
changeQueue.pop();
}
}
else if (arr[i] == 0 && i < nSize - 1)
{
changeQueue.push(arr[i + 1]);
arr[i + 1] = 0;
i++;
}
}
return;
}
};
1 将values[]和labels[]数组中的元素组成pair对
2 将pair对存到priori_queue中进行排序
3 定义一个map统计labels[]中的元素出现的次数
4 遍历priori_queue中的元素 找到符合条件的元素加到res
class Solution {
public:
struct cmp{
template<typename T, typename U>
bool operator()(T const &a, U const &b){
if(a.first < b.first) return true;
else return false;
}
};
int largestValsFromLabels(vector<int>& values, vector<int>& labels, int numWanted, int useLimit) {
priority_queue<pair<int,int>, vector<pair<int,int> >, cmp> q;
map<int, int> map;
int count = 0;
int res = 0;
int len = values.size();
for(int i = 0; i < len; i++) q.push({values[i], labels[i]});
while(!q.empty()){
auto pairs = q.top();
if(count < numWanted && map[pairs.second] < useLimit){
res += pairs.first;
count++;
if(map.count(pairs.second) == 0) map[pairs.second] = 1;
else map[pairs.second] += 1;
}
q.pop();
}
return res;
}
};
经典BFS
class Solution {
public:
int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
if(grid[0][0]==1)return -1;
int n=grid.size(),ans=1;
const int dire[8][2]={{1,0},{-1,0},{0,1},{0,-1},{1,1},{1,-1},{-1,-1},{-1,1}};
queue<pair<int,int> > q;
q.emplace(0,0); //从0,0开始
grid[0][0]=1; //标记为1代表走过
while(!q.empty()){ //bfs
int m=q.size();
while(m--){
auto [x,y]=q.front();
q.pop();
if(x==n-1&&y==n-1)return ans;
for(int i=0;i<8;i++){ //遍历八个方向的
int nx=x+dire[i][0];
int ny=y+dire[i][1];
if(nx<0||ny<0||nx>=n||ny>=n)continue; //判断是否越界
if(grid[nx][ny]==0){ //判断是否能走
q.emplace(nx,ny);
grid[nx][ny]=1; //标记
}
}
}
ans++; //记录循环次数
}
return -1;
}
};
先求最大公共子序列,然后将两个字符串中不在公共序列的拼接上即可(拼接利用动态规划求的dp来判断是否是公共子序列中的元素)
class Solution {
public:
string shortestCommonSupersequence(string str1, string str2) {
string ans;
int m = str1.size(), n = str2.size();
//求公共子序列
vector<vector<int>> dp(m + 1, vector<int>(n + 1));
for(int i = 1; i <= m; ++i){
for(int j = 1; j <= n; ++j){
if(str1[i-1] == str2[j-1])
dp[i][j] = dp[i-1][j-1] + 1;
else
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}
}
int i = m, j = n;
//从后向前回溯加上字符串
while(dp[i][j] > 0){
if(str1[i - 1] == str2[j - 1]){
//如果只在这里进行push_back这题就变成了求其中一个最长的重复子串的问题了,求超序列就是将不匹配的地方也求进去
ans.push_back(str1[i - 1]);
i--;
j--;
}
else{
if(dp[i-1][j] >= dp[i][j-1]){
ans.push_back(str1[i - 1]);
i--;
}
else{
ans.push_back(str2[j - 1]);
j--;
}
}
}
//到这里字符串1的前i和字符串2的前j个字符完全不匹配,将这些字符全部加上即可,顺序随意
while(i > 0 || j > 0){
for(int k = i; k > 0; --k){
ans.push_back(str1[k - 1]);
i--;
}
for(int k = j; k > 0; --k){
ans.push_back(str2[k - 1]);
j--;
}
}
reverse(ans.begin(), ans.end());
return ans;
}
};