868. 二进制间距

122 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

一、题目描述

  • 给定一个正整数 n,找到并返回 n 的二进制表示中两个 相邻 1 之间的 最长距离 。如果不存在两个相邻的 1,返回 0 。
  • 如果只有 0 将两个 1 分隔开(可能不存在 0 ),则认为这两个 1 彼此 相邻 。两个 1 之间的距离是它们的二进制表示中位置的绝对差。例如,"1001" 中的两个 1 的距离为 3 。
  • 示例 1:
    • 输入: n = 22
    • 输出: 2
    • 解释
      • 22 的二进制是 "10110" 。
      • 在 22 的二进制表示中,有三个 1,组成两对相邻的 1 。
      • 第一对相邻的 1 中,两个 1 之间的距离为 2 。
      • 第二对相邻的 1 中,两个 1 之间的距离为 1 。
      • 答案取两个距离之中最大的,也就是 2 。
  • 示例 2:
    • 输入: n = 8
    • 输出: 0
    • 解释
      • 8 的二进制是 "1000" 。
      • 在 8 的二进制表示中没有相邻的两个 1,所以返回 0 。
  • 示例 3:
    • 输入: n = 5
    • 输出: 5
    • 解释:5 的二进制是 "101" 。
  • 提示:
    • 1 <= n <= Math.pow(10, 9)

二、思路分析:

  • 想要得到二进制的最长间距,首先你需要先把给到的十进制的数字转化成二进制表示,对吧
    • 转化方法:toString,传入一个数字参数,该方法会将调用这个方法的数字转化成你传入参数的进制表示。
      • 注意下,这个方法返回的是表示该进制数的字符串
      • 例如:n = 22n.toString(2)返回"10110"
  • 将十进制的数字转化成二进制字符串之后呢?
    • 定义一个保存最长间距的变量,后面会用到
    • 遍历二进制字符串,如果当前的这个字符串中的字符等于1,再次遍历这个字符串,不过要从这个当前位置的下一个位置开始遍历,直到找到下一个等于1的字符
    • 将这两个等于字符1的位置相减取绝对值,利用Math.max方法,将之前定义保存最长间距的变量和这个差值的绝对值两两比较,返回最大的再赋值给这个结果变量
  • 遍历结束后,结果变量保存的是二进制最长间距的值,返回即可

三、AC 代码:

function binaryGap(n: number): number {
    let fixed = n.toString(2);
    let lengths = 0;
    for(let i = 0; i < fixed.length; i++){
        if(fixed[i] === '1'){
            for(let j = i + 1; j < fixed.length; j++){
                if(fixed[i] === fixed[j]){
                    lengths = Math.max(lengths, Math.abs(i - j));
                    break;
                }
            }
        }
    }
    return lengths;
};

四、总结:

  • 为什么要在二次遍历前判断fixed[i]是不是等于字符串1
    • 首先题目要求的是1之间的最长间距
    • 如果不在这里判断,在二层遍历里面一样需要判断
    • 在二次遍历前判断的优势在于,如果首次遍历的当前字符不等于1,那么久没必要开启二次循环,直接遍历下一个字符,省略了无效的二次遍历
  • 注意下字符间距的两两比较,在二次遍历的时候如果找到了距离外层的第一个字符1,那么需要退出当前的二次遍历,也就是需要手动break一下

81a522564069b084c2e5762b0691090.png