千位分隔数

283 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

给你一个整数 n,请你每隔三位添加逗号(即 "," 符号)作为千位分隔符,并将结果以字符串格式返回。

比如:输入数字 58327,输出字符串 58,327

二、思路分析:

这个题目还是比较简单的,首先想到的是使用正则匹配的形式,通过正向查找 (?=exp) 符号匹配 exp 前面的位置。exp1(?=exp2) 表示查找 exp2 前面的 exp1。根据题目每隔三位添加逗号,我们从前往后添加逗号,如果后面超3为数,前面的数字才需要添加逗号。

function moneySplice(num){
  let str = String(num)
  retrun str.replace(/(\d{1,3})(?=(\d{3})+$)/g,'$1,')
}

如果面试的时候不让用正则来实现,必须用算法来实现,我们就相对比较困难。不用正则实现的思路是这样的,假设提供的数字是 58327,我们可以每次取出一位(除于10即可),减少之后变成 5832,按照这个逻辑继续操作,在这个过程中要记录提取了多少次,如果提取了三次那就加上逗号。

58327 5832 提取7
5832  583  提取2,得到72
583   58.  提取3,得到723,
58    8.   提取8,得到723,8
5     5.   提取5,得到723,85

最后将字符串反转:723,85 变成 58,327

根据思路我们可以写出下面的代码:

var thousandSeparator = function(n) {
  let count = 0;
  let ans = "";
  do {
      let cur = n % 10;
      n = Math.floor(n / 10);
      ans += cur.toString();
      ++count;
      if (count % 3 == 0 && n) {
          ans += '.';
      }
  } while (n);
  return ans.split('').reverse().join('');
}

上面代码是通过 count 记录提取了多少次,我们也可以通过数组的长度来判断提取的次数。

var thousandSeparator = function(n) {
  let list = []
  do {
      list.push(n % 10)
      n = Math.floor(n / 10)
      if (list.length % 3 === 0 && n) {
        list.push(',')
      }
  } while (n);
  return list.reverse().join('')
}

上面是使用数组反转,其实我们也可以使用字符串拼接。

var thousandSeparator = function(n) {
  let list = []
  do {
      list.push(n % 10)
      n = Math.floor(n / 10)
      if (list.length % 3 === 0 && n) {
        list.push(',')
      }
  } while (n);
  let coverted = ''
  while(list.length) {
    coverted += list.pop()
  }
  return coverted
}

四、总结:

这道题目主要考察数据结构栈。

栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构,也就是最新添加的项最早被移除。数组专门提供了 push() 和 pop() 方法,以便实现类似栈的行为。

关于栈的使用技巧还要很多,比如可以利用栈将一个数字从一种数制转换成另一种数制。假设想将数字 n 转换为以 b 为基数的数字,实现转换的算法如下。

function mulBase(num, base) {
  let list = []
  do {
    list.push(num % base)
    num = Math.floor(num / base)
  } while (num > 0)
  let converted = ''
  while (list.length > 0) {
    converted += list.pop()
  }
  return converted
}

let num = 100
console.log(mulBase(num, 2)) // 1100100
console.log(num.toString(2)) // 1100100

数字的 toString 方法也可以传入参数表示需要将数字转换为多少进制的字符串。

算法也很简单,我们再来一个常见的面试题,那就是判断回文字符串。

function isPalindrome(word) {
  let list = []
  for(let i = 0; i < word.length; i++) {
    list.push(word[i])
  }
  let rword = ''
  while (list.length > 0) {
    rword += list.pop()
  }
  return word === rword
}

做算法要学会灵活的应用,每个题目都可以联想出来很多类似的题目。