首页 秋招复盘8.13:算法
文章
取消

秋招复盘8.13:算法

待复盘完成。

mhy笔试

  1. 题目1. 奥数之术,花里胡哨,6. 很简单,直接计算正着走或者反向走取最小值就行
    • 题目

      1
      2
      3
      4
      5
      6
      7
      
        // 有一个矩阵,范围从(1,1)到(n,m)
        // 每次可以向上下左右四个方向移动一格。
        // 同时,在边界处时,可以从另一边界“穿出”。即在第一行(x,1)向下移动一格,会到第n行的同一列(x,m)。
        // 在第一列(1,y)向左移动一格,会到第n列的同一行(n,y)。
        // 在第n行(x,m)向下移动一格,会到第一行的同一列(x,1)。
        // 在第n列(n,y)向右移动一格,会到第一列的同一行(1,y)。
        // 现在,给定一个起点(x1,y1)和两个终点(x2,y2)(x3, y3),问从起点出发,最少需要多少步才能到达第一个终点和第二个终点。
      
    • 实现

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      
        #include <iostream>
        #include <algorithm>
              
        using namespace std;
              
        // 从一个点到另一个点的最短路径
        int minDist(int n, int m, int x1, int y1, int x2, int y2) {
            int dist;
            // 先走到同一行,可以直接向终点行走,距离为abs(y1 - y2),也可以向另一行走,距离为m - abs(y1 - y2)
            dist = min(abs(y1 - y2), m - abs(y1 - y2));
              
            // 再走到同一列,可以直接向终点列走,距离为abs(x1 - x2),也可以向另一列走,距离为n - abs(x1 - x2)
            dist += min(abs(x1 - x2), n - abs(x1 - x2));
              
            return dist;
        }
              
        int main() {
            int n, m;
            cin >> n >> m;
            int x1, y1, x2, y2, x3, y3;
            cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
              
            cout << minDist(n, m, x1, y1, x2, y2) + minDist(n, m, x2, y2, x3, y3) << endl;
            return 0;
        }
      
  2. 题目2。 给树加节点。又是阅读理解题,感觉题很简单。10%。不知道坑在哪里。就构造树,求原本的距离。找出叶子节点,往上加。层序遍历。Why
    • 题目。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      
        // 给出一颗有根树,树上有n个节点和n-1条边,边的距离为1. 根节点编号为1.
        // 根据上述构建出这棵有根树。
        // 然后,进行任意次操作:
        // 操作内容:对于树的叶子节点添加一个叶子节点,新添加边长度也是1.
        // 问经过操作以后,使得这棵树中所有节点与根节点的距离不超过k的最大值是多少?
        // 输入
        //4 2
        //1 2
        //1 3
        //2 4
        // 输出
        //5
      
    • 实现。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      
        #include <iostream>
        #include <vector>
        #include <queue>
        #include <map>
              
        using namespace std;
              
        // 树的节点
        struct Node {
            [[maybe_unused]] unsigned int id;
            vector<Node *> children;
              
            explicit Node(unsigned int id) : id(id) {}
        };
              
        int maxKDistNum(int k, const vector<vector<int>> &edges) {
            unsigned int n = edges.size() + 1;
            // 使用map映射节点的值和节点的指针
            map<int, Node *> nodes;
            for (const auto &edge: edges) {
                int a = edge[0];
                int b = edge[1];
                // 如果节点不存在,就创建一个节点
                if (nodes.find(a) == nodes.end()) {
                    nodes[a] = new Node(a);
                }
                if (nodes.find(b) == nodes.end()) {
                    nodes[b] = new Node(b);
                }
                // 添加边
                nodes[a]->children.push_back(nodes[b]);
            }
            auto root = nodes[1];
              
            // 从根节点开始,进行广度优先搜索,同时记录每个节点到根节点的距离
            // 获取当前树所有节点(包括叶子节点和非叶子节点)中,与根节点距离不超过k的节点数量
            queue<Node *> q;
            q.push(root);
            // 记录每个节点到根节点的距离
            map<Node *, int> dist;
            dist[root] = 0;
            // 记录当前树所有节点与根节点的距离
            int count = 1; // 根节点
            while (!q.empty()) {
                auto node = q.front();
                q.pop();
              
                // 遍历当前节点的所有子节点
                for (auto child: node->children) {
                    // 如果当前子节点到根节点的距离小于k,就将当前子节点加入队列
                    if (dist[node] < k) {
                        q.push(child);
                        // 将当前子节点加入队列,将count加1
                        count++;
                        dist[child] = dist[node] + 1;
                    }
                }
            }
              
            // 找出当前树的所有叶子节点,然后对每个叶子节点进行操作,操作内容:对于树的叶子节点添加一个叶子节点,新添加边长度也是1.
            // 使用广度优先搜索找出所有当前和根节点距离不超过k的叶子节点,然后对每个叶子节点进行操作
            // 操作内容:对于树的叶子节点添加一个叶子节点,新添加边长度也是1. 如果添加后距离还是不超过k,就将当前叶子节点加入队列
            // 重复上述操作,直到队列为空
              
            // 1. 查找dist map中的叶子节点
            queue<Node *> leafs;
            for (auto &item: dist) {
                if (item.first->children.empty()) {
                    leafs.push(item.first);
                }
            }
            // 2. 循环处理每个叶子节点
            while (!leafs.empty()) {
                auto leaf = leafs.front();
                leafs.pop();
              
                // 判断取出来的叶子节点和根节点的距离,如果大于等于k,就不用再处理了
                if (dist[leaf] >= k) {
                    continue;
                }
              
                // 3. 对当前叶子节点进行操作
                // 3.1 添加一个叶子节点
                auto newLeaf = new Node(++n);
                // 3.2 添加边
                leaf->children.push_back(newLeaf);
                // 3.3 如果添加后距离还是不超过k,就将当前叶子节点加入队列
                if (dist[leaf] + 1 <= k) {
                    leafs.push(newLeaf);
                    // 将当前叶子节点加入队列,将count加1
                    count++;
                    dist[newLeaf] = dist[leaf] + 1;
                }
            }
            return count;
        }
              
        int main() {
            int n, k;
            cin >> n >> k;
            vector<vector<int>> edges;
            for (int i = 0; i < n - 1; ++i) {
                int a, b;
                cin >> a >> b;
                edges.push_back({a, b});
            }
            cout << maxKDistNum(k, edges) << endl;
            return 0;
        }
      
  3. 题目3. 不玩原神就寄!

    憨批题目。这不是题目描述就又问题吗?

    img

    当然了,就按照正常理解就行。还是自己不会做。像是什么马尔科夫链。数学题?How?

  4. 括号表示转二叉树
  5. IF中断
  6. 友元函数
  7. 无效指令导致进程终止。

