leetcode/nowcoder-huawei-9-其他

9.其他

HJ108. 求最小公倍数

  1. 描述

    正整数A和正整数B 的最小公倍数是指 能被A和B整除的最小的正整数值,设计一个算法,求输入A和B的最小公倍数。
    
    数据范围:1≤a,b≤100000 
    输入描述:输入两个正整数A和B。
    输出描述:输出A和B的最小公倍数。
    示例1
    输入:
    	5 7
    输出:
    	35
    示例2
    输入:
    	2 4
    输出:
    	4
    
  2. 思路

    先获取两个数的最大公因数p,最小公倍数是m*n/p

  3. 代码

    #include <iostream>
    using namespace std;
    
    int getMaxFactor(int m, int n) {
        int res = min(m,n);
        while (res > 1) {
            if(m % res == 0 && n % res == 0)    break;
            res--;
        }
        return res;    
    }
    
    int getMinMultiple(int m, int n) {
        int k = getMaxFactor(m, n);
        return m*n/k;
    }
    
    int main() {
        int m;
        int n;
        cin >> m >> n;
        cout << getMinMultiple(m, n);
        return 0;
    }
    

HJ28.素数伴侣

  1. 描述

    若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如2和5、6和13,它们能应用于通信加密。现在密码学会请你设计一个程序,从已有的 N ( N 为偶数)个正整数中挑选出若干对组成“素数伴侣”,挑选方案多种多样,例如有4个正整数:2,5,6,13,如果将5和6分为一组中只能得到一组“素数伴侣”,而将2和5、6和13编组将得到两组“素数伴侣”,能组成“素数伴侣”最多的方案称为“最佳方案”,当然密码学会希望你寻找出“最佳方案”。
    输入:
    有一个正偶数 n ,表示待挑选的自然数的个数。后面给出 n 个具体的数字。
    输出:
    输出一个整数 K ,表示你求得的“最佳方案”组成“素数伴侣”的对数。
    
    数据范围:1≤n≤100,输入的数据大小满足 2≤val≤30000 
    输入描述:输入说明:1 输入一个正偶数 n;2 输入 n 个整数
    输出描述:求得的“最佳方案”组成“素数伴侣”的对数。
    示例1
    输入:
    	4
    	2 5 6 13
    输出:
    	2
    示例2
    输入:
    	2
    	3 6
    输出:
    	0
    
  2. 思路

    • 概念

      • 二分图

        • 顶点分为两个不想交的集合(U,V)

        • 集合内的点两两不相连

        • 二分图匹配

          • 匹配:如果选择一条边就会连通对应的两个点,就会构成一个匹配。规定一个顶点最多只能构成一个匹配
          • 最大匹配:对于一张二分图,构成匹配数量最多的情况叫最大匹配
          • 完美匹配:所有定点都有了匹配
      • 增广路径:二分图的匹配中,有一条路径的首尾是非匹配点,路径中其他点均是匹配点,这条路径就是一条增广路径。(即一条首尾相连的路径)

      • 匈牙利算法

        • 寻找增广路径,从而达成最大匹配。
        • 本质是一个调整匹配的过程,通过递归调用的形式尝试调整已经占据了发生冲突位置的匹配,腾出位置来给右边的节点
    • 变量:

      • vector ev、vector od:记录所有奇数/偶数
      • vector evVis、vector odVis:记录所有该顶点匹配的对应顶点
      • vector visited:当前轮次(对应不同的i),是否已遍历当前顶点
      • vector<vector> allPair:记录所有的匹配
    • 思路

      • 针对每个左侧图的i,将所有的visited清零,深度搜索找到能匹配的点,并返回1
      • 读取每个右侧图的j,如果该右侧顶点没有遍历切存在匹配i-j,进入匹配
      • 进入匹配先将visited状态修改
      • 进行匹配
        • 右侧点未匹配,则直接修改匹配
        • 右侧点已经匹配,重新将其原来对应的左侧点送入递归重新调整匹配
      • 确认匹配后记录左右点对应的匹配点

    参考:https://www.cnblogs.com/techflow/p/13522712.html

    https://zhuanlan.zhihu.com/p/534989336

    • 代码
    #include <iostream>
    using namespace std;
    #include <vector>
    
    class Solution
    {
    private:
        vector<vector<bool>> allPair;
        vector<int> evVis;
        vector<int> odVis;
        vector<int> visited;
    public:
        Solution(vector<int> ev, vector<int> od) {
            int m = ev.size();
            int n = od.size();
            allPair.resize(m, vector<bool> (n, false));
            for(int i = 0; i < m; i++) {
                for(int j = 0; j < n; j++) {
                    if(isPrime(ev[i] + od[j]))  allPair[i][j] = true;
                }
            }
            evVis.resize(m, -1);
            odVis.resize(n, -1);
        } 
    
        bool isPrime(int num) {
            for(int i = 2; i < num/2; i++)
                if(num % i == 0)    return false;
            return true;
        }
    
        int dfs(int i) {
            for(int j = 0; j < odVis.size(); j++) {
                if(!visited[j] && allPair[i][j]) {
                    visited[j] = true;
                    if(odVis[j] == -1 || dfs(odVis[j])) {
                        evVis[i] = j;
                        odVis[j] = i;
                        return 1;
                    }
                }
            }
            return 0;
        }
    
        int getCouple() {
            int res = 0;
            for(int i = 0; i < evVis.size(); i++) {
                visited.assign(odVis.size(),0);
                res += dfs(i);
            }
            return res;
        }
    };
    
    int main() {
        int n;
        cin >> n;
        vector<int> nums(n);
        vector<int> ev,od;
        int num;
        for(int i = 0; i < n; i++) {
            cin >> num;
            if(num % 2 == 0)
                od.push_back(num);
            else
                ev.push_back(num);
        }
        Solution sol(ev, od);
        cout << sol.getCouple() << endl;
        return 0;
    }
    

