字节豆油瓶笔试题C/C++

这篇博客介绍了如何通过图法和集合法解决抖音用户‘豆油瓶’群体的识别问题。首先,利用BFS/DFS遍历用户互动矩阵来找出‘豆油’关系,然后通过集合操作降低空间复杂度,实现高效解决方案。两种方法分别针对不同规模的数据,展示了在信息技术领域中处理社交网络数据的方法。
摘要由CSDN通过智能技术生成

字节豆油瓶笔试题

题目

题目描述:
抖音上每天都有几亿用户,如果用户 A 和 B 互动不少于 3 次,我们就认为 A 和 B 属于“豆油”,如果 A 和 B 是“豆油”,B 和 C 也是“豆油”, 那么 A 和 C 也互为“豆油”,我们定义“豆油瓶”就是由直系和间接朋友所组成的群体。

给定个 N×N 的矩阵 M,代表抖音上所有用户的互动次数,如果M[i][j]= 5,那么第i个和第j个用户就互动过5次,为 0 的话代表没有互动,对于i = j,即同个用户, 互动次数我们计为0。请你计算并输出发现的抖音上所有“豆油瓶”的个数。

输入描述:
输入第1行:二维数组的行数(列数一样)N
接下来的N行每行N个数字,空格分割

输出描述:
输出发现的“豆油瓶”数量 k

示例1:
输入

3
0 4 0
4 0 0
0 0 0

输出

2

解释:第1个和第2个用户互动超过3次,互为豆油第3个学生和其他人没有互动,自成个豆油瓶

示例2:
输入

3
0 4 0
4 0 6
0 6 0

输出

1

解释:三个用户都在同一个豆油瓶里

题解

方法1:图法

比较容易想到使用BFS/DFS遍历每个有关联的用户,这里给出了一个小规模数据适用的算法

#include <bits/stdc++.h>

using namespace std::chrono;

int n;
int count = 0;

inline bool match(int ** G,const int& a,const int& b)
{
    return G[a][b]>=3;
}


void BFS(int **G,int a,int b)
{
    int start = a;
    std::queue<int> Q;

    Q.push(start);

    if(match(G,a,b))
        count++;

    G[a][b] = 0; //set visit

    while(!Q.empty()) //取能到达的节点
    {
        auto _node = Q.front();//取队头节点
        Q.pop();

        //查找该节点能到达的节点
        for(int i=0;i<n;i++)
        {
            if(match(G,_node,i))
            {
                Q.push(i);
                G[_node][i] = 0; //set neighbour visit
            }
        }
    }

}
void DFS_CLS(int **G,const int a,const int b)
{
    if(!match(G,a,b))
        return;

    G[a][b] = 0; //清除自身

    for(int j=0;j<n;j++) //清除邻居
    {
        if(match(G,a,j)) //对于a的邻居{S},如果s符合条件,则处理s和其邻居
        {
            DFS_CLS(G,j,a);
        }
    }
}
void DFS(int **G,const int& a,const int& b)
{
    if(!match(G,a,b)) //未找到
        return;

    //处理目标
    count++;

    DFS_CLS(G,a,b);
}


int main()
{
    std::cin >> n;
    int **matrix = new int* [n];

    for(int i=0;i<n;i++) //处于数据量考虑,这里不直接在栈空间申请内存。但是使用邻接矩阵表示图在大约n>sqrt(32768*1024/4)时会超过内存限制
    {
        matrix[i] = new int[n];

        for(int j=0;j<n;j++)
        {
            std::cin >> matrix[i][j];

            if(i == j)
                matrix[i][j] = 3; //自己和自己至少是一个豆油瓶
        }
    }

    for(int i=0;i<n;i++)
        BFS(matrix,i,i);

    for(int i=0;i<n;i++)
    {
        delete[] matrix[i];
    }
    delete[] matrix;

    std::cout<<count;
    return 0;
}


方法2:集合法

上一种方法的空间复杂度是O(N^2),非常低效,哪怕改用邻接表也可能不够内存

使用集合法能将空间复杂度降到O(N),由于哈希集合插入和查找的时间为O(1),所以时间复杂度也是O(N)

#include <iostream>
#include <cstring>
#include <unordered_set>

using namespace std;

int n;
int count = 0;
int main()
{
    cin >> n;
    int tmp;
   
    unordered_set<int> group; //unordered_set底层实现是哈希表,相当于java的Hash_Set
    for(int i=0;i<n;i++) 
    {
        for(int j=0;j<n;j++)
        {
            cin >> tmp;
            if(tmp>=3) //某用户与其他用户互动>=3
            {
                 //集合中没有人和这两用户有互动,说明是新的豆油瓶
                if(group.find(i) == group.end() && group.find(j) == group.end())
                {
                    count++;
                }
                //set自带去重
                group.insert(i);
                group.insert(j);
            }

        }
    }
    count += (n-group.size()); //加上没有和任何人互动过的孤立豆油
    cout<<count;
    return 0;
}

这种方法感觉比较取巧,并不是很容易想到

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值