416、栈
栈是一个后进先出的数据结构。JavaScript中没有栈,但是可以用Array实现栈的所有功能。
// 数组实现栈数据结构
const stack = []
// 入栈
stack.push(0)
stack.push(1)
stack.push(2)
// 出栈
const popVal = stack.pop() // popVal 为 2
417、队列
队列是一个先进先出的数据结构。JavaScript中没有队列,但是可以用Array实现队列的所有功能。
// 数组实现队列数据结构
const queue = []
// 入队
stack.push(0)
stack.push(1)
stack.push(2)
// 出队
const shiftVal = stack.shift() // shiftVal 为 0
418、链表反转
该题目来自LeetCode,题目需要将一个单向链表反转。思路很简单,使用三个变量分别表示当前节点和当前节点的前后节点,虽然这题很简单,但是却是一道面试常考题
以下是实现该算法的代码
var reverseList = function(head) {
// 判断下变量边界问题
if (!head || !head.next) return head
// 初始设置为空,因为第一个节点反转后就是尾部,尾部节点指向 null
let pre = null
let current = head
let next
// 判断当前节点是否为空
// 不为空就先获取当前节点的下一节点
// 然后把当前节点的 next 设为上一个节点
// 然后把 current 设为下一个节点,pre 设为当前节点
while(current) {
next = current.next
current.next = pre
pre = current
current = next
}
return pre
};
419、Js中的大数相加
/**
* 大数加法
* 以字符串的形式读入两个数字s和t,编写一个函数计算它们的和,以字符串形式返回。
* s和t的长度 小于等于 100000,字符串仅有 0-9 构成
* 要求:时间复杂度
*/
//方案1
function solve(s, t) {
// write code here
return (BigInt(s) + BigInt(t)).toString() // 用 BigInt 直接转下就好了
}
console.log(solve(99999, 999990))
//方案二
function solveTwo(s, t) {
let carry = 0, res = '';
let sArr = s.split(''), tArr = t.split('');
while (sArr.length || tArr.length) {
let num = Number(sArr.pop() || 0) + Number(tArr.pop() || 0) + carry;
if (num > 9) {
carry = 1;
num = num % 10
} else {
carry = 0;
}
res = num + res;
}
if (carry) {
res = carry + res;
}
return res;
}
console.log(solveTwo("99999", "999990"))
//方案三
function solveThree( s , t ) {
// write code here
// 首先取出大数中长度最长的
let maxLength = Math.max(s.length,t.length);
// 用0 补齐长度
s = s.padStart(maxLength,0);
t = t.padStart(maxLength,0);
// 定义加法过程中需要用到的变量
let a = 0;
let b = 0; //进位
let sum = "";
for( let i = maxLength - 1; i >=0; i--){
a = parseInt(s[i]) + parseInt(t[i]) + b;
b = Math.floor(a/10);
sum = a%10 + sum;
}
if( b == 1){
sum = "1" + sum;
}
return sum;
}
console.log(solveThree("99999", "999990"))
420、最长递增子序列
最长递增子序列意思是在一组数字中,找出最长一串递增的数字,比如
0, 3, 4, 17, 2, 8, 6, 10
对于以上这串数字来说,最长递增子序列就是 0, 3, 4, 8, 10,可以通过以下表格更清晰的理解
数字
0
3
4
17
2
8
6
10
长度
1
2
3
4
2
4
4
5
通过以上表格可以很清晰的发现一个规律,找出刚好比当前数字小的数,并且在小的数组成的长度基础上加一。
这个问题的动态思路解法很简单,直接上代码
function lis(n) {
if (n.length === 0) return 0
// 创建一个和参数相同大小的数组,并填充值为 1
let array = new Array(n.length).fill(1)
// 从索引 1 开始遍历,因为数组已经所有都填充为 1 了
for (let i = 1; i < n.length; i++) {
// 从索引 0 遍历到 i
// 判断索引 i 上的值是否大于之前的值
for (let j = 0; j < i; j++) {
if (n[i] > n[j]) {
array[i] = Math.max(array[i], 1 + array[j])
}
}
}
let res = 1
for (let i = 0; i < array.length; i++) {
res = Math.max(res, array[i])
}
return res
}
421、实现找到最大字符并输出其个数
const array1 =[1,3,5,6,8,8,8];
function foo(arr) {
const maximum = Math.max(...arr);
const maximumArr = arr.filter(function(item,index) {
return item === maximum;
});
return { maximum, "length":maximumArr.length }
}
422、Js中如何展开多维数组
arr.flat() 方法可以展开多维数组,但当面试官要求使用其他方法实现,你有什么想法吗?
toString
let arr = [1, 2, 4, 6,[5, 4, 5,[98, 3], [34], [7]]];
arr.toString().split(',').map(Number);
es6 的扩展运算符
let arr = [1, 2, 4, 6,[5, 4, 5,[98, 3], [34], [7]]];
function flatten(arr){
while(arr.some(item=>Array.isArray(item))){
arr = [].concat(...arr);
}
return arr;
}
var sunArr = [1,2,3,[4,[5,[6]]]];
flatten(sunArr);
使用递归来处理
let arr = [1, 2, 4, 6,[5, 4, 5,[98, 3], [34], [7]]];
function f(arr=[],newArr=[]) {
arr.forEach((item) => {
if (!Array.isArray(item)) {
newArr.push(item);
} else {
f(item, newArr);
}
});
return newArr;
}
f(arr);
423、使用Js求解连续子数组的最大和
当使用 JavaScript 求解连续子数组的最大和问题时,可以按照以下步骤进行编码:
function maxSubArray(nums) {
let maxSum = nums[0]; // 初始化最大和为第一个元素
let curSum = nums[0]; // 初始化当前子数组和为第一个元素
const len = nums.length;
for (let i = 1; i < len; i++) {
// 判断当前元素加入子数组后的和是否大于当前元素本身
curSum = Math.max(nums[i], curSum + nums[i]);
// 比较当前子数组和与最大和,将较大值赋给最大和
maxSum = Math.max(maxSum, curSum);
}
return maxSum;
}
// 示例使用
const nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4];
const result = maxSubArray(nums);
console.log(result);
在上述代码中,maxSubArray 函数接收一个数组 nums,并返回该数组中连续子数组的最大和。
函数使用动态规划的思想,通过遍历数组的每个元素,不断更新当前子数组和和最大和。
首先,将最大和和当前子数组和初始化为数组的第一个元素。
然后,从数组的第二个元素开始遍历,对于每个元素,判断当前元素加入子数组后的和是否大于当前元素本身,如果是,则将当前元素加入子数组,更新当前子数组和;如果不是,则将当前元素作为起始元素重新计算子数组和,更新当前子数组和。
每次更新当前子数组和后,都和最大和进行比较,将较大值赋给最大和。
最终,返回最大和即可。
示例代码中给出了一个示例输入 [-2, 1, -3, 4, -1, 2, 1, -5, 4],运行结果将打印连续子数组的最大和。
424、版本号比较(1.2 & 1.4.3)
在比较两个版本号时,通常需要逐段比较每个版本号的各个部分。版本号通常由数字和点组成,例如 1.2 和 1.4.3。比较的规则是:
- 从左到右,逐段比较每个数字。
- 如果一个版本号的某一段缺失(例如
1.2相对于1.2.0),则认为缺失的部分为0。 - 如果某一段的数字较大,则该版本号较大。
- 如果所有对应的段都相等,则版本号相等。
下面是一个用 JavaScript 实现的版本号比较的函数:
function compareVersion(version1, version2) {
// 将版本号字符串分割成数组
const v1 = version1.split('.').map(Number);
const v2 = version2.split('.').map(Number);
// 比较每个段
for (let i = 0; i < Math.max(v1.length, v2.length); i++) {
// 如果当前段不存在,则认为是0
const num1 = i < v1.length ? v1[i] : 0;
const num2 = i < v2.length ? v2[i] : 0;
// 如果两个数字不相等,则返回比较结果
if (num1 > num2) {
return 1;
} else if (num1 < num2) {
return -1;
}
}
// 如果所有段都相等,则返回0
return 0;
}
// 测试
console.log(compareVersion('1.2', '1.4.3')); // 应该输出 -1
这个函数首先将两个版本号字符串分割成数组,并转换为数字。然后,它逐个比较每个数组中的数字。如果在某个位置发现两个数字不相等,它将返回相应的比较结果(1 表示第一个版本号较大,-1 表示第二个版本号较大)。如果所有比较的数字都相等,则返回 0 表示两个版本号相等。在上面的测试用例中,'1.2' 应该比 '1.4.3' 版本低,所以输出 -1。