Yra's blog Yra's blog
Homepage
  • LeetCode周赛
  • Acwing周赛
  • 刷题整理
  • 题解
  • CPP
  • Golang
  • System

    • MIT6.S081 Labs
  • Computer Networking

    • CS144: Computer Networking
  • DataBase

    • MySQL
    • Redis
  • Others

    • ......
  • Paper Reading

    • Petri Net
  • Static Analysis

    • NJU Course Notes
  • Deep Learning

    • Dive into Deep Learning
Casual Records
Archives

Yra

Only a vegetable dog.
Homepage
  • LeetCode周赛
  • Acwing周赛
  • 刷题整理
  • 题解
  • CPP
  • Golang
  • System

    • MIT6.S081 Labs
  • Computer Networking

    • CS144: Computer Networking
  • DataBase

    • MySQL
    • Redis
  • Others

    • ......
  • Paper Reading

    • Petri Net
  • Static Analysis

    • NJU Course Notes
  • Deep Learning

    • Dive into Deep Learning
Casual Records
Archives
  • LeetCode周赛

    • Contests

      • LeetCode 307th Weekly Contest
      • LeetCode 308th Weekly Contest
      • LeetCode 86th Biweekly Contest
      • LeetCode 310th Weekly Contest
      • LeetCode 312th Weekly Contest
      • LeetCode 313th Weekly Contest
      • LeetCode 88th Biweekly Contest
      • LeetCode 321th Weekly Contest
        • A
          • 题目
          • 思路
          • 1. 枚举 $O(n)$
          • 代码
        • B
          • 题目
          • 思路
          • 1. 双指针 + 遍历一次 $O(n)$
          • 代码
        • C
          • 题目
          • 思路
          • 1.后缀最大值 $O(n)$
          • 代码
        • D
          • 题目
          • 思路
          • 1. 等价转换 + 哈希表 $O(n)$
          • 代码
          • 代码
  • Acwing周赛

  • 刷题日寄

  • 题解

  • Competitive Programming
  • LeetCode周赛
  • Contests
Yra
2022-11-28
目录

LeetCode 321th Weekly Contest

好久没打周赛了,这次比较简单,纯纯手速场,写的基本都是暴力,可能不是最优写法。

# A

# 题目

2485. 找出中枢整数 - 力扣(LeetCode) (opens new window)

# 思路

# 1. 枚举

利用等差数列求和公式枚举即可。

