title: LeetCode - 做题笔记
tags:

  • leetcode
  • 每日一题
    abbrlink: ‘2e627859’
    date: 2022-03-03 15:03:41

这篇博客集中整理在LeetCode的刷题记录,方便查阅

258. 各位相加 - 力扣(LeetCode) (leetcode-cn.com)

代码

  1. class Solution {
  2. public:
  3. int addDigits(int num) {
  4. int ans=999999;
  5. while(ans >= 10)
  6. {
  7. ans=0;
  8. while(num!=0)
  9. {
  10. ans = ans + num%10;
  11. num/=10;
  12. }
  13. num=ans;
  14. }
  15. return ans;
  16. }
  17. };

401. 二进制手表 - 力扣(LeetCode) (leetcode-cn.com)

题目

二进制手表顶部有 4 个 LED 代表 小时(0-11),底部的 6 个 LED 代表 分钟(0-59)。每个 LED 代表一个 0 或 1,最低位在右侧。

例如,下面的二进制手表读取 “3:25” 。

给你一个整数 turnedOn ,表示当前亮着的 LED 的数量,返回二进制手表可以表示的所有可能时间。你可以 按任意顺序 返回答案。

小时不会以零开头:

例如,”01:00” 是无效的时间,正确的写法应该是 “1:00” 。
分钟必须由两位数组成,可能会以零开头:

例如,”10:2” 是无效的时间,正确的写法应该是 “10:02” 。

示例 1:

输入:turnedOn = 1
输出:[“0:01”,”0:02”,”0:04”,”0:08”,”0:16”,”0:32”,”1:00”,”2:00”,”4:00”,”8:00”]
示例 2:

输入:turnedOn = 9
输出:[]

提示:

0 <= turnedOn <= 10

思路

思路比较直接,就是枚举出这个二进制数的每一位,然后分别判定是否符合时间单位的标准,如果是的话就保存下来输出即可,主要还是要学习二进制位运算的相关操作。

C++代码

  1. class Solution {
  2. public:
  3. vector<string> readBinaryWatch(int num) {
  4. vector<string> res;
  5. char str[10];
  6. for(int i=0;i<1<<10;i++)//枚举每一位
  7. {
  8. int s=0;
  9. for(int j=0;j<10;j++)
  10. {
  11. if(i>>j & 1)//如果i的第j位是1
  12. s++;
  13. }
  14. if(s==num)
  15. {
  16. int a=i>>6, b=i&63;//63=各个位均为1,a取了i的小时(最高的四位)
  17. if(a<12 && b<60)
  18. {
  19. sprintf(str, "%d:%02d", a, b);
  20. res.push_back(str);
  21. }
  22. }
  23. }
  24. return res;
  25. }
  26. };

2104. 子数组范围和 - 力扣(LeetCode) (leetcode-cn.com)

思路

枚举计算出每个子数组之间最大值与最小值的差值并加在最终结果中即可

代码

  1. class Solution {
  2. public:
  3. long long subArrayRanges(vector<int>& nums) {
  4. int n = nums.size();
  5. long long res=0;
  6. for(int i=0;i<n;i++)
  7. {
  8. int minVal=INT_MAX, maxVal=INT_MIN;
  9. for(int j=i;j<n;j++)
  10. {
  11. minVal = min(minVal, nums[j]);
  12. maxVal = max(maxVal, nums[j]);
  13. res+=maxVal - minVal;
  14. }
  15. }
  16. return res;
  17. }
  18. };

521. 最长特殊序列 Ⅰ - 力扣(LeetCode) (leetcode-cn.com)

思路

究竟贪心题,如果两者长度相等,那么一定没有特殊串,如果长度不等,那么长的一串一定不会不特殊(短的再怎么删也不会变长)

代码

  1. class Solution {
  2. public:
  3. int findLUSlength(string a, string b) {
  4. if(a==b) return -1;
  5. return max(a.size(), b.size());
  6. }
  7. };

504. 七进制数 - 力扣(LeetCode) (leetcode-cn.com)

代码

  1. class Solution {
  2. public:
  3. string convertToBase7(int num) {
  4. if(!num) return "0";
  5. bool is_neg = num < 0;
  6. num = abs(num);
  7. string res;
  8. while(num)
  9. res+= to_string(num%7), num/=7;
  10. reverse(res.begin(), res.end());
  11. if(is_neg)
  12. res = '-'+res;
  13. return res;
  14. }
  15. };

LeetCode 2049. 统计最高分的节点数目

思路

