- 公平的糖果交换
爱丽丝和鲍勃拥有不同总数量的糖果。给你两个数组 aliceSizes 和 bobSizes ,aliceSizes[i] 是爱丽丝拥有的第 i 盒糖果中的糖果数量,bobSizes[j] 是鲍勃拥有的第 j 盒糖果中的糖果数量。两人想要互相交换一盒糖果,这样在交换之后,他们就可以拥有相同总数量的糖果。一个人拥有的糖果总数量是他们每盒糖果数量的总和。返回一个整数数组 answer,其中 answer[0] 是爱丽丝必须交换的糖果盒中的糖果的数目,answer[1] 是鲍勃必须交换的糖果盒中的糖果的数目。如果存在多个答案,你可以返回其中 任何一个 。题目测试用例保证存在与输入对应的答案。
用哈希表存储所有的数然后查找即可
class Solution {
public:
vector<int> fairCandySwap(vector<int>& aliceSizes, vector<int>& bobSizes) {
int sumA = accumulate(aliceSizes.begin(), aliceSizes.end(), 0);
int sumB = accumulate(bobSizes.begin(), bobSizes.end(), 0);
int delta = (sumA - sumB) / 2;
unordered_set<int> rec(aliceSizes.begin(), aliceSizes.end());
vector<int> ans;
for (auto& y : bobSizes) {
int x = y + delta;
if (rec.count(x)) {
ans = vector<int>{x, y};
break;
}
}
return ans;
}
};
- 根据前序和后序遍历构造二叉树
返回与给定的前序和后序遍历匹配的任何二叉树。
递归查找,首先根据前序确定左子树的根,然后根据后续确定左子树的长度。由此可以递归左子树,直至只有一个节点。右子树同理。
/**
* 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* constructFromPrePost(vector<int>& pre, vector<int>& post) {
return helper(pre, post, 0, pre.size() - 1, 0, post.size() - 1);
}
TreeNode* helper(vector<int>& pre, vector<int>& post, int prestart, int preend, int poststart, int postend) {
if (prestart > preend) {
return NULL;
}
TreeNode* root = new TreeNode(pre[prestart]);
if (prestart == preend) { //只有一个,直接返回
return root;
}
int i = poststart;
while (i < postend && post[i] != pre[prestart + 1]) { //确定分界点,左子树的根节点
i++;
}
int len = i - poststart + 1; //左子树长度
root->left = helper(pre, post, prestart + 1, prestart + len, poststart, i);
root->right = helper(pre, post, prestart + 1 + len, preend, i + 1, postend - 1);
return root;
}
};
- 查找和替换模式
你有一个单词列表 words 和一个模式 pattern,你想知道 words 中的哪些单词与模式匹配。如果存在字母的排列 p ,使得将模式中的每个字母 x 替换为 p(x) 之后,我们就得到了所需的单词,那么单词与模式是匹配的。(回想一下,字母的排列是从字母到字母的双射:每个字母映射到另一个字母,没有两个字母映射到同一个字母。)返回 words 中与给定模式匹配的单词列表。你可以按任何顺序返回答案。
轮询words,每个域pattern单独比较字符规则,如果相同则说明是一个解。
class Solution {
public:
vector<string> findAndReplacePattern(vector<string>& words, string pattern) {
vector<string>ans;
int n=pattern.size();
for(auto&s:words){
if(s.size()!=n)continue;
bool flag=false;
unordered_map<char,char>mp1,mp2;
for(int i=0;i<n;i++){
char c1=s[i],c2=pattern[i];
if(mp1.count(c1)&&mp1[c1]!=c2){
flag=true;
break;
}
mp1[c1]=c2;
if(mp2.count(c2)&&mp2[c2]!=c1){
flag=true;
break;
}
mp2[c2]=c1;
}
if(flag==false)ans.push_back(s);
}
return ans;
}
};
- 子序列宽度之和
一个序列的 宽度 定义为该序列中最大元素和最小元素的差值。给你一个整数数组 nums ,返回 nums 的所有非空 子序列 的 宽度之和 。由于答案可能非常大,请返回对 109 + 7 取余 后的结果。子序列 定义为从一个数组里删除一些(或者不删除)元素,但不改变剩下元素的顺序得到的数组。例如,[3,6,2,7] 就是数组 [0,3,1,6,2,2,7] 的一个子序列。
推导数学公式并求解
typedef long long ll;
const ll MOD = 1e9 + 7;
class Solution {
public:
int sumSubseqWidths(vector<int>& A) {
int n = A.size();
sort(A.begin(), A.end());
vector<ll> two(n + 1);
two[0] = 1;
for (int i = 1; i <= n; ++i)
two[i] = (two[i - 1] << 1) % MOD;
ll ans = 0;
for (int i = 0; i < n; ++i) {
int left = i;
int right = n - i - 1;
ans = (ans + (two[left] - two[right]) * A[i]) % MOD;
}
return (ans + MOD) % MOD;
}
};
- 三维形体的表面积
给你一个 n * n 的网格 grid ,上面放置着一些 1 x 1 x 1 的正方体。每个值 v = grid[i][j] 表示 v 个正方体叠放在对应单元格 (i, j) 上。放置好正方体后,任何直接相邻的正方体都会互相粘在一起,形成一些不规则的三维形体。请你返回最终这些形体的总表面积。
挨个统计即可
class Solution {
public:
int surfaceArea(vector<vector<int>>& grid) {
int dr[]{0, 1, 0, -1};
int dc[]{1, 0, -1, 0};
int N = grid.size();
int ans = 0;
for (int r = 0; r < N; ++r) {
for (int c = 0; c < N; ++c) {
if (grid[r][c] > 0) {
ans += 2;
for (int k = 0; k < 4; ++k) {
int nr = r + dr[k];
int nc = c + dc[k];
int nv = 0;
if (0 <= nr && nr < N && 0 <= nc && nc < N) {
nv = grid[nr][nc];
}
ans += max(grid[r][c] - nv, 0);
}
}
}
}
return ans;
}
};
- 特殊等价字符串组
给你一个字符串数组 words。现在规定,words 的 一组特殊等价字符串 就是 words 的一个同时满足下述条件的非空子集:该组中的每一对字符串都是 特殊等价 的
该组字符串已经涵盖了该类别中的所有特殊等价字符串,容量达到理论上的最大值(也就是说,如果一个字符串不在该组中,那么这个字符串就 不会 与该组内任何字符串特殊等价)
返回 words 中 特殊等价字符串组 的数量。
按奇偶分类存俩string,然后排序后拼接,放入set中,计数即可
class Solution {
public:
int numSpecialEquivGroups(vector<string>& words) {
unordered_set<string>mp;
for(auto&s:words){
string odd,even;
for(int i=0;i<s.size();i++){
if(i&1)odd.push_back(s[i]);
else even.push_back(s[i]);
}
sort(odd.begin(),odd.end());
sort(even.begin(),even.end());
string connect=odd+"#"+even;
mp.insert(connect);
}
return mp.size();
}
};
- 所有可能的满二叉树
满二叉树是一类二叉树,其中每个结点恰好有 0 或 2 个子结点。返回包含 N 个结点的所有可能满二叉树的列表。 答案的每个元素都是一个可能树的根结点。答案中每个树的每个结点都必须有 node.val=0。你可以按任何顺序返回树的最终列表。
递归迭代
/**
* 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) {}
* };
*/
/**
* 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 {
private:
unordered_map<int, vector<TreeNode*>> num2nodes;
public:
vector<TreeNode*> allPossibleFBT(int n) {
if (num2nodes.find(n) == num2nodes.end())
{
vector<TreeNode*> res;
if (n == 1)
{
res.push_back(new TreeNode(0));
}
else if (n % 2 == 1)
{
// 大于等于3的奇数
// 去按照不同取值构建关系
for (int l = 0; l < n; ++l)
{
int r = n - 1 - l;
for (TreeNode* left : allPossibleFBT(l))
{
for (TreeNode* right : allPossibleFBT(r))
{
// 构建一个新的结点,并且设置left和right
res.push_back(new TreeNode(0, left, right));
}
}
}
}
num2nodes[n] = res;
}
return num2nodes[n];
}
};