以下为ChatGPT自动生成的解答,正确与否请自行判断。

BFE.devAI解答 - JavaScript 代码题
77. 实现 BigInt 的减法(含符号)

思路:

实现大整数减法的操作和大整数加法操作类似,都是从个位数开始进行操作,将当前位上的数字相减得到当前位的差,若前一位需要借位,则从前一位减去1。同时还需要考虑两个数的正负号以及结果的正负号,思路如下:

  1. 分别判断两个数的正负性,并将其转化为同号相加的形式,即确保第一个数为正数,第二个数为负数。

  2. 判断两个数的绝对值大小,确保第一个数大于等于第二个数。

  3. 从个位数开始,分别计算当前位上的数字差(后一个数为负数,实际操作为加法),并更新结果数组与是否需要借位的标志。

  4. 最后根据是否需要借位以及结果的正负号得到最终的结果。

代码实现如下:

function substract(a, b) {
  const arr1 = a.split('');
  const arr2 = b.split('');
  let sign1 = 1, sign2 = 1;
  let len1 = 0, len2 = 0;
  let i = 0, j = 0;

  // 判断正负号并转化为同号相加的形式
  if (arr1[0] === '-') {
    sign1 = -1;
    i = 1;
  }
  if (arr2[0] === '-') {
    sign2 = -1;
    j = 1;
  }

  // 计算两个数的绝对值长度
  len1 = arr1.length - (sign1 === -1 ? 1 : 0);
  len2 = arr2.length - (sign2 === -1 ? 1 : 0);

  // 为两个数的绝对值长度不足的高位补 0
  if (len1 < len2) {
    arr1.unshift(...Array(len2 - len1).fill('0'));
    len1 = len2;
  } else if (len1 > len2) {
    arr2.unshift(...Array(len1 - len2).fill('0'));
    len2 = len1;
  }

  const res = Array(len1).fill(0);

  // 判断两个数的大小,确保第一个数大于等于第二个数
  if (sign1 === -1 && sign2 === -1) {
    if (arr1.join('') < arr2.join('')) {
      [arr1, arr2] = [arr2, arr1];
      [sign1, sign2] = [sign2, sign1];
    }
  } else if (sign1 === -1 && sign2 === 1) {
    [arr1, arr2] = [arr2, arr1];
    [sign1, sign2] = [sign2, sign1];
  } else if (sign1 === 1 && sign2 === -1) {
    if (arr1.join('') < arr2.join('')) {
      [arr1, arr2] = [arr2, arr1];
      [sign1, sign2] = [sign2, sign1];
    }
  }

  let borrow = false; // 是否需要借位

  // 从个位数开始计算
  for (let k = len1 - 1; k >= 0; k--) {
    let num1 = Number(arr1[k]);
    let num2 = Number(arr2[k]);

    if (borrow) {
      num1 -= 1;
      borrow = false;
    }

    if (sign1 === -1) num1 = -num1;
    if (sign2 === -1) num2 = -num2;

    let diff = num1 + num2;

    if (diff < 0) {
      diff += 10;
      borrow = true;
    }

    if (sign1 === -1) diff = -diff;

    res[k] = diff;
  }

  // 判断是否需要借位
  if (sign1 === -1 && sign2 === -1 && borrow) {
    for (let k = len1 - 1; k >= 0; k--) {
      if (res[k] === 0) {
        res[k] = 9;
      } else {
        res[k] -= 1;
        break;
      }
    }
  }

  // 去除结果中高位的 0
  while (res[0] === 0 && res.length > 1) {
    res.shift();
  }

  // 组合结果字符串
  let resStr = '';
  if (sign1 === -1 && (sign2 === -1 || sign2 === 1 && arr1.join('') < arr2.join(''))) {
    resStr = '-';
  }
  resStr += res.join('');

  return resStr;
}

测试代码:

console.log(substract('-999999999999999999', '-1')); // -999999999999999998
console.log(substract('-999999999999999999', '+1')); // -1000000000000000000
console.log(substract('-999999999999999999', '0'));  // -999999999999999999
console.log(substract('999999999999999999', '-999999999999999999')); // "2000000000000000000"
console.log(substract('999999999999999999', '+999999999999999999')); // '0'
console.log(substract('-999999999999999999', '-999999999999999999')); // '0'
console.log(substract('+999999999999999999', '+999999999999999999')); // '1999999999999999998'
console.log(substract('0', '0')); // '0'

时间复杂度:$O(n)$,其中 $n$ 表示两个数的绝对值的长度。

空间复杂度:$O(n)$,其中 $n$ 表示两个数的绝对值的长度。