大疆笔试

  1. 编程题。自己菜的扣脚。
    1. 题目1. 给定两个数组,用第二个数组中的数替换掉第一个数组的数,使得第一个数组严格递增,求最小替换次数。直接决策树暴力递归,过的很少。
      • 题目。

        1
        2
        
          // 给定两个数组,用第二个数组中的数替换掉第一个数组的数,使得第一个数组严格递增,求最小替换次数。
          // 例如:[81,85,83,86,87],[81,83,82,84],最小替换次数为1,将85替换为82即可。
        
      • 实现

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        60
        61
        62
        63
        64
        65
        66
        67
        68
        69
        70
        71
        72
        73
        74
        75
        76
        77
        78
        79
        80
        81
        82
        83
        84
        85
        86
        87
        88
        89
        90
        91
        92
        93
        94
        
          void dfs(vector<uint8_t> &score1, vector<uint8_t> &score2, int index,
                   int pre, int pre2, int count, vector<uint8_t> &res)
          {
              if (index == score1.size())
              {
                  // 记录下所有成功的替换次数
                  res.push_back(count);
                  return;
              }
              // 如果当前这个数比上一个数大,则不需要替换,继续遍历下一个数
              if (score1[index] > pre)
              {
                  return dfs(score1, score2, index + 1, score1[index], pre, count, res);
              }
              else
              {
                  // 如果当前这个数比上一个数小或等于,则需要替换
                  // 1. 可以选择在score2中找一个比当前这个数小,比前面第二个数大的数来替换掉前一个数
                  // 2. 可以选择在score2中找一个比上一个数大的数来替换掉当前这个数。
                  // 产生两种分支
                  // 使用递归和回溯的方式遍历这个决策树
                    
                  // 1. 可以选择在score2中找一个比当前这个数小,比前面第二个数大的数来替换掉前一个数
                  // 从score2中找到第一个比当前这个数小,比前面第二个数大的数
                  int i = 0;
                  while (i < score2.size())
                  {
                      if (score2[i] > pre2 && score2[i] < score1[index])
                      {
                          break;
                      }
                      i++;
                  }
                  // 如果找到了这样的数,则替换掉前一个数,继续遍历下一个数
                  if (i < score2.size())
                  {
                      dfs(score1, score2, index + 1, score2[i], pre, count + 1, res);
                  }
                    
                  // 2. 可以选择在score2中找一个比上一个数大的数来替换掉当前这个数。
                  // 从score2中找到第一个比上一个数大的数
                  i = 0;
                  while (i < score2.size())
                  {
                      if (score2[i] > pre)
                      {
                          break;
                      }
                      i++;
                  }
                  // 如果找到了这样的数,则替换掉当前这个数,继续遍历下一个数
                  if (i < score2.size())
                  {
                      dfs(score1, score2, index + 1, score1[index], pre, count + 1, res);
                  }
              }
          };
          // 给定两个数组,用第二个数组中的数替换掉第一个数组的数,使得第一个数组严格递增,求最小替换次数。
          // 例如:[81,85,83,86,87],[81,83,82,84],最小替换次数为1,将85替换为82即可。
          int minReplace(vector<uint8_t> &score1, vector<uint8_t> &score2)
          {
              if (score1.size() <= 1)
                  return 0;
                    
              int count = 0;
                    
              // 对score2排序
              sort(score2.begin(), score2.end());
                    
              // 遍历score1的过程中
              // 如果score1这个数比上一个数小于或等于,则
              // 1. 可以选择在score2中找一个比当前这个数小,比前面第二个数大的数来替换掉前一个数
              // 2. 可以选择在score2中找一个比上一个数大的数来替换掉当前这个数。
              // 产生两种分支
              // 使用递归和回溯的方式遍历这个决策树
              vector<uint8_t> res;
              dfs(score1, score2, 1, score1[0], 0, 0, res);
                    
              // 找到所有成功的替换次数中的最小值
              if (res.size() > 0)
              {
                  count = res[0];
                  for (int i = 1; i < res.size(); i++)
                  {
                      count = min(count, (int)res[i]);
                  }
              }
              else
              {
                  count = -1;
              }
                    
              return count;
          }
        
    2. 题目2. 做一个文件树系统,对这个树进行模糊搜索。可以做的,赶着去做米哈游了,人麻了。
      • 题目

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        
          // 4 (搜索字符串)
          // 11
          // root/
          // -folder1/
          // --file1.txt
          // --file2.txt
          // -folder2/
          // --file3.txt
          // --file4.txt
          // -folder3/
          // --file5.txt
          // -folder4/
          // --file6.txt
          // 样例输出
          // /root/folder2/file4.txt
          // /root/folder4/
        
  2. 重入
  3. 静态全局变量对单个源文件访问的影响
  4. 排序算法的稳定性

宽德笔试

本文由作者按照 CC BY 4.0 进行授权

2023年8月11日分享:建政

2023年8月28日分享:内容创作、女人