HJ60. 查找组成一个偶数最接近的两个素数

  1. 描述

    任意一个偶数(大于2)都可以由2个素数组成,组成偶数的2个素数有很多种情况,本题目要求输出组成指定偶数的两个素数差值最小的素数对。
    
    数据范围:输入的数据满足4≤n≤1000 
    输入描述:输入一个大于2的偶数
    输出描述:从小到大输出两个素数
    示例1
    输入:
    	20
    输出:
        7
        13
    示例2
    输入:
    	4
    输出:
        2
        2
    
  2. 思路

    从一半开始从大到小遍历,判断是否为素数

  3. 代码

    #include <iostream>
    using namespace std;
    
    bool isPrime(int n) {
        for(int i = 2; i < n/2; i++)
            if(n%i == 0)    return false;
        return true;
    }
    
    void getPrimeCouple(int n) {
        int a = n/2;
        int b;
        while(a) {
            b = n - a;
            if(!isPrime(a)){
                a--;
                continue;
            }
            if(isPrime(b))  break;
            a--;
        }
        cout << a << endl;
        cout << b << endl;
    }
    
    int main() {
        int n;
        cin >> n;
        getPrimeCouple(n);
        return 0;
    }
    

leetcode 994. 腐烂的橘子

  1. 描述

    在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一:
    值 0 代表空单元格;
    值 1 代表新鲜橘子;
    值 2 代表腐烂的橘子。
    每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。
    返回 直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能,返回 -1
    
    示例 1:
    输入:grid = [[2,1,1],[1,1,0],[0,1,1]]
    输出:4
    示例 2:
    输入:grid = [[2,1,1],[0,1,1],[1,0,1]]
    输出:-1
    解释:左下角的橘子(第 2 行, 第 0 列)永远不会腐烂,因为腐烂只会发生在 4 个正向上。
    示例 3:
    输入:grid = [[0,2]]
    输出:0
    解释:因为 0 分钟时已经没有新鲜橘子了,所以答案就是 0 。
    
    提示:
    m == grid.length
    n == grid[i].length
    1 <= m, n <= 10
    grid[i][j] 仅为 0、1 或 2
    
  2. 思路

    使用bfs算法,先遍历烂橘子的周围,step++,直到遍历完为止

  3. 代码

    #include <iostream>
    using namespace std;
    #include <vector>
    #include <queue>
    
    class Solution {
        int dirs[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
    public:
        int orangesRotting(vector<vector<int>>& grid) {
            int step = -1;
            queue<pair<int,int>>  que;
            bool isOnlyZero = true;
            for (auto ls:grid)
                for (auto x:ls)
                    if (x) isOnlyZero = false;
            if(isOnlyZero)  return 0;
            for (int i = 0; i < grid.size(); i++)
                for (int j = 0; j < grid[i].size(); j++)
                    if (grid[i][j] == 2) que.emplace(i,j);
            while (!que.empty()) {
                int size = que.size();
                step++;
                while(size--) {
                    auto [x, y] = que.front();
                    que.pop();
                    for(int i = 0; i < 4; i++) {
                        int nx = x + dirs[i][0];
                        int ny = y + dirs[i][1];
                        if (nx >= 0 && nx < grid.size() && ny >= 0 && ny < grid[nx].size() && grid[nx][ny] == 1) {
                            que.emplace(nx, ny);
                            grid[nx][ny] = 2;
                        }
                    }
                }
            }
            for (auto ls:grid)
                for (auto x:ls)
                    if (1 == x)
                        return -1;
            return step;
        }
    };
    
    int main() {
        vector<vector<int>> grid;
        grid.push_back({2,1,1});
        grid.push_back({0,1,1});
        grid.push_back({1,0,1});
        Solution sol;
        cout << sol.orangesRotting(grid) << endl;
        return 0;
    }
    

leetcode 204. 计算质数

  1. 描述

    给定整数 n ,返回 所有小于非负整数 n 的质数的数量 。 
    
    示例 1:
    输入:n = 10
    输出:4
    解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。
    示例 2:
    输入:n = 0
    输出:0
    示例 3:
    输入:n = 1
    输出:0 
    
    提示:
    0 <= n <= 5 * 106
    
  2. 思路

    • 暴力解答,直接枚举
    • 空间换时间,列举所有数字初始化为质数,将所有数的倍数设置为合数
  3. 代码

    #include <iostream>
    using namespace std;
    #include <vector>
    
    // class Solution {
    // public:
    //     int countPrimes(int n) {
    //         int res = 0;
    //         bool isPrimes = true;
    //         for (int i = 2; i < n; i++) {
    //             isPrimes = true;
    //             for (int j = 2; j * j <= i; j++) {
    //                 if(i % j == 0)  isPrimes = false;
    //             }
    //             if (isPrimes){
    //                 res++;
    //                 printf("%d\n",i);
    //             }
    //         }
    //         return res;
    //     }
    // };
    
    class Solution {
    public:
        int countPrimes(int n) {
            int res = 0;
            vector<bool> isPrimes(n,true);
            for (int i = 2; i * i < n; i++) {
                if (isPrimes[i])
                    for (int j = i * i; j < n; j += i)
                        isPrimes[j] = false;
            }
            for (int i = 2; i < n; i++)
                if (isPrimes[i]) res++;
            return res;
        }
    };
    
    
    int main() {
        int n = 20;
        Solution sol;
        cout << sol.countPrimes(n) << endl;
        return 0;
    }
    

HJ25. 数据分类处理

  1. 描述

    信息社会,有海量的数据需要分析处理,比如公安局分析身份证号码、 QQ 用户、手机号码、银行帐号等信息及活动记录。
    采集输入大数据和分类规则,通过大数据分类处理程序,将大数据分类输出。
    
    数据范围:1≤I,R≤100  ,输入的整数大小满足 0≤val≤2^31−1 
    输入描述:一组输入整数序列I和一组规则整数序列R,I和R序列的第一个整数为序列的个数(个数不包含第一个整数);整数范围为0~(2^31)-1,序列个数不限
    输出描述:从R依次中取出R<i>,对I进行处理,找到满足条件的I: 
    I整数对应的数字需要连续包含R<i>对应的数字。比如R<i>为23,I为231,那么I包含了R<i>,条件满足 。 
    按R<i>从小到大的顺序:
    (1)先输出R<i>; 
    (2)再输出满足条件的I的个数; 
    (3)然后输出满足条件的I在I序列中的位置索引(从0开始); 
    (4)最后再输出I。 
    附加条件: 
    (1)R<i>需要从小到大排序。相同的R<i>只需要输出索引小的以及满足条件的I,索引大的需要过滤掉 
    (2)如果没有满足条件的I,对应的R<i>不用输出 
    (3)最后需要在输出序列的第一个整数位置记录后续整数序列的个数(不包含“个数”本身)
     
    序列I:15,123,456,786,453,46,7,5,3,665,453456,745,456,786,453,123(第一个15表明后续有15个整数) 
    序列R:5,6,3,6,3,0(第一个5表明后续有5个整数) 
    输出:30, 3,6,0,123,3,453,7,3,9,453456,13,453,14,123,6,7,1,456,2,786,4,46,8,665,9,453456,11,456,12,786
    说明:
    30----后续有30个整数
    3----从小到大排序,第一个R<i>为0,但没有满足条件的I,不输出0,而下一个R<i>是3
    6--- 存在6个包含3的I 
    0--- 123所在的原序号为0 
    123--- 123包含3,满足条件 
    示例1
    输入:
        15 123 456 786 453 46 7 5 3 665 453456 745 456 786 453 123
        5 6 3 6 3 0
    输出:
        30 3 6 0 123 3 453 7 3 9 453456 13 453 14 123 6 7 1 456 2 786 4 46 8 665 9 453456 11 456 12 786
    说明:
        将序列R:5,6,3,6,3,0(第一个5表明后续有5个整数)排序去重后,可得0,3,6。
        序列I没有包含0的元素。
        序列I中包含3的元素有:I[0]的值为123、I[3]的值为453、I[7]的值为3、I[9]的值为453456、I[13]的值为453、I[14]的值为123。
        序列I中包含6的元素有:I[1]的值为456、I[2]的值为786、I[4]的值为46、I[8]的值为665、I[9]的值为453456、I[11]的值为456、I[12]的值为786。
        最后按题目要求的格式进行输出即可。     
    
  2. 思路

    • 将R排序并删除重复项
    • 将每个R和J的元素对比,是否符合条件
      • 都转换为string
      • I中的元素与R元素第一个匹配,则将子串与R元素对比
    • 将符合条件的元素和索引压入res
  3. 代码

    #include <iostream>
    using namespace std;
    #include <vector>
    #include <algorithm>
    
    vector<int> sortAndDel(vector<int> nums) {
        sort(nums.begin(), nums.end());
        if(nums.size() <= 1)    return nums;
        int pre = nums[0];
        vector<int> res;
        res.push_back(pre);
        for(int i = 1; i < nums.size(); i++) {
            if(nums[i] != pre) {
                pre = nums[i];
                res.push_back(pre);
            }
        }
        return res;
    }
    
    bool isRight(int x, int y) {
        string a = to_string(x);
        string b = to_string(y);
        for(int i = 0; i < a.size(); i++)
            if(a[i] == b[0] && !a.substr(i,b.size()).compare(b))
                return true;
        return false;
    }
    
    //取出R[i],对I进行处理,找到满足条件的I
    //条件:I证书对应的数字需要连续包含R[i],对I进行处理
    vector<vector<pair<int,int>>> getRes(vector<int> I, vector<int> R) {
        //R[i]从小到大的顺序
        R = sortAndDel(R);
        vector<vector<pair<int,int>>> res(R.size(), vector<pair<int,int>>());
        for(int i = 0; i < R.size(); i++) {
            for(int j = 0; j < I.size(); j++) {
                if(isRight(I[j],R[i])) res[i].push_back({j, I[j]});
            }
        }
        int num = 0;
        for(int i = 0; i < res.size(); i++) {
            if(res[i].size())  num = num + 2 + 2 * res[i].size();
        }
        printf("%d ",num);
        for(int i = 0; i < res.size(); i++) {
            if(!res[i].size())  continue;
            //先输出R[i] 输出满足条件的I的个数
            printf("%d %d ", R[i], res[i].size());
            for(int j = 0; j < res[i].size(); j++) {
                //输出满足条件的I在I序列中的位置索引 输出I
                printf("%d %d ",res[i][j].first,res[i][j].second);
            }
        }
        printf("\n");
        return res;
    }
    
    int main() {
        int m;
        cin >> m;
        vector<int> I(m);
        for(int i = 0; i < m; i++)
            cin >> I[i];
        int n;
        cin >> n;
        vector<int> R(n);
        for(int i = 0; i < n; i++)
            cin >> R[i];
        getRes(I,R);
        return 0;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值