360前端校招2019笔试编程题

360用的是自己的网站来做笔试而不是牛客网。
一直很不明白为什么笔试都喜欢输入输出而不是子函数的形式哈哈哈,虽然提供了js模拟输入输出的接口,但是由于没办法在自己的编译器上调试,一般出错就很麻烦,只能人眼debug哈哈哈。既然人家这么做了,我们也得适应别人。
对于我而言,很久没写java了,然后只能是用c++或者c来代替js做一些简单的笔试题。

前端对算法其实不是很看重,因为实际业务方面的确是后端偏算法一些嘛,所以题目就是五十道选择题,两道编程题。
大概可以说一下.


第一题
给你一个矩阵,矩阵上元素的数字代表相应位置叠了几个小方块。最后让你求表面积。
解决思路:
投影三个面,正侧上面的面积 * 2即可,每列求出最大值

#include 
using namespace std;
int main() {
  int N, M;
  cin >> N >> M;
  int arr[N][M];
  for(int i = 0; i < N; i++) {
    for(int j = 0; j < M; j++) {
      cin >> arr[i][j];
    }
  }
  // 正面
  int sum = 0;
  int part1 = 0, part2 = 0;
  for(int j = 0; j < M; j++) {
    int max = 0;
    for(int i = 0; i < N; i++) {
      if(arr[i][j] > max) {
        max = arr[i][j];
      } 
    }
    part1 += max;
  }
  // 侧面
  for(int i = 0; i < N; i++) {
    int max = 0;
    for(int j = 0; j < M; j++) {
      if(arr[i][j] > max) {
        max = arr[i][j];
      }
    }
    part2 += max;
  }
  sum = part1 * 2 + part2 * 2 + M * N * 2;
  cout << sum << endl;

}

第二题
给出两个数,m进制的,各位上的数字可以调换顺序,得出相加后最大的值。如果某位需要进位的,模m,但是不进位。
如:
1 2 3 1
2 3 3 0
四进制的,运算应调整为
1 3 3 2
2 0 3 3
结果是 3321

解题思路:当时做题时间比较紧,也来不及多想,选择最无脑的暴力求解。
for循环每一位数去和对应的数相加,贪心算法,优先满足高位的值最大,每次得出一位,就去除两个加数(c++里我选择直接将值设置为-1)。

#include 
using namespace std;
int main() 
{
  int n, m; 
  cin >> n >> m;
  int arr1[n], arr2[n], result[n]; 
  for(int i = 0; i < n; i++) {
    cin >> arr1[i];
  }
  for(int i = 0; i < n; i++) {
    cin >> arr2[i];
  }
  for(int t = 0; t < n; t++) {
    int max = 0;
    int cur_i, cur_j;
    for(int i = 0; i < n; i++) {
      if(arr1[i] == -100) {
        continue;
      } 
      for(int j = 0; j < n; j++) {
        if(arr2[j] == -100) {
          continue;
        }
        int result = (arr1[i] + arr2[j]) % m;
        if(result > max) {
          max = result;
          cur_i = i;
          cur_j = j
        }
      }
    }
    result[t] = max;
    arr1[cur_i] = -1;
    arr2[cur_j] = -1;
  }
  for(int t = 0; t < n; t++) {
    cout << result[t] << ' ';
  }
}

时间复杂度: n 2 + ( n − 1 ) 2 + ( n − 2 ) 2 + . . . + 1 2 = n ( n + 1 ) ( 2 n + 1 ) 6 ≈ n 3 n^2 + (n-1)^2 + (n-2)^2 + ... + 1^2 = \frac{ n(n+1)(2n+1) }{6} \approx n^3 n2+(n1)2+(n2)2+...+12=6n(n+1)(2n+1)n3
说实话,复杂度很差,并不算什么好算法。
主要可优化的部分在于后一次循环重复计算了很多次前一次循环已经算过的值。
所以设想的改进做法是使用缓存或者动态规划。


想到的一种做法是:
假设第一个加数是数组A,第二个加数是数组B。对数组A的每一个元素,都去尝试与数组B中的元素相加,不管会不会重复使用B中的元素。
然后发现如果重复使用了B中的X元素,就看A中哪个元素与B中X元素相加能得到的值最大。锁死X元素,不允许再被选择,其余的用到X的A中的元素必须重新选择B中除X以外的元素。
例如:
3 2 1 0
1 0 0 0
四进制
除了3要0以外,A中的2,1,0都想要B中的1,于是2获得1,A中剩余的1,0必须重新选择。
不过这势必导致一个隐患,如果很多位数的话,重新选择可能又要选到一样的,然后就变成了每次都只能锁死一位,每次就比原来少一位去重选。
感觉时间复杂度似乎没变多少,反倒是 代码要比暴力求解要复杂得多


经过咨询同学,得出的新的解决方法是,统计上下两行各数字有多少个,然后从能得出最大的数开始找。
such as

3 2 1 0
1 1 1 1
0 0 1 3

配出3的有3+0,2+1,1+2,0+3 (m次)
一共要配n位
复杂度为O(n + nm)
比我之前 n 3 n^3 n3 的复杂度好了不少。

你可能感兴趣的:(日常记录)