leetcode解题思路分析(八十三)726 - 732 题

快来打我* 2022-10-19 14:55 300阅读 0赞
  1. 原子的数量
    给定一个化学式formula(作为字符串),返回每种原子的数量。

使用哈希表存储原子名和数量,使用栈来应对可能出现的括号,由此可解

  1. class Solution {
  2. public:
  3. string countOfAtoms(string formula) {
  4. int i = 0, n = formula.length();
  5. auto parseAtom = [&]() -> string {
  6. string atom;
  7. atom += formula[i++]; // 扫描首字母
  8. while (i < n && islower(formula[i])) {
  9. atom += formula[i++]; // 扫描首字母后的小写字母
  10. }
  11. return atom;
  12. };
  13. auto parseNum = [&]() -> int {
  14. if (i == n || !isdigit(formula[i])) {
  15. return 1; // 不是数字,视作 1
  16. }
  17. int num = 0;
  18. while (i < n && isdigit(formula[i])) {
  19. num = num * 10 + int(formula[i++] - '0'); // 扫描数字
  20. }
  21. return num;
  22. };
  23. stack<unordered_map<string, int>> stk;
  24. stk.push({ });
  25. while (i < n) {
  26. char ch = formula[i];
  27. if (ch == '(') {
  28. i++;
  29. stk.push({ }); // 将一个空的哈希表压入栈中,准备统计括号内的原子数量
  30. } else if (ch == ')') {
  31. i++;
  32. int num = parseNum(); // 括号右侧数字
  33. auto atomNum = stk.top();
  34. stk.pop(); // 弹出括号内的原子数量
  35. for (auto &[atom, v] : atomNum) {
  36. stk.top()[atom] += v * num; // 将括号内的原子数量乘上 num,加到上一层的原子数量中
  37. }
  38. } else {
  39. string atom = parseAtom();
  40. int num = parseNum();
  41. stk.top()[atom] += num; // 统计原子数量
  42. }
  43. }
  44. auto &atomNum = stk.top();
  45. vector<pair<string, int>> pairs;
  46. for (auto &[atom, v] : atomNum) {
  47. pairs.emplace_back(atom, v);
  48. }
  49. sort(pairs.begin(), pairs.end());
  50. string ans;
  51. for (auto &p : pairs) {
  52. ans += p.first;
  53. if (p.second > 1) {
  54. ans += to_string(p.second);
  55. }
  56. }
  57. return ans;
  58. }
  59. };
  1. 自除数
    给定上边界和下边界数字,输出一个列表,列表的元素是边界(含边界)内所有的自除数。

暴力遍历

  1. class Solution {
  2. public:
  3. vector<int> selfDividingNumbers(int left, int right) {
  4. vector<int> res;
  5. for (int i = left; i <= right; i ++ ) //遍历范围内每个数
  6. {
  7. int t = i;
  8. bool flag = true; //设置一个标志位
  9. while (t) //用t来遍历i中的位
  10. {
  11. int div = t % 10;
  12. if (div == 0) flag = false; //只要其中有值为0的位,或者除不尽的位
  13. else if ((i % (t % 10)) != 0) flag = false; //就把标志位设为false
  14. t /= 10;
  15. }
  16. if (flag) res.push_back(i); //把符合条件的数放入结果数组中
  17. }
  18. return res;
  19. }
  20. };
  1. 我的日程安排表1
    实现一个 MyCalendar 类来存放你的日程安排。如果要添加的时间内没有其他安排,则可以存储这个新的日程安排。

使用set即可

  1. class MyCalendar {
  2. private:
  3. map<int, int> m;
  4. public:
  5. MyCalendar() {
  6. }
  7. bool book(int start, int end) {
  8. // start 已重复
  9. if (m.find(start) != m.end())
  10. {
  11. return false;
  12. }
  13. auto pos = m.emplace(start, end).first;
  14. // 和上一个比较
  15. if (pos != m.begin())
  16. {
  17. --pos;
  18. if (pos->second > start)
  19. {
  20. m.erase(start);
  21. return false;
  22. }
  23. // 恢复回去
  24. ++pos;
  25. }
  26. // 和下一个比较
  27. ++pos;
  28. if (pos != m.end())
  29. {
  30. if (pos->first < end)
  31. {
  32. m.erase(start);
  33. return false;
  34. }
  35. }
  36. return true;
  37. }
  38. };
  39. /** * Your MyCalendar object will be instantiated and called as such: * MyCalendar* obj = new MyCalendar(); * bool param_1 = obj->book(start,end); */
  1. 统计不同回文子序列
    给定一个字符串 S,找出 S 中不同的非空回文子序列个数,并返回该数字与 10^9 + 7 的模。