# 代码


    class Solution {
    public:
        int pivotInteger(int n) {
            for (int i = 1; i<= n; i++) {
                if ((1 + i) * i / 2 == (i + n) * (n - i + 1) / 2) {
                    return i;
                }
            }
            return -1;
        }
    };
    
    // Make sure to add code blocks to your code group

    # B

    # 题目

    2486. 追加字符以获得子序列 - 力扣(LeetCode) (opens new window)

    # 思路

    # 1. 双指针 + 遍历一次

    只需要找到字符串 t 在 字符串 s 的子序列中存在的最长前缀即可,因此我们利用双指针分别指向两个数组,看看 s 能满足的 t 的最长前缀,最后答案是 t 的长度减去能满足的最长前缀的长度。

    # 代码


      class Solution {
      public:
        int appendCharacters(string s, string t) {
            int i = 0, j = 0;
            int n = s.size(), m = t.size();
            for (; i < n; i++) {
                if (s[i] == t[j]) {
                    j++;
                }
            }
            return m - j;
        }
      };
      
      // Make sure to add code blocks to your code group

      # C

      # 题目

      2487. 从链表中移除节点 - 力扣(LeetCode) (opens new window)

      # 思路

      # 1.后缀最大值

      比赛时写的代码,可能有点繁杂,也不是最优的,不过想法应该是比较简单的。

      先用数组 a 将链表存起来,然后得到后缀最大值数组 sufmax,我们要保留的元素满足其右侧不存在一个比他大的元素,所以对于下标 i,如果 a[i] == sufmax[i],我们就保留下标为 i 的元素,最后用链表存起来即可

      # 代码


        /**
        * Definition for singly-linked list.
        * struct ListNode {
        *     int val;
        *     ListNode *next;
        *     ListNode() : val(0), next(nullptr) {}
        *     ListNode(int x) : val(x), next(nullptr) {}
        *     ListNode(int x, ListNode *next) : val(x), next(next) {}
        * };
        */
        class Solution {
        public:
          ListNode* removeNodes(ListNode* head) {
              std::vector<int> a;
              while (head) {
                  a.emplace_back(head->val);
                  head = head->next;
              }
              int n = a.size();
              std::vector<int> sufmax(n);
              sufmax.back() = a.back();
              for (int i = n - 2; ~i; i--) {
                  sufmax[i] = std::max(a[i], sufmax[i + 1]);
              }
              auto res = new ListNode();
              auto t = res;
              for (int i = 0; i < n; i++) {
                  if (sufmax[i] == a[i]) {
                      t->val = a[i];
                      t->next = new ListNode();
                      t = t->next;
                  }
              }
              auto tt = res;
              while (tt->next != t) {
                  tt = tt->next;
              }
              tt->next = nullptr;
              return res;
          }
        };
        
        // Make sure to add code blocks to your code group

        # D

        # 题目

        2488. 统计中位数为 K 的子数组 - 力扣(LeetCode) (opens new window)

        # 思路

        # 1. 等价转换 + 哈希表

        赛时的写法太烦了,不过整体思路差不多,数组的每个元素进行转换,如果大于 k 则为 1,小于 k 则为 -1,等于 k 则为 0。

        那么我们就可以将问题转化寻找满足条件的子数组个数,条件是如果子数组长度为奇数,则子数组和为 0,如果长度为 偶数,则子数组和为 1。

        我的写法因为 unordered_map 不支持复杂的映射,所以只能用 map 来实现哈希表,整体时间复杂度会因为排序多一个

        # 代码


          class Solution {
          public:
            int countSubarrays(vector<int>& nums, int k) {
                std::map<std::pair<int, int>, int> pos; 
                for (auto &x : nums) {
                    if (x > k) x = 1;
                    else if (x == k) x = 0;
                    else x = -1;
                }
                
                int n = nums.size();
                std::vector<int> psum(n);
                psum[0] = nums[0];
                for (int i = 1; i < n; i++) {
                    psum[i] = psum[i - 1] + nums[i];
                }
                int res = 0;
                for (int i = 0; i < n; i++) {
                    int len = i + 1;
                    int tozero = psum[i];
                    int toone = psum[i] - 1;
                    if (((len & 1) && psum[i] == 0) || ((len % 2 == 0) && psum[i] == 1)) {
                        res++;
                    }
                    res += pos[{tozero, (len & 1) ^ 1}];
                    res += pos[{toone, (len & 1)}];
                    
                    pos[{psum[i], (i + 1) & 1}]++;
                }
                return res;
            }
          };
          
          // Make sure to add code blocks to your code group

          这里贴一下灵神的代码,比我的会高效简洁很多(%%%%)

          等价转换(Python/Java/C++/Go) - 统计中位数为 K 的子数组 - 力扣(LeetCode) (opens new window)

          很容易发现子数组一定是包含 k 的,因此可以从 k 的位置出发,向左向右进行延伸,这样更高效,而且更容易去判断长度的奇偶性,cnt[i] 如果 i 是 奇数,则一定是朝一个方向衍生了奇数个数字,偶数同理,(因为在这里排除了 k 的情况,所以只会 +1 -1)那么向一边衍生 cnt[i] 位,向另一边衍生 cnt[i] 位,加上中间的 k,数字个数一定是 2 * i + 1 个,也就是奇数,当另一边衍生 cnt[i + 1] 位时,则一定是偶数长度。

          # 代码


            class Solution {
            public:
              int countSubarrays(vector<int> &nums, int k) {
                  int pos = find(nums.begin(), nums.end(), k) - nums.begin(), n = nums.size();
                  unordered_map<int, int> cnt;
                  cnt[0] = 1; // i=pos 的时候 c 是 0,直接记到 cnt 中,这样下面不是大于就是小于
                  for (int i = pos + 1, c = 0; i < n; ++i) {
                      c += nums[i] > k ? 1 : -1;
                      ++cnt[c];
                  }
            
                  int ans = cnt[0] + cnt[1]; // i=pos 的时候 c 是 0,直接加到答案中,这样下面不是大于就是小于
                  for (int i = pos - 1, c = 0; i >= 0; --i) {
                      c += nums[i] < k ? 1 : -1;
                      ans += cnt[c] + cnt[c + 1];
                  }
                  return ans;
              }
            };
            
            // Make sure to add code blocks to your code group

            #Competitive Programming#LeetCode周赛#Contests
            Last Updated: 3/4/2023, 5:38:14 PM
            LeetCode 88th Biweekly Contest
            Acwing 64th Weekly Contest

            ← LeetCode 88th Biweekly Contest Acwing 64th Weekly Contest→

            最近更新
            01
            408 计组笔记
            07-19
            02
            Dive into Deep Learning
            01-27
            03
            25 考研随记
            11-27
            更多文章>
            Theme by Vdoing | Copyright © 2022-2025
            • 跟随系统
            • 浅色模式
            • 深色模式
            • 阅读模式