class Solution
{
public:
int minNumberOfHours(int ien, int iex, vector<int>& energy, vector<int>& experience)
{
// ien 初始精力,iex 初始经验
int m = energy.size();
int sum = accumulate(energy.begin(), energy.end(), 0);
int ans = ien > sum ? 0 : sum + 1 - ien; // 如果累加精力和低于初始值,则无需进行学习
for(int num : experience)
{
if(iex <= num)
{
int diff = num + 1 - iex;
ans += diff;
iex += diff;
}
iex += num;
}
return ans;
}
};
AA...BBCBB...AA
(中间单个字符,前后字符对称)或 AA...BBBB...AA
(中间无字符,前后字符对称)。9
,再依次插入更小的数值),只要该数值对应的频数仍大于 1
,就将其成对成对地删去,即成对成对地构造回文数字串。【先插入前半段,后半段通过前半段反转得到】
1
个)或没有了,再重新从大数值的频数开始遍历到小数值的频数,尝试插入一个更大值作为回文数字串的中位数值,0
,所以要很小心特殊情况。0
的部分很混乱】class Solution
{
public:
string largestPalindromic(string num)
{
vector<int> cnt(10);
for(char& c : num)
++cnt[c-'0'];
string ans;
int mid = -1;
// 先把偶数次数的数值字符构造完
for(int i = 9; i >= 1; --i)
{
if((cnt[i] & 1) == 1 and mid == -1) mid = i;
while(cnt[i] > 1)
{
ans.push_back('0'+i);
cnt[i] -= 2;
}
}
// 在这之后我尝试先处理 `0`,再处理回文字符串的中间位置
// 其实两部分处理可以合并
if((cnt[0] & 1) == 1 and mid == -1)
mid = 0;
if(ans.empty())
{
if(mid == -1)
ans += '0';
else ans += ('0' + mid);
return ans;
}
while(cnt[0] > 1)
{
ans.push_back('0');
cnt[0] -= 2;
}
string back(ans);
reverse(back.begin(), back.end());
if(mid != -1)
ans += ('0' + mid);
return ans+back;
}
};
递归函数进入根节点,并返回左子树高度和右子树高度的更大值。
也就是说递归返回的是树高,但是在中途可以利用左、右子树高来更新距离。
首先情况一:当前节点 cur
是初始感染节点 initial
,则向下感染的距离最远是树高,即 max(height(cur->right), height(cur->left))
,这是可以直接从递归结果中得出的。
接着关键的是情况二:当前节点是初始感染节点的祖先节点,且感染节点处于祖先节点的左子树中,则感染该树(注意是感染当前树)的最远距离为 depth(initial) - depth(cur) + height(cur->right)
。【如果处于右子树中,则最远距离中最后的 height(cur->right)
要改为 height(cur->left)
】
可以从具体例子中加深理解:
还可以再举另一个例子:
如此只需要把最远距离 len
变量置为全局,再在遍历过程中不断更新结果即可。
更新结果的式子为 max(len, depth(initial) - depth(cur) + height(cur->right))
,这个式子是对于所有节点都可以进行判断的;假若 cur
是 initial
的子孙节点,则 depth(initial) - depth(cur)
为负值,所以长度 len
不会更新;假若 cur
是 initial
的兄弟节点,则两者相连必定经过 initial
的祖先节点,则在此处 len
也不会更新。
class Solution
{
private:
int len = 0; // 最短用时
int depth = -1; // 起始节点的高度
int dfs(TreeNode* root, int level, int start)
{
if (!root) return 0;
if (root->val == start) depth = level; // 当前节点即起始节点
int l = dfs(root->left, level + 1, start); // 左子树的树高
bool inLeft = depth != -1; // 起始节点是否在左子树上
int r = dfs(root->right, level + 1, start); // 右子树的树高
if (root->val == start) len = max(len, max(l, r)); // 情况1:感染以 start 为根结点的树所需时间
if (inLeft) len = max(len, depth - level + r); // 情况2:感染以 root 为根结点的树所需时间
else len = max(len, depth - level + l);
return max(l, r) + 1; // 返回树高
}
public:
int amountOfTime(TreeNode* root, int start)
{
dfs(root, 0, start);
return len;
}
};