动态规划求解

  1. class Solution {
  2. public:
  3. int countPalindromicSubsequences(string s) {
  4. int n = s.size();
  5. vector<vector<int>> f(n,vector<int>(n,0));
  6. for(int i=0;i<n;i++)f[i][i]=1;
  7. const int mod = 1e9+7;
  8. for(int i=n-2;i>=0;i--)
  9. {
  10. for(int j=i+1;j<n;j++)
  11. {
  12. if(s[i]!=s[j])f[i][j]=f[i+1][j]+f[i][j-1]-f[i+1][j-1];
  13. else
  14. {
  15. f[i][j] = f[i+1][j-1]*2+2;
  16. int l=i+1,r=j-1;
  17. while(l<=r&&s[l]!=s[i])l++;
  18. while(l<=r&&s[r]!=s[i])r--;
  19. // 第2.1种情况 中间有1个s[i]
  20. if(l==r)f[i][j]--;
  21. // 第2.2种情况 中间有≥2个s[i]
  22. else if(l<r)f[i][j] -=2+f[l+1][r-1];
  23. }
  24. f[i][j]=(f[i][j]>=0)?f[i][j]%mod:f[i][j]+mod;
  25. }
  26. }
  27. return f[0][n-1];
  28. }
  29. };
  1. 我的日程安排表2
    实现一个 MyCalendar 类来存放你的日程安排。如果要添加的时间内不会导致三重预订时,则可以存储这个新的日程安排。

用数组存储每个区间以及存储twice的情况,判断twice,加入则加入普通存储

  1. class MyCalendarTwo {
  2. vector<vector<int>> datas;
  3. vector<vector<int>> twice;
  4. bool find(int start, int end)
  5. {
  6. for (const vector<int>& d : twice)
  7. {
  8. if (!(d[0] >= end || d[1] <= start))
  9. return true;
  10. }
  11. return false;
  12. }
  13. public:
  14. MyCalendarTwo() {
  15. datas.clear();
  16. twice.clear();
  17. }
  18. bool book(int start, int end) {
  19. if (find(start, end))
  20. return false;
  21. for (const vector<int>& d : datas)
  22. {
  23. if (!(d[0] >= end || d[1] <= start))
  24. twice.push_back({ max(d[0], start), min(end, d[1])});
  25. }
  26. datas.push_back({ start, end});
  27. return true;
  28. }
  29. };
  30. /** * Your MyCalendarTwo object will be instantiated and called as such: * MyCalendarTwo* obj = new MyCalendarTwo(); * bool param_1 = obj->book(start,end); */
  1. 我的日程安排表2
    给你一些日程安排 [start, end) ,请你在每个日程安排添加后,返回一个整数 k ,表示所有先前日程安排会产生的最大 k 次预订。

线段树处理。

  1. const int MX = 1e5 + 5;
  2. const int M = 1e9;
  3. class MyCalendarThree {
  4. public:
  5. int ls[MX], rs[MX], sum[MX], lz[MX];
  6. int cnt, root;
  7. MyCalendarThree() {
  8. ls[0] = rs[0] = sum[0] = lz[0] = 0;
  9. cnt = 0;
  10. root = ++cnt;
  11. init_node(root);
  12. }
  13. void init_node(int rt) {
  14. ls[rt] = rs[rt] = sum[rt] = lz[rt] = 0;
  15. }
  16. void PushUP(int rt) {
  17. int l = ls[rt], r = rs[rt];
  18. sum[rt] = max(sum[l] + lz[l], sum[r] + lz[r]);
  19. }
  20. void update(int L, int R, int l, int r, int &rt) {
  21. if(rt == 0) {
  22. rt = ++cnt;
  23. init_node(rt);
  24. }
  25. if(L <= l && R >= r) {
  26. lz[rt]++;
  27. return;
  28. }
  29. int m = (l + r) >> 1;
  30. if(L <= m) update(L, R, l, m, ls[rt]);
  31. if(R > m) update(L, R, m + 1, r, rs[rt]);
  32. PushUP(rt);
  33. }
  34. int book(int l, int r) {
  35. if(l < r) update(l, r - 1, 0, M, root);
  36. return sum[root] + lz[root];
  37. }
  38. };
  1. 图像渲染
    有一幅以二维整数数组表示的图画,每一个整数表示该图画的像素值大小,数值在 0 到 65535 之间。给你一个坐标 (sr, sc) 表示图像渲染开始的像素值(行 ,列)和一个新的颜色值 newColor,让你重新上色这幅图像。

dfs和bfs的简单运用

  1. class Solution {
  2. public:
  3. const int dx[4] = { 1, 0, 0, -1};
  4. const int dy[4] = { 0, 1, -1, 0};
  5. void dfs(vector<vector<int>>& image, int x, int y, int color, int newColor) {
  6. if (image[x][y] == color) {
  7. image[x][y] = newColor;
  8. for (int i = 0; i < 4; i++) {
  9. int mx = x + dx[i], my = y + dy[i];
  10. if (mx >= 0 && mx < image.size() && my >= 0 && my < image[0].size()) {
  11. dfs(image, mx, my, color, newColor);
  12. }
  13. }
  14. }
  15. }
  16. vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
  17. int currColor = image[sr][sc];
  18. if (currColor != newColor) {
  19. dfs(image, sr, sc, currColor, newColor);
  20. }
  21. return image;
  22. }
  23. };

发表评论

表情:
评论列表 (有 0 条评论,300人围观)

还没有评论,来说两句吧...

相关阅读