在一棵树中,当把一个节点和与它相连的所有边删除,剩余部分最多是三棵非空子树,即原节点的左子树,右子树,以及把以这个节点为根结点的子树移除所形成的子树(除根结点外均有),最少数量则无此类特性。而题目中提到各节点的分数为这些子树的节点个数的乘积。我们可以先用 parents 数组统计出每个节点的子节点,然后使用深度优先搜索来计算以每个节点为根结点的子树的大小,同时计算每个节点的大小,作为深度优先搜索的返回值,最后统计最大分数出现的次数。在实现上,统计最大分数出现的次数可以放到深度优先搜索中完成,从而节省一部分空间。

代码

  1. class Solution {
  2. public:
  3. long long n;
  4. long long maxScore=0;
  5. long long cnt=0;
  6. vector<vector<int>> children;
  7. int dfs(int node)
  8. {
  9. long long size = n-1;
  10. long long score = 1;
  11. for(int c:children[node])
  12. {
  13. int t = dfs(c);
  14. score *= t;
  15. size -= t;//算出节点大小,让size减去他
  16. }
  17. if(node != 0)
  18. {
  19. score *= size;
  20. }
  21. if(score == maxScore)
  22. cnt++;
  23. else if(score > maxScore)
  24. {
  25. maxScore = score;
  26. cnt=1;
  27. }
  28. return n-size;
  29. }
  30. int countHighestScoreNodes(vector<int>& parents) {
  31. this->n = parents.size();
  32. this->children = vector<vector<int>> (n);
  33. for(int i=0;i<n;i++)
  34. {
  35. int p = parents[i];
  36. if(p!=-1)
  37. {
  38. children[p].emplace_back(i);//记录p节点的儿子节点
  39. }
  40. }
  41. dfs(0);
  42. return cnt;
  43. }
  44. };

LeetCode 599. 两个列表的最小索引总和

思路

利用哈希表存储后进行字符串索引查找,同时通过map记录每个哈希值的索引数值大小

代码

  1. class Solution {
  2. public:
  3. vector<string> findRestaurant(vector<string>& list1, vector<string>& list2) {
  4. unordered_map<string, int> hash;
  5. for(int i=0;i<list1.size();i++)
  6. hash[list1[i]] = i;
  7. int sum = INT_MAX;
  8. vector<string> res;
  9. for(int i=0;i<list2.size();i++)
  10. {
  11. string& s = list2[i];
  12. if(hash.count(s))
  13. {
  14. int k = hash[s] + i;
  15. if(k < sum)
  16. {
  17. sum = k;
  18. res = {s};
  19. }
  20. else if(k==sum)
  21. {
  22. res.push_back(s);
  23. }
  24. }
  25. }
  26. return res;
  27. }
  28. };

2044. 统计按位或能得到最大值的子集数目 - 力扣(LeetCode) (leetcode-cn.com)

思路

爆搜思路,对于任意一位 xx 而言,都有选和不选两种选择,分别对应了dfs(u + 1, val | nums[x])dfs(u + 1, val)两条搜索路径,在搜索所有状态过程中,使用全局变量maxans来记录最大得分以及取得最大得分的状态数量。

代码

  1. class Solution {
  2. public:
  3. vector<int> nums;
  4. int ans=0, max=0;
  5. int countMaxOrSubsets(vector<int>& _nums) {
  6. nums = _nums;
  7. dfs(0,0);
  8. return ans;
  9. }
  10. void dfs(int u, int val)
  11. {
  12. if(u == nums.size())
  13. {
  14. if(val > max)
  15. {
  16. max = val;
  17. ans = 1;
  18. }
  19. else if(val == max) ans++;
  20. return;
  21. }
  22. dfs(u+1, val | nums[u]);
  23. dfs(u+1, val);
  24. }
  25. };

720. 词典中最长的单词 - 力扣(LeetCode) (leetcode-cn.com)

思路

先将输入的words进行排序,规则为先按长度升序排序,在长度相同情况下再按照字典序降序排序,这样就可以保证我们在后面遍历每个单词时,比该单词短的全部子单词已全部遍历过,且每次遇到符合要求的单词一定是最长且字典序最小的单词,可以直接将其更新为答案。

代码

  1. class Solution {
  2. public:
  3. string longestWord(vector<string>& words) {
  4. sort(words.begin(), words.end(), [](const string &a, const string &b){
  5. return a.size()!=b.size()?a.size()<b.size():a>b;
  6. });
  7. string longest;
  8. unordered_set<string> candidates = {""};
  9. for(auto &word : words)
  10. {
  11. if(candidates.count(word.substr(0, word.size() - 1)))
  12. {
  13. longest = word;
  14. candidates.emplace(word);
  15. }
  16. }
  17. return longest;
  18. }
  19. };