AcWing第63场周赛+Leetcod第84场双周赛+第305场周赛

这篇博客主要解析了AcWing第63场周赛和LeetCode第84、305场周赛的四道编程题目,涉及数对计数、字符串消除、合并相似物品和统计坏数对的数目等算法问题。通过枚举、哈希表和深度优先搜索等方法进行求解,展示了在有限数据范围内如何高效解决编程竞赛中的常见问题。
摘要由CSDN通过智能技术生成

AcWing第63场周赛

第一题:4503. 数对数量

分析:因为本题数据范围较小,所以可以直接枚举。

代码:

#include<iostream>
int a,b,n;

using namespace std;

int main()
{
    int cnt = 0;
    cin >> a >> b >> n;
     for(int i = 0;i <= a;i ++){
         for(int j = 0;j <= b; j ++){
             if(i + j == n)cnt ++;
         }
     }
     cout << cnt;
     return 0;
}

第二题:4504. 字符串消除

分析: 任意次序取相邻做消除,最后结果是一样的。首先统计消除操作的数目,发现 如果是偶数,那么先手必输。可以利用栈的数据结构, 一出现成对就删除。

代码:

#include<iostream>
#include<cstring>

using namespace std;

int main() {
  string s;
  string stk;
  cin >> s;
  int ans = 0;
  for (auto &c : s) {
    if (stk.back() == c) {
      ans++;
      stk.pop_back();
    } else {
      stk.push_back(c);
    }
  }
  if (ans % 2 == 0)
    cout << "No";
  else
    cout << "Yes";
  return 0;
}

Leetcode第84场双周赛

第一题:2363. 合并相似的物品

分析:map可以用来同时存储一个物品的价值和重量,利用哈希表的自动升序,key存价值,将两个数组中相同价值的重量加在一起,再遍历三次即可得到结果

代码:

class Solution {
public:
    vector<vector<int>> mergeSimilarItems(vector<vector<int>>& items1, vector<vector<int>>& items2) {
        vector<vector<int>> res;
        map<int,int> m;
        for(int i = 0; i < items1.size() ;i++)
        {
            m[items1[i][0]] = items1[i][1];
        }
        for(int j = 0; j < items2.size() ;j++)
        {
           
            m[items2[j][0]] += items2[j][1];
            
            
        }
        for(auto it = m.begin(); it != m.end(); it++)
        {
            res.push_back(vector<int>{it->first, it->second});
            
        }
        return res;  
    }
};

第二题:2364. 统计坏数对的数目

分析:可以先将题目的不等式转换成j - nums[j] != i - nums[i]。这样问题便转换成了一个从后面的数向前面的数找不同的个数。利用哈希表记录每个数出现的次数,由下标 i 可知前面存在 i 个数,用i减去相同的个数便得到最后不同的个数。

代码:

class Solution {
public:
    long long countBadPairs(vector<int>& nums) {
        int n = nums.size();
        long long res = 0;
        unordered_map<int,int>count;
        for(int i = 0; i < n; i ++)
        {
           nums[i] = i - nums[i];
        }
        count[nums[0]] ++;
        for(int i = 1; i < n; i ++)
        {
            res += (i - count[nums[i]]);
            count[nums[i]] ++;
        }
        return res;
    }
};

Leetcode第305场周赛

第一题:2367. 算术三元组的数目

分析:由于该题的数据范围也比较小,还是可以通过暴力枚举。

代码:

class Solution {
public:
    int arithmeticTriplets(vector<int>& nums, int diff) {
        int res = 0;
        for(int i = 0;i < nums.size();i ++){
            for(int j = i + 1;j < nums.size();j ++){
                for(int k = j + 1;k < nums.size();k ++)
                        if(nums[j] - nums[i] == diff&&nums[k] - nums[j] == diff)
                            res ++;
            }
        }
        return res;
    }
};

第二题:2368. 受限条件下可到达节点的数目

分析:用一个vector数组来存储是否为限制节点,这样可以将o(n)复杂度降到o(1)。用二维vector数组restore来存储边,比如restore[0]存储的是与0相连的节点。unordered_set 来装存储已经遍历过的节点,由于0不可能是限制节点,0可以直接放进去。思路参考

代码:

class Solution {
public:
    int r = 1;
    vector<vector<int>> restore;  
    unordered_set<int> set;   
    vector<bool> Contain;
    int reachableNodes(int n, vector<vector<int>>& edges, vector<int>& restricted) {
        set.insert(0);
        restore.resize(100005);
        Contain.resize(1e5+5);
        for(int i = 0;i < restricted.size();i++){
            Contain[restricted[i]] = true;
        }
        for(int i = 0;i < edges.size();i++){
            restore[edges[i][0]].push_back(edges[i][1]);
            restore[edges[i][1]].push_back(edges[i][0]);
        }       
        auto a = restore[0];
        for(int i = 0;i < a.size();i++){
            if(!Contain[a[i]])
                dfs(a[i]);
        }return r;
    }  
    void dfs(int nextVal)
    {
        if(set.find(nextVal) != set.end())
            return;
        set.insert(nextVal);
        r++;
        auto a = restore[nextVal];
        for(int i = 0;i < a.size();i++){
            if(!Contain[a[i]])
                dfs(a[i]);
        }
    }    
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值