3.27网易实习笔试(前端)
只讲编程题,意向前端,我用的javascript
第1题,一组数据,判断能组成三角形最多的数,如果有多个,都写下来
思路,从小到大排序,三重循环暴力,通过70%案例
let n = parseInt(readline()); let arr = readline().split(' ').map((a) => parseInt(a)).sort((a, b) => a - b); let canComTri = new Array(n).fill(0); for (let i = 0; i < n - 2; i++) { for (let j = i + 1; j < n - 1; j++) { for (let k = j + 1; k < n; k++) { if (arr[k] < arr[i] + arr[j]) { canComTri[i]++; canComTri[j]++; canComTri[k]++; } else { break; } } } } let res = []; let max = Math.max(...canComTri); for (let i = 0; i < n; i++) { if (canComTri[i] === max) res.push(arr[i]); } console.log(res.join(' '))
优化方案更新,两次三重循环,三重循环优化后时间复杂度由O(N^3)降为O(N^2),第3重循环的数k与第2重j相关,因此降低了时间复杂度
let n = parseInt(readline()); let arr = readline() .split(" ") .map((a) => parseInt(a)) .sort((a, b) => a - b); let canComTri = new Array(n).fill(0); for (let i = 0; i < n - 2; i++) { let k = i + 2; for (let j = i + 1; j < n - 1; j++) { for (k = k > j ? k : j + 1; k < n && arr[k] < arr[i] + arr[j]; k++) {} canComTri[i] += k - j - 1; canComTri[j] += k - j - 1; } } for (let i = n - 1; i >= 2; i--) { let k = i - 2; for (let j = i - 1; j >= 1; j--) { for (k = k < j ? k : j - 1; k >= 0 && arr[i] < arr[j] + arr[k]; k--) {} canComTri[i] += k - j - 1; } } let res = []; let max = Math.max(...canComTri); for (let i = 0; i < n; i++) { if (canComTri[i] === max) res.push(arr[i]); } console.log(res.join(" "));第2题,给你一个二叉树,实现固定值和的路径,优先层数低的,排在左边的
思路:BFS,由于输入是数组,进行字符串切割,进行BFS遍历各点的和,和为想要的固定值,倒推路径,通过70%案例
思路:想到DFS暴力,觉得不对,pass了,做问答题时想到了按模6分组,每组排序,回来想写,发现写不了,无语了,问答题也写不了,只能提前交卷
let arr = readline().split('[')[1].split(']')[0].split(',').map((a) => parseInt(a)); const sum = parseInt(readline()); const n = arr.length; let index; let res = [...arr]; for (let i = 1; i < n; i++) { if (isNaN(res[i])) { continue; } else { res[i] += res[((i - 1) >> 1)]; if (res[i] === sum) { index = i; break; } } } if (index) { let path = [arr[index]]; while (index) { index = ((index - 1) >> 1); path.unshift(arr[index]); } console.log('[' + path.join(',') + ']'); } else { console.log([]); }
优化方案
let arr = readline().split('[')[1].split(']')[0].split(',').map((a) => parseInt(a)); const sum = parseInt(readline()); const n = arr.length; let index; let res = [...arr]; let queue = []; if (!isNaN(res[0])) { queue.push(0); } while (queue.length) { const len = queue.length; for (let i = 0; i < len; i++) { let cur = queue.shift(); if (!isNaN(res[cur * 2 + 1])) { queue.push(cur * 2 + 1); res[cur * 2 + 1] += res[cur]; if (res[cur * 2 + 1] === sum) { index = cur * 2 + 1; break; } } if (!isNaN(res[cur * 2 + 2])) { queue.push(cur * 2 + 2); res[cur * 2 + 2] += res[cur]; if (res[cur * 2 + 2] === sum) { index = cur * 2 + 2; break; } } } if (index) break; } if (index) { let path = [arr[index]]; while (index) { index = ((index - 1) >> 1); path.unshift(arr[index]); } console.log('[' + path.join(',') + ']'); } else { console.log([]); }
第3题,一组数据,找出能组成和被6整除的最大值对应的集合
其实应该用动态规划,dp[i][n]表示前i个数模6余n的最大值,先求出最大和再经过反向遍历求出该集合
第4题,编辑距离变种,定义了编辑距离和两组字符串长度的比值,参考 https://leetcode-cn.com/problems/edit-distance/ ,只不过增删距离为1,改距离为2
思路:动态规划,dp[i][j]为字符串前i个字符子串到字符串前j个字符子串的编辑距离,可以压缩空间,笔试就不装逼了,面试被问到的话打算写好后口述优化思路,终于A了1道,感觉自己好菜
let str0Arr = readline().split(''); let str1Arr = readline().split(''); const len0 = str0Arr.length; const len1 = str1Arr.length; const dp = new Array(len0 + 1); dp[0] = new Array(len1 + 1); for (let j = 0; j <= len1; j++) { dp[0][j] = j; } for (let i = 1; i <= len0; i++) { dp[i] = new Array(len1 + 1).fill(Number.MAX_SAFE_INTEGER); dp[i][0] = i; } for (let i = 1; i <= len0; i++) { for (let j = 1; j <= len1; j++) { if (str0Arr[i - 1] === str1Arr[j - 1]) { dp[i][j] = Math.min(dp[i][j], dp[i - 1][j - 1], dp[i - 1][j] + 1, dp[i][j - 1] + 1); } else { dp[i][j] = Math.min(dp[i][j], dp[i - 1][j] + 1, dp[i][j - 1] + 1); } } } let sim = (len0 + len1 - dp[len0][len1]) / (len0 + len1); console.log(sim.toFixed(2));
优化空间,从O(MN)降至O(N)
let str0Arr = readline().split(''); let str1Arr = readline().split(''); const len0 = str0Arr.length; const len1 = str1Arr.length; // const dp = new Array(len0 + 1); // dp[0] = new Array(len1 + 1); const dp = new Array(len1 + 1); for (let j = 0; j <= len1; j++) { // dp[0][j] = j; dp[j] = j; } // for (let i = 1; i <= len0; i++) { // dp[i] = new Array(len1 + 1).fill(Number.MAX_SAFE_INTEGER); // dp[i][0] = i; // } for (let i = 1; i <= len0; i++) { let pre = dp[0]; dp[0] = i; for (let j = 1; j <= len1; j++) { let temp = dp[j]; if (str0Arr[i - 1] === str1Arr[j - 1]) { // dp[i][j] = Math.min(dp[i][j], dp[i - 1][j - 1], dp[i - 1][j] + 1, dp[i][j - 1] + 1); dp[j] = Math.min(pre, dp[j] + 1, dp[j - 1] + 1); } else { // dp[i][j] = Math.min(dp[i][j], dp[i - 1][j] + 1, dp[i][j - 1] + 1); dp[j] = Math.min(dp[j] + 1, dp[j - 1] + 1); } pre = temp; } } let sim = (len0 + len1 - dp[len1]) / (len0 + len1); console.log(sim.toFixed(2));