js 基础算法题(二)

一、判断一个数是不是质数(素数)

  • 质数又称素数。一个大于 1 的自然数,除了 1 和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数。

  • 0 和 1 既不是质数也不是合数,最小的质数是 2

function isPrime(num) {
  // 这里特殊处理了一下小于等于3的数,因为小于等于3的自然数只有2和3是质数。
  if (num <= 3) return n > 1
  // 循环2到num之间的数,不能超过num
  for (let i = 2; i < num; i++) {
    // 如果2~num之间有可以被num整除的就返回false
    if (num % i === 0) {
      return false
    }
  }
  // 否则返回true
  return true
}
console.log(isPrime(5)) // true

优化: 假如 n 是合数,必然存在非 1 的两个约数 p1 和 p2,其中 p1<=sqrt(n),p2>=sqrt(n)。由此我们可以改进上述方法优化循环次数。

function isPrime2(num) {
  if (num <= 3) return n > 1
  let sqrt = parseInt(Math.sqrt(num))
  for (let i = 2; i <= sqrt; i++) {
    if (num % i === 0) {
      return false
    }
  }
  return true
}
console.log(isPrime2(4)) // false

二、斐波那契数列

  • 描述: 斐波那契数,指的是这样一个数列:1、1、2、3、5、8、13、21、……在数学上,斐波那契数列以如下被以递归的方法定义:F0=0,F1=1,Fn=Fn-1+Fn-2(n>=2,n∈N*),
    用文字来说,就是斐波那契数列由 0 和 1 开始,之后的斐波那契数列系数就由之前的两数相加。
  • 斐波那契数列:1、1、2、3、5、8、13、21、34、……

递归写法

function fibonaqi(n) {
  // 递归必须要有出口
  if (n === 1 || n === 2) return 1
  return fibonaqi(n - 1) + fibonaqi(n - 2)
}
console.log(fibonaqi(12))

循环

function fibonaqi2(n) {
  if (n <= 2) {
    return 1
  }
  // 定义三个变量,前两个开始的数和 sum
  let sum = 0
  let x = 1
  let y = 1
  // 从第二个开始循环
  for (let i = 2; i < n; i++) {
    // 计算和
    sum = x + y
    x = y
    y = sum
  }

  return temp
}
console.log(fibonaqi2(12))

三、求最大公约数

方法 1:使用循环

function greatestCommonDivisor(a, b) {
  // 记录a大还是b大
  let flag = a > b
  // 得到a和b的余数
  let n = flag ? a % b : b % a
  // 如果余数是0最大公约数就是小的那个数
  if (n === 0) return flag ? b : a
  let res = 0
  for (let i = n; i > 0; i--) {
    // 这里倒序a和b的余数得到第一个能被a和b整除的数就停止循环
    if (a % i === 0 && b % i === 0) {
      res = i
      break
    }
  }
  return res
}
console.log(greatestCommonDivisor(4, 8)) // 4
console.log(greatestCommonDivisor(93, 31)) // 1

方法 2:使用递归

function greatestCommonDivisor2(a, b) {
  if (a % b === 0) {
    return b
  }
  return greatestCommonDivisor2(b, a % b)
}
console.log(greatestCommonDivisor2(4, 8)) // 4
console.log(greatestCommonDivisor2(93, 31)) // 1

四、判断数组中是否有两数之和

  • 在一个未排序的数组中找出是否有任意两数之和等于给定的数。
  • 这题很简单,不要想得太复杂
    使用数组的 indexOf 方法
function sumFind(arr, num) {
  // 循环遍历数组
  for (let i = 0; i < arr.length; i++) {
    // 得到num和arr[i]的插值
    let temp = num - arr[i]
    // 判断arr中是否有这个差值,但要排出自己
    if (arr.indexOf(temp, i + 1) !== -1) {
      // 有就返回true
      return true
    }
  }
  // 最后都没有的话返回false
  return false
}
console.log(sumFind([6, 4, 3, 2, 1, 7], 11))

五、用正则实现 trim() 清除字符串两端空格

function trim(str) {
  return str.replace(/^\s*|\s*$/g, '')
}
console.log(trim('   hello world   ')) // hello world

