力扣第447场周赛

这次终于赶上力扣的周赛了, 赛时成绩如下(依旧还是三题 ):

  1. 统计被覆盖的建筑

给你一个正整数 n,表示一个 n x n 的城市,同时给定一个二维数组 buildings,其中 buildings[i] = [x, y] 表示位于坐标 [x, y] 的一个 唯一建筑。

如果一个建筑在四个方向(左、右、上、下)中每个方向上都至少存在一个建筑,则称该建筑 被覆盖

返回 被覆盖的建筑数量。

数据范围如下:

  • 2 <= n <= 10^5
  • 1 <= buildings.length <= 10^5
  • buildings[i] = [x, y]
  • 1 <= x, y <= n
  • buildings 中所有坐标均 唯一
    解题思路:题目描述的是一个建筑,在上下左右四个方向只要有建筑就行(不一定相邻)

下面代码中提供了具体实现思路。

代码如下:

cpp 复制代码
class Solution {
public:
    int countCoveredBuildings(int n, vector<vector<int>>& buildings) {
        unordered_map<int,vector<int>> a,b;
        for(auto& v: buildings){
            int x=v[0]; int y=v[1];
            a[x].push_back(y);
            b[y].push_back(x);
        }
        for(auto& x:a){
            auto& va=x.second;
            sort(va.begin(),va.end());
        }
        for(auto& y:b){
            auto& va=y.second;
            sort(va.begin(),va.end());
        }
        int cnt=0;
        for(auto& v:buildings){
            int x=v[0]; int  y=v[1];
            auto& r=a[x];
            auto& c=b[y];
            auto itX=lower_bound(c.begin(),c.end(),x);
            bool l_one=(itX!=c.begin()); bool r_one=(next(itX)!=c.end());
            auto itY=lower_bound(r.begin(),r.end(),y);
            bool l_two=(itY!=r.begin()); bool r_two=(next(itY)!=r.end());
            if(l_one&&r_one&&l_two&&r_two) cnt++;  
        }
        return cnt;
    }
};
1. 统计x相等的  2. 统计y相等的
eg: [[1,2],[2,2],[3,2],[2,1],[2,3]]

x:
(1,2) 
(2,1) (2,2) (2,3)
(3,2)

y:
(2,3)
(1,2) (2,2) (3,2)
(2,1)

eg: (2,2) 检查(2,2)坐标的x左右侧和y的左右侧 x: (1,3) y: (1,3) 符合题意
  1. 针对图的路径存在性查询 I

给你一个整数 n,表示图中的节点数量,这些节点按从 0n - 1 编号。

同时给你一个长度为 n 的整数数组 nums,该数组按 非递减 顺序排序,以及一个整数 maxDiff

如果满足 |nums[i] - nums[j]| <= maxDiff(即 nums[i]nums[j]绝对差 至多为 maxDiff),则节点 i 和节点 j 之间存在一条 无向边

此外,给你一个二维整数数组 queries。对于每个 queries[i] = [ui, vi],需要判断节点 uivi 之间是否存在路径。

返回一个布尔数组 answer,其中 answer[i] 等于 true 表示在第 i 个查询中节点 uivi 之间存在路径,否则为 false

数据范围如下:

  • 1 <= n == nums.length <= 10^5
  • 0 <= nums[i] <= 10^5
  • nums非递减顺序排序。
  • 0 <= maxDiff <= 10^5
  • 1 <= queries.length <= 10^5
  • queries[i] == [ui, vi]
  • 0 <= ui, vi < n
    解题思路:没啥好说的,直接套并查集模版就行(我前面的基础算法学习中提到了)
cpp 复制代码
class DisjointSet {
    vector<int> fa; 
    vector<int> sz; 

public:
    int cc; 
    DisjointSet(int n) : fa(n), sz(n, 1), cc(n) {
        ranges::iota(fa, 0);
    }
    int find(int x) {
        if (fa[x] != x) {
            fa[x] = find(fa[x]);
        }
        return fa[x];
    }
    bool is_same(int x, int y){
        return find(x) == find(y);
    }
    bool Union(int from, int to) {
        int x = find(from), y = find(to);
        if (x == y) {
            return false;
        }
        fa[x] = y; 
        sz[y] += sz[x]; 
        cc--; 
        return true;
    }
    int get_size(int x) {
        return sz[find(x)];
    }
};
class Solution {
public:
    vector<bool> pathExistenceQueries(int n, vector<int>& nums, int maxDiff, vector<vector<int>>& queries) {
        DisjointSet a(n); 
        vector<bool> answer; sort(nums.begin(),nums.end());
        for(int i=1;i<nums.size();i++){
            if(nums[i]-nums[i-1]<=maxDiff){
                a.Union(i,i-1);
            }
        }
        for(auto& q:queries){
            int x=q[0]; int y=q[1];
            answer.push_back(a.find(x)==a.find(y));
        }
        return answer;
    }
};

判断节点i和节点j之间存在无向边
|nums[i]-nums[j]|<=maxDiff => 满足公式则存在无向边
然后给你个query查询,返回一个bool类型的answer数组

