将标题首字母大写
我们顺序遍历title字符串,对于其中每个以空格为分界的单词,找出它的起始与末尾下标,判断它的长度。
class Solution{
public:
string capitalizeTitle(string title){
int n = title.size();
int l = 0, r = 0;
title.push_back(' ');
while(r < n){
while(title[r] != ' '){
r++;
}
if(r - l > 2){
title[l] = touuper(title[l]);
l++;
}
while(l < r){
title[l] = tolower(title[l]);
l++;
}
l = r + 1;
++r;
}
title.pop_back();
return title;
}
}
快乐数
class Solution {
public:
int sum(int n){
int ret = 0;
while(n){
ret += ((n%10)*(n%10));
n/=10;
}
return ret;
}
bool isHappy(int n) {
int i = 0;
while(n != 1){
i++;
n = sum(n);
if(i == 32){
return false;
}
}
return true;
}
};
用哈希集合检测循环
根据探索,猜测会有三种可能:
- 最终得到1
- 最终会进入循环
- 值会越来越大,最后接近无穷大
对于 333 位数的数字,它不可能大于 243243243。这意味着它要么被困在 243243243 以下的循环内,要么跌到 111。444 位或 444 位以上的数字在每一步都会丢失一位,直到降到 333 位为止。所以我们知道,最坏的情况下,算法可能会在 243243243 以下的所有数字上循环,然后回到它已经到过的一个循环或者回到 111。但它不会无限期地进行下去,所以我们排除第三种选择。
即使在代码中你不需要处理第三种情况,你仍然需要理解为什么它永远不会发生,这样你就可以证明为什么你不处理它。
完全二叉树的节点个数
/**
* 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:
int countNodes(TreeNode* root) {
if(root == nullptr){
return 0;
}else if(root->left == nullptr && root->right == nullptr){
return 1;
}
return 1+countNodes(root->left)+countNodes(root->right);
}
};
完全二叉树的定义如下:在完全二叉树除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
在受污染的二叉树中查找元素
深度优先搜索+哈希表
对二叉树的根节点root进行深度优先搜索,在搜索过程中,根据规则对遍历的节点的值进行恢复,并且将遍历的节点的值加入哈希表valSet中。调用find函数时,返回target值是否存在哈希表valSet中.
class FindElements {
private:
unordered_set<int> valSet;
void dfs(TreeNode *node, int val) {
if (node == nullptr) {
return;
}
node->val = val;
valSet.insert(val);
dfs(node->left, val * 2 + 1);
dfs(node->right, val * 2 + 2);
}
public:
FindElements(TreeNode* root) {
dfs(root, 0);
}
bool find(int target) {
return valSet.count(target) > 0;
}
};
翻转二叉树
递归
从根节点开始,递归地对树进行遍历,并从叶子节点开始翻转。
如果当前遍历到的节点root的左右子树都已经翻转,那么只需要交换两棵子树的位置,即可完成以root为根节点的整棵子树的翻转。
class Solution{
public:
TreeNode* invertTree(TreeNode* root){
if(root == nullptr){
return nullptr;
}
TreeNode* left = invertTree(root->left);
TreeNode* right = invertTree(root->right);
root->left = right;
root->right = left;
}
}
汇总区间
给定一个无重复元素的有序整数数组nums。
返回恰好覆盖数组中所有数字的最小有序区间范围列表。
nums的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于nums的数字x。
一次遍历
class Solution {
public:
vector<string> summaryRanges(vector<int>& nums) {
vector<string> ret;
int n = nums.size();
if(n == 0){
return ret;
}
int begin = 0;
int end = 0;
string str = to_string(nums[0]);
for(int i=1; i<n; i++){
if(nums[i] == nums[end]+1){
end++;
}else{
if(end!=begin){
str.append("->");
str.append(to_string(nums[end]));
}
begin = ++end;
ret.push_back(str);
str = to_string(nums[begin]);
}
if(end == n-1){
if(end!=begin){
str.append("->");
str.append(to_string(nums[end]));
}
}
}
ret.push_back(str);
return ret;
}
};
2的幂
class Solution {
public:
bool isPowerOfTwo(int n) {
int sum = 0;
while(n>0){
if(n%2){
sum++;
}
n = n/2;
if(sum > 1){
return false;
}
}
if(sum == 1){
return true;
}
return false;
}
};
有效的字母异位词
t是s的异位词等价于两个字符串排序后相等。
class Solution{
public:
bool isAnagram(string s,string t){
if(s.length() != t.length()){
return false;
}
sort(s.begin(), s.end());
sort(t.begin(), t.end());
return s==t;
}
}
最大二进制奇数
题目给定二进制字符串 sss 构造字典序最大的二进制奇数,根据定义可以知道字符串中每一位要么为 000,要么为 111。由于构造的数必须为奇数,则最低位必须为 111,因此我们从字符串 sss 中选择一个 111 放置到最低位。按照贪心原则,其余的 111 全部放在最高位,剩余的 000 放在剩下的位即可,直接构造目标字符串返回即可。
class Solution{
public:
string maximumOddBinaryNumber(string s){
int cnt = count(s.begin(),s.end(),'1');
return string(cnt-1,'1') + string(s.length()-cnt,'0') + '1';
}
}
Nim游戏
让我们考虑一些小例子。显而易见的是,如果石头堆中只有一块、两块、或是三块石头,那么在你的回合,你就可以把全部石子拿走,从而在游戏中取胜;如果堆中恰好有四块石头,你就会失败。因为在这种情况下不管你取走多少石头,总会为你的对手留下几块,他可以将剩余的石头全部取完,从而他可以在游戏中打败你。因此,要想获胜,在你的回合中,必须避免石头堆中的石子数为 4 的情况。
- 如果有5、6、7块石头,只有控制自己拿取的石头数,使对手恰好留下4块,就会输掉比赛。
- 如果有八块石头,还是会输掉比赛,因为无论挑出1、2、3,对手可以挑3、2、1,使得下一轮时我又有四块。
- 如果总的石头数不是4的倍数,只要每次取x%4个石头,剩余石头数必然为4的倍数,从而对手会输掉比赛。