本周总共有7个题
    周一
    丑数
    给你一个整数 n ,请你判断 n 是否为 丑数 。如果是,返回 true ;否则,返回 false 。
    丑数 就是只包含质因数 2、3 和/或 5 的正整数。
    链接:https://leetcode-cn.com/problems/ugly-number

    1. /**
    2. @param {number} n
    3. @return {boolean}
    4. */
    5. var isUgly = function(n) {
    6. //对N 取模,如果模为0在取商,如果2,3,5都取完了就看商是不是为1
    7. while(true){
    8. if(n<=0) return false //边界一开始最好就搞清楚
    9. if(n%2 === 0){
    10. n = n/2
    11. }else if(n%3 === 0){
    12. n = n/3
    13. }else if(n%5 =0){
    14. n = n/5
    15. }else{
    16. if(n=1){
    17. return true
    18. }else{
    19. return false
    20. }
    21. }
    22. }
    23. };


    回文数
    tips 这个题目是我加餐的,进阶要求是不能转为字符串来解决,第一周目我想仿照快慢指针来求解,但是其实只写出来一个半成品(看了官方解答,不是半成品,有些判定条件他自己也没有办法加进去)
    给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
    回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
    链接:https://leetcode-cn.com/problems/palindrome-number

    1. /**
    2. @param {number} x
    3. @return {boolean}
    4. */
    5. //1.23 n =2
    6. //123.123 -》123
    7. var isPalindrome = function(x) {
    8. //通过快慢指针找到中间点,反转
    9. let count = 0
    10. function findMiddleFunc(n){
    11. // 如果数字长度是偶数 结果是没有问题的,但是如果是奇数,就会有一位的偏差,该怎么修正
    12. //1122 fine
    13. //121 -> 1.21 vs 12.1
    14. let low = n
    15. let fast = n
    16. while(fast >1){
    17. fast = fast/100
    18. low = low/10
    19. count ++
    20. }
    21. // console.log(low)
    22. return Math.floor(low)
    23. }
    24. function reverse(n){//反转数字
    25. let result = 0
    26. if(count ===0)return n
    27. while(count>0){
    28. //21120 是个坑
    29. count--
    30. result = result*10+ (n%10)
    31. n = Math.floor(n/10)
    32. // console.log(n)
    33. }
    34. // console.log(result)
    35. return result
    36. }
    37. // console.log(Math.floor(findMiddleFunc(x) ))
    38. // console.log(reverse(x))

    //小于0直接判定 我一直希望能把这个判定写进两个函数里面,后面发现官方也是这么写的
    if (x < 0 || (x % 10 === 0 && x !== 0)) {
    return false;
    }
    //奇数和偶数长度判定
    return findMiddleFunc(x)=== reverse(x) ||findMiddleFunc(x)=== Math.floor(reverse(x)/10 )
    };
    这个题目提交错误12次….
    周二
    丢失的数字
    给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。
    进阶:

    你能否实现线性时间复杂度、仅使用额外常数空间的算法解决此问题?
    链接:https://leetcode-cn.com/problems/missing-number
    /**

    • @param {number[]} nums
    • @return {number}
      /
      var missingNumber = function(nums) {
      //注意看题,给定一个包含[0,n]的n个数的数组 也就是说数组加上缺失的元素应该有 (n+1)个
      // 解法求出总和 - 实际和
      const n = nums.length
      const total = n
      (n+1)/2
      const actual = nums.reduce((pre,next)=>{return pre+next})
      return total-actual
      };
      /**
    • @param {number[]} nums
    • @return {number}
      /
      var missingNumber = function(nums) {
      //使用异或+交换律
      // a = 1 ^ 1^ 2=2
      const n = nums.length
      let curr = nums.reduce((pre,next)=>{
      return pre ^next
      })
      for(let i = 0;i<=n;++i){
      curr ^=i
      }
      return curr
      };
      周三
      第一个错误的版本
      你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
      假设你有 n 个版本 [1, 2, …, n],你想找出导致之后所有版本出错的第一个错误的版本。
      你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
      链接:https://leetcode-cn.com/problems/first-bad-version
      /*
    • Definition for isBadVersion()

    • @param {integer} version number
    • @return {boolean} whether the version is bad
    • isBadVersion = function(version) {
      1. ...
    • };
      */

    //[1,2,3..]这是一个顺序的数组,通过二分法可以有效的缩短
    //之前的思路都是活动的middle
    //看了官解之后选择[活动的边界]
    /**

    • @param {function} isBadVersion()
    • @return {function}
      /
      var solution = function(isBadVersion) {
      /*
      • @param {integer} n Total versions
      • @return {integer} The first bad version
        /
        //初始边界值是1,n
        return function(n) {
        let left = 1
        let right = n
        let middle = null
        while(leftmiddle = Math.floor((left +(right-left)/2)) //这个计算方法很妙,我都是直接左右和/2,他这个是以左边点为
        //出发点加上差值一半,当时看官解说是防溢出,也就是左右的和过大
        if(isBadVersion(middle)){
        //中间是坏版本,那么就得在 left -middle中找
        right = middle
        }else{
        //不是就得在中间之后的一位和right中找
        left = middle+1
        }
        }
        return left
        };
        };
        周四
        移动零
        给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
        https://leetcode-cn.com/problems/move-zeroes/
        /*
    • @param {number[]} nums
    • @return {void} Do not return anything, modify nums in-place instead.
      /
      var moveZeroes = function(nums) {
      //第一种解法数组一边shift() 一边 push
      let len = nums.length
      let count = 0
      let curr = null
      for(let i =0;icurr = nums.shift()
      if(curr === 0 ){
      count
      }else{
      nums.push(curr)
      }
      }
      while(count>0){
      nums.push(0)
      count—
      }
      return nums
      };
      /*
    • @param {number[]} nums
    • @return {void} Do not return anything, modify nums in-place instead.
      /
      var moveZeroes = function(nums) {
      //使用快慢指针
      //我其实没想到这种题可以使用快慢指针 表示下标
      const len = nums.length
      let fast = 0 //去寻找非0元素
      let low = 0 //始终指向第一个0的位置
      while(fastif(nums[low] !==0){
      fast++
      low++
      }else if(nums[fast] === 0){//low指向第一个0,但是fast还没有找到非0
      fast++
      }else{//找到了
      [nums[low],nums[fast]] = [nums[fast],nums[low]]
      //对调完成
      low++
      fast++
      }
      }
      return nums
      };
      周五
      单词规律
      给定一种规律 pattern 和一个字符串 str ,判断 str 是否遵循相同的规律。
      这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应规律。
      链接:https://leetcode-cn.com/problems/word-pattern
      /*
    • @param {string} pattern
    • @param {string} s
    • @return {boolean}
      */
      var wordPattern = function(pattern, s) {
      //双hash标
      const patternMap = new Map()
      const patternArray = […pattern]
      const sMap = new Map()
      const sArray = s.split(‘ ‘)
      if(patternArray.length !== sArray.length) return false
      patternArray.forEach((item,index)=>{
      // a —0
      // b —1
      if(!patternMap.has(item)){
      patternMap.set(item,index)
      }
      })
      sArray.forEach((item,index)=>{
      //dog —0
      //cat —1
      if(!sMap.has(item)){
      sMap.set(item,index)
      }
      })

    for(let i = 0;i//a map 的索引
    if( sArray[patternMap.get(patternArray[i])] !==sArray[i]){
    return false
    }
    if(patternArray[sMap.get(sArray[i])] !==patternArray[i]){
    return false
    }
    }
    return true
    };
    脑袋晕乎乎的,这个题的多解法暂时不看了
    周六
    你和你的朋友,两个人一起玩 Nim 游戏:

    桌子上有一堆石头。
    你们轮流进行自己的回合,你作为先手。
    每一回合,轮到的人拿掉 1 - 3 块石头。
    拿掉最后一块石头的人就是获胜者。
    假设你们每一步都是最优解。请编写一个函数,来判断你是否可以在给定石头数量为 n 的情况下赢得游戏。如果可以赢,返回 true;否则,返回 false 。
    https://leetcode-cn.com/problems/nim-game/
    /**

    • @param {number} n
    • @return {boolean}
      */
      var canWinNim = function(n) {
      //第一个想法是递归,假设最后一个石头是你拿的,那么推回来第一次你拿的石油能否在1-3
      // 但是我看这个题目应该是个动态规划的题目
      //数学规律 1,2,3 win 4,lose 5,6,7win ,8lose
      // if(n<=3) return true
      if(n%4 ==0){
      return false
      }else{
      return true
      }
      };
      //此处需要补充一个动态规划的解法,但是我要去看电影了哈哈,明天在看
      动态方程:
      这个题目第一眼就是要是用动态方程求解,虽然我看到题解当中很多人都说超时
      动态的步骤是:
      1.递归+记忆化 ->递推

    2.状态的定义:opt[n],dp[n],fib[n]
    定义成一个数组

    3.状态转移方程: opt[n] = best_of( opt[n-1],opt[n-2],…..) DP方程

    1.先手对应 n 个石头,后面肯定对应 n-1 /n-2 /n-3个石头
    从最后一步分析,如果先手剩余1-3个石头,那先手取得胜利/剩余0个个石头先手失败
    所以递推关系
    Fn = F(n-1)
    倒数第二手的三种解法都失败了,倒数第一手才会成功
    f(n) = !( f(n-1) && f(n-2) && f(n-3)) /这里也可以写成 !f(n-1) && !f(n-2) && !f(n-3)
    f(0) = false
    function canWinNim(n){
    if(n<=3){
    return true
    }
    return !(canWinNim(n-1) && canWinNim(n-2) && canWinNim(n-3))
    }
    当然,这里最后测试的结果是超时,但是我只是因为不记得动态规划所以复习一下