3.判断连接可整除性

给你一个正整数数组 nums 和一个正整数 k

nums 的一个 排列 中的所有数字,按照排列顺序 连接其十进制表示 后形成的数可以 k 整除时,我们称该排列形成了一个 可整除连接

返回能够形成 可整除连接字典序 最小的排列(按整数列表的形式表示)。如果不存在这样的排列,返回一个空列表。

数据范围如下:

  • 1 <= nums.length <= 13
  • 1 <= nums[i] <= 105
  • 1 <= k <= 100
    解题思路:如果是暴力全排列的话是O(n!),题目说的字典序数组,比较的是数组的数字

eg: [3,12,45]和[3,45,12], 前面的字典序更小

为了让字典序最小,我们要从小到大枚举。把 nums 从小到大排序,然后枚举第一个位置填nums[0],nums[1],nums[2]....nums[n-1], 一旦我们找到了答案(拼接的 n 个数模 k 等于 0),就立刻返回 true,不再继续递归搜索, 因为有重复的状态,所以我们要写一个记忆化数组。

递归入口:dfs(0, 0) 是从初始状态(无数字被使用,拼接为0)开始搜索,尝试找到一种数字排列,使得拼接后的数字能被 k 整除。如果找到,返回对应的排列(path);否则返回空列表。

递归出口:m==(1<<n)-1, 这是集合的二进制表示,指的是所有数字都被使用了

cpp 复制代码
class Solution {
public:
    vector<int> concatenatedDivisibility(vector<int>& nums, int k) {
        int n=nums.size();
        sort(nums.begin(),nums.end());
        vector<int> len(n),pow_10_len(n);
        for(int i=0;i<n;i++){
            int x=nums[i];
            int t=x;
            while(t>0){
                len[i]++;
                t/=10;
            }
            int p=1;
            for(int j=0;j<len[i];j++){
                p=p*10;
            }
            pow_10_len[i]=p;
        }
        vector<vector<bool>> memo(1 << n, vector<bool>(k, false));
        vector<int> path;
        auto dfs = [&](this auto&& dfs,int m, int r) -> bool {
            if (m == (1 << n) - 1) {
                return r == 0;
            }
            if (memo[m][r]) return false;
            for (int i = 0; i < n; i++) {
                if (!(m & (1 << i))) {
                    int new_r = (r * pow_10_len[i] + nums[i] ) % k;
                    path.push_back(nums[i]);
                    if (dfs(m | (1 << i), new_r)) {
                        return true;
                    }
                    path.pop_back();
                }
            }
            memo[m][r] = true;
            return false;
        };
        if (dfs(0, 0)) {
            return path;
        }else {
            return {}; 
        }
    }
};

4.针对图的路径存在性查询 II

给你一个整数 n,表示图中的节点数量,这些节点按从 0n - 1 编号。

同时给你一个长度为 n 的整数数组 nums,以及一个整数 maxDiff

如果满足 |nums[i] - nums[j]| <= maxDiff(即 nums[i]nums[j]绝对差 至多为 maxDiff),则节点 i 和节点 j 之间存在一条 无向边

此外,给你一个二维整数数组 queries。对于每个 queries[i] = [ui, vi],找到节点 ui 和节点 vi 之间的 最短距离。如果两节点之间不存在路径,则返回 -1。

返回一个数组 answer,其中 answer[i] 是第 i 个查询的结果。

**注意:**节点之间的边是无权重(unweighted)的。
感觉要用线段树优化,没写出来(还是太菜了)

具体解法可以看这位佬的。

3534. 针对图的路径存在性查询 II - 力扣(LeetCode)

感谢大家的点赞和关注,你们的支持是我创作的动力!

相关推荐
DebugKitty19 分钟前
C语言14-指针4-二维数组传参、指针数组传参、viod*指针
c语言·开发语言·算法·指针传参·void指针·数组指针传参
qystca25 分钟前
MC0241防火墙
算法
jie*43 分钟前
小杰数据结构(one day)——心若安,便是晴天;心若乱,便是阴天。
数据结构
伍哥的传说2 小时前
React & Immer 不可变数据结构的处理
前端·数据结构·react.js·proxy·immutable·immer·redux reducers
行然梦实3 小时前
粒子群优化算法(Particle Swarm Optimization, PSO) 求解二维 Rastrigin 函数最小值问题
算法·机器学习·数学建模
XH华3 小时前
C语言第六章函数递归
c语言·开发语言·算法
斯安3 小时前
LRU(Least Recently Used)原理及算法实现
算法
go54631584653 小时前
基于LSTM和GRU的上海空气质量预测研究
图像处理·人工智能·深度学习·神经网络·算法·gru·lstm
亮亮爱刷题4 小时前
算法提升之数论(矩阵+快速幂)
线性代数·算法·矩阵
亿坊电商4 小时前
AI 数字人在处理音频时,如何确保声音的自然度?
人工智能·算法·音视频