SPRINT-10

64 阅读1分钟

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.21.4.3。比较的规则是:

  1. 从左到右,逐段比较每个数字。
  2. 如果一个版本号的某一段缺失(例如 1.2 相对于 1.2.0),则认为缺失的部分为 0
  3. 如果某一段的数字较大,则该版本号较大。
  4. 如果所有对应的段都相等,则版本号相等。

下面是一个用 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