六、宣讲会安排

  • 一些项目要占用一个会议室宣讲,会议室不能同时容纳两个项目的宣讲。 给你每一个项目开始的时间和结束的时间(数组,里面是一个个具体的项目),你来安排宣讲的日程,要求会议室进行 的宣讲的场次最多。返回这个最多的宣讲场次。

  • 步骤:

    1. 先按照会议的 end 时间升序排序;
    2. 排除了因为正在进行会议而无法进行的会议(now > arr[i].start)
    3. 会议能举行,则 res++,并且更新目前时间 now (now = arr[i].end;)。
function getMostCount(arr) {
  // 判断是否有会议
  if (!arr || arr.length < 1) return
  // 将会议按照结束时间排序
  arr.sort((a, b) => a.end - b.end)
  console.log(arr)
  // 记录会议次数
  let res = 1
  // 记录上一次会议的结束时间
  let now = arr[0].end
  for (let i = 1; i < arr.length; i++) {
    // 如果上一次会议的结束时间和这一次会议开始时间不重合,则 res++
    if (now < arr[i].start) {
      res++
      now = arr[i].end
    }
  }
  return res
}
let arr = [
  { start: 6, end: 8 },
  { start: 7, end: 9 },
  { start: 11, end: 12 },
  { start: 10, end: 14 },
  { start: 16, end: 18 },
]
console.log(getMostCount(arr)) // 3

七、水仙花数

  • 所谓的“水仙花数”是指一个三位数其各位数字的立方和等于该数本身,例如 153 是“水仙花数”,因为:153 = 13 + 53 + 33。
  • 根据“水仙花数”的定义,判断一个数是否为“水仙花数”,最重要的是要把给出的三位数的个位、十位、百位分别拆分,并求其立方和(设为 s),若 s 与给出的三位数相等, 三位数为“水仙花数”,反之,则不是。
function narcissusNumber(n) {
  //  “水仙花数”是指满足某一条件的三位数  ,根据这一信息可以确定整数的取值范围是 100〜999
  if (n < 100 || n > 1000) {
    return false
  }
  // 分别取出个位、十位、百位
  let ge = n % 10
  let shi = parseInt((n / 10) % 10)
  let bai = parseInt(n / 100)
  if (ge * ge * ge + shi * shi * shi + bai * bai * bai === n) {
    return true
  }
  return false
}
for (let i = 100; i < 1000; i++) {
  if (narcissusNumber(i)) {
    console.log(i) // 153  370  371  407
  }
}

八、计算闰年

  • 条件一是能够被 4 整除、但是不能被 100 整除;
  • 条件二是能够被 400 整除。满足两个条件中的一个即能判断是闰年。
function getLeapYear(start, end) {
  let arr = []
  for (let i = start; i <= end; i++) {
    if ((i % 4 === 0 && i % 100 !== 0) || i % 400 === 0) {
      arr.push(i)
    }
  }
  return arr
}
console.log(getLeapYear(1900, 2100))

九、1,2,3,4 四个数字,能组合成多少种互不相同且没有重复的三位数

function fun() {
  // 定义一个空数组,用于记录每次组合的数
  let arr = []
  for (let i = 1; i <= 4; i++) {
    for (let j = 1; j <= 4; j++) {
      for (let k = 1; k <= 4; k++) {
        if (i !== j && i !== k && j != k) {
          arr.push(i * 100 + j * 10 + k)
        }
      }
    }
  }
  return arr.length
}
console.log(fun())

十、猴子吃桃问题

  • 猴子吃桃子问题:猴子第一天摘下 N 个桃子,当时就吃了一半,还不过瘾,就又吃了一个。
  • 第二天又将剩下的桃子吃掉一半,又多吃了一个。以后每天都吃前一天剩下的一半零一个。
  • 到第 10 天在想吃的时候就剩一个桃子了。求第一天共摘下来多少个桃子?
function fun() {
  let sum = 1
  for (let i = 1; i < 10; i++) {
    sum = (sum + 1) * 2
  }
  return sum
}
console.log(fun())

欢迎大佬指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值