开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情
[811. 子域名访问计数]
题目是想要我们统计所有域名及其出现的次数,我们 自然就联想到映射,然后二者组合返回
我们可以发现: rep d1.d2.d3 其中req表示访问域名的次数, d1.d2.d3 d2.d3 d3都是域名,只不过他们的层级不相同而已, 并且访问次数和域名是以空格区分的,域名和域名是以.区分的
所以做法为:遍历计数配对域名数组,先根据空格的位置,记录访问次数, 然后划分域名,对应域名累加访问次数
class Solution {
public:
vector<string> subdomainVisits(vector<string>& cpdomains) {
unordered_map<string,int> map;//域名-访问次数
//遍历计数配对域名数组
for(auto& str:cpdomains)
{
//根据空格区分访问次数和域名
int index = str.find(' ');
//注意:atoi的参数是const char* 而str.substr(0,index)返回的是string
//当然也可以使用:stoi函数,作用也是字符串转为整形,参数是string
int times = stoi(str.substr(0,index));
//int times = atoi(str.substr(0,index).c_str());//访问次数,字符串->整数
string dmName = str.substr(index+1);//index往后的就是域名
//划分域名,统计每个域名的访问次数
while(index > 0)
{
map[dmName] += times;
//划分下一级的域名
//discuss.leetcode.com -> leetcode.com ->com ->跳出循环
index = dmName.find('.');
dmName = dmName.substr(index+1);
}
}
//遍历哈希表 存放结果
vector<string> ans;
for(auto& kv:map)
{
ans.push_back(to_string(kv.second) + " " + kv.first); //访问次数 空格 域名
}
return ans;
}
};
需要注意atoi函数和stoi函数的区别!
-
共同点:都是c++的字符处理函数,把字符串转化为整形
-
区别:atoi()的参数是const char *,因此对于string类型的字符串str我们必须调用c_str()的方法把这个string 转换成const char *类型的
- stoi()的参数是const string&
[338. 比特位计数]
做法1:暴力做法 直接求0~n的每个数的比特位为1的情况放到数组中
class Solution {
public:
//计算n中比特位为1的个数
int CountBit(int n)
{
int count = 0;
while(n)
{
count++;
n&=(n-1);
}
return count;
}
/*
int CountBit(int n)
{
int count = 0;
while(n) count+=n&1,n>>=1;
return count;
}
*/
vector<int> countBits(int n) {
vector<int> ans(n+1,0);
for(int i = 0;i<=n;i++)
{
ans[i] = CountBit(i);
}
return ans;
}
};
做法2:观察规律
dp[i]的含义是:i的比特位当中1的个数
对于所有的数字,无非就是奇数和偶数,假设当前的数为i
- 奇数: i的二进制表示当中,一定比它前面的i-1的那个偶数多一个1,多的就是最低位的比特位1
- 偶数:i的二进制表示当中,比特位1的个数一定和i/2这个数的比特位1的个数是一样的, 因为偶数最低位肯定是0, /2就是右移一位.也就是把0抹掉,1的个数是不变的
所以我们可以得到下面的状态方程:
当i为奇数时: dp[i] = dp[i-1]+1
当i为偶数时: dp[i] = dp[i/2]
class Solution {
public:
vector<int> countBits(int n) {
vector<int> res(n+1,0);
for(int i = 0;i<=n;i++)
{
if(i&1) //i是奇数
res[i] = res[i-1]+1;
else //i是偶数
res[i] = res[i/2];
}
return res;
}
};
实际上,上述的方程可以进一步优化:
- 当i为奇数的时候,i-1为偶数, 其二进制中1的个数一定和它/2之后的个数一样, dp[i-1] = dp[(i-1)/2]
- 因为i为奇数,所以 (i-1)/2 == i/2
所以转移方程可以是: dp[i/2] + i%2 如果i为奇数:i%2 == 1 i为偶数:i%2 == 0
其中i/2 == i >>1 i%2 == i&1
class Solution {
public:
vector<int> countBits(int n) {
vector<int> res(n+1,0);
for(int i = 0;i<=n;i++)
{
//res[i] = res[i/2] + i%2;
res[i] = res[i>>1] + (i&1);
}
return res;
}
};