• 183竞赛


    将二进制表示减到 1 的步骤数

    给你一个以二进制形式表示的数字 s 。请你返回按下述规则将其减少到 1 所需要的步骤数:

    如果当前数字为偶数,则将其除以 2 。

    如果当前数字为奇数,则将其加上 1 。

    题目保证你总是可以按上述规则将测试用例变为 1 。

    示例 1:

    输入:s = "1101"
    输出:6
    解释:"1101" 表示十进制数 13 。
    Step 1) 13 是奇数,加 1 得到 14 
    Step 2) 14 是偶数,除 2 得到 7
    Step 3) 7 是奇数,加 1 得到 8
    Step 4) 8 是偶数,除 2 得到 4 
    Step 5) 4 是偶数,除 2 得到 2 
    Step 6) 2 是偶数,除 2 得到 1 
    示例 2:

    输入:s = "10"
    输出:1
    解释:"10" 表示十进制数 2 。
    Step 1) 2 是偶数,除 2 得到 1
    示例 3:

    输入:s = "1"
    输出:0
     

    提示:

    1 <= s.length <= 500
    s 由字符 '0' 或 '1' 组成。
    s[0] == '1'

    /**
     * @param {string} s
     * @return {number}
     */
    var numSteps = function(s) {
      let arr = s.split('');
      let res = 0;
    
      while (arr.length > 1) {
        // console.log(arr);
        if (arr[arr.length - 1] === '1') {//奇数,+1
          plusOne(arr);
        } else if (arr[arr.length - 1] === '0') {//偶数 右移一位 >>1
          arr.pop(); //右移1位, 相当于 s>>1
        }
        res++;
      }
    
      return res;
    };
    //+1
    function plusOne(arr) {
      let flag = false;
      for (let i = arr.length - 1; i >= 0; i--) {
        if (arr[i] === '1') {
          arr[i] = '0';
        } else {
          arr[i] = '1';
          flag = true;
          break;
        }
      }
      if (!flag) {//全是1,再进1位
        arr.unshift('1');
      }
    }
    

      

    // python3 就不会出现变量溢出的情况
    class Solution:
        def numSteps(self, s: str) -> int:
            s = int(s, 2)
            ret = 0
            while s!=1:
                ret += 1
                if s%2:
                    s+=1
                else:
                    s//=2
            return ret
    

      

    /**
     * @param {string} s
     * @return {number}
     */
    var numSteps = function(s) {
            // python3是可以的,可能p3里面不存在超出变量表达范围
            // s = parseInt(s,2)
            // let ret = 0
            // while(s!=1) {
            //    ret += 1
            //     if(s%2){
            //         s+=1;
            //     } else {
            //         s/=2 
            //     }
            // }
            // return ret
            let cs = s.split('');
            let n = cs.length;
            let i = n-1;
            let count = 0;
            let top = 0;
            while(i>0){
                if(cs[i]=='1'){
                    let j = i-1;
                    while(j>=0&&cs[j]=='1'){
                        --j;
                    }
                    if(j>=0) cs[j] = '1';
                    else top = 1;
                    count += i-j+1;
                    i = j;
                }else{
                    --i;
                    ++count;
                }
            }
            return count;
        // >> 计算机把s当成了10进制,就是原来题给的二进制, p3可以可能表示变量的机制不一样
        // let step = 0;
        // while(true){
        //     if(s===1) return step
        //     if(s[s.length-1]==0){
        //         s >>=1;  // 我也想又移一位,但就不会说二进制数组pop一下
        //         step++
        //     }else{
        //         num+=1; // +1 也可以二进制数组从后向前遍历啊,这么简单个场景
        //         step++
        //     }
        // }
        // 后面测试用例通不过,估计是变量超范围
        // let num = parseInt(s,2)
        // let step = 0;
        // while(true){
        //     if(num===1) return step
        //     if(num%2===0){
        //         num/=2;
        //         step++
        //     }else{
        //         num+=1;
        //         step++
        //     }
        // }
    };
    

      

    最长快乐字符串

    如果字符串中不含有任何 'aaa','bbb' 或 'ccc' 这样的字符串作为子串,那么该字符串就是一个「快乐字符串」。

    给你三个整数 a,b ,c,请你返回 任意一个 满足下列全部条件的字符串 s:

    s 是一个尽可能长的快乐字符串。
    s 中 最多 有a 个字母 'a'、b 个字母 'b'、c 个字母 'c' 。
    s 中只含有 'a'、'b' 、'c' 三种字母。
    如果不存在这样的字符串 s ,请返回一个空字符串 ""。

    示例 1:

    输入:a = 1, b = 1, c = 7
    输出:"ccaccbcc"
    解释:"ccbccacc" 也是一种正确答案。
    示例 2:

    输入:a = 2, b = 2, c = 1
    输出:"aabbc"
    示例 3:

    输入:a = 7, b = 1, c = 0
    输出:"aabaa"
    解释:这是该测试用例的唯一正确答案。
     

    提示:

    0 <= a, b, c <= 100
    a + b + c > 0

    var longestDiverseString = function(a, b, c) {
      let arr = [
        { str: 'a', count: a },
        { str: 'b', count: b },
        { str: 'c', count: c }
      ], ans = '';
      
      const last = () => ans.charAt( ans.length - 1 );
      
      while (true) {
        arr.sort((prev, curr) => {
          return curr.count - prev.count;
        });
        
        let add = null;
        
        for (let i = 0; i < 3; i++) {
          let obj = arr[i];
          if (obj.str === last()) continue;
          let { str, count } = obj;
          
          if (i === 0) {
            if (count >= 2) {
              add = str.repeat(2);
              obj.count -= 2;
            } else {
              if (count > 0) {
                add = str;
                obj.count -= 1;
              }
            }
          } else if (count > 0) {
            add = str;
            obj.count -= 1;
          }
          
          break;
        }
        
        if (!add) break;
        ans += add;
      }
      
      return ans;
    };
    

      

    /**
     * @param {number} a
     * @param {number} b
     * @param {number} c
     * @return {string}
     */
    // 虽然当时提交成功。但是感觉是测试用例不完全的原因。getStr 方法中,  if(arr[0].key!==last) 这个判断里面的内容还是不完全的。但是把核心思想体现出来了。优先队列 + 贪心么
    var longestDiverseString = function(a, b, c) {
        let arr = [];
        let oa = {key: 'a', val: a},ob = {key: 'b', val: b},oc = {key: 'c', val: c};
        arr.push(oa, ob, oc);
        arr.sort((a,b)=>b.val-a.val);
        let res = [];
        let last='';
        const getStr = (arr)=>{
            let n1 = arr[0].val, n2 = arr[1].val, n3 = arr[2].val;
            if(arr[0].key!==last){
              while(n1--){
                  res.push(arr[0].key)
              }
              while(n2--){
                  res.push(arr[1].key)
              }
              while(n3--){
                  res.push(arr[2].key)
              }
            } else {
                
              while(n2--){
                  res.push(arr[1].key)
              }
            while(n1--){
                  res.push(arr[0].key)
              }
              while(n3--){
                  res.push(arr[2].key)
              }
            }
        }
         
        while(true){
          
          if(arr[0].val > 2 && arr[0].key!==last){
              
              res.push(arr[0].key, arr[0].key);
              arr[0].val-=2;
              if(arr[1].val){
                res.push(arr[1].key);
                arr[1].val-=1;
                last = arr[1].key
              } else {
                break
              }
              arr.sort((a,b)=>b.val-a.val);
              
          }else if(arr[0].val > 2 && arr[0].key===last){
            if(arr[1].val){
                if(arr[1].val>2){
                  res.push(arr[1].key, arr[1].key);
                  arr[1].val-=2;
                  last = arr[1].key
                }else {
                  res.push(arr[1].key);
                  arr[1].val-=1;
                  last = arr[1].key
                }
              } else {
                break
              }
              arr.sort((a,b)=>b.val-a.val);
    
          }else{
              getStr(arr)
              break;
          }  
        }
        return res.join('')
        
    };
    

      

    石子游戏 III

    Alice 和 Bob 用几堆石子在做游戏。几堆石子排成一行,每堆石子都对应一个得分,由数组 stoneValue 给出。

    Alice 和 Bob 轮流取石子,Alice 总是先开始。在每个玩家的回合中,该玩家可以拿走剩下石子中的的前 1、2 或 3 堆石子 。比赛一直持续到所有石头都被拿走。

    每个玩家的最终得分为他所拿到的每堆石子的对应得分之和。每个玩家的初始分数都是 0 。比赛的目标是决出最高分,得分最高的选手将会赢得比赛,比赛也可能会出现平局。

    假设 Alice 和 Bob 都采取 最优策略 。如果 Alice 赢了就返回 "Alice" ,Bob 赢了就返回 "Bob",平局(分数相同)返回 "Tie" 。

    示例 1:

    输入:values = [1,2,3,7]
    输出:"Bob"
    解释:Alice 总是会输,她的最佳选择是拿走前三堆,得分变成 6 。但是 Bob 的得分为 7,Bob 获胜。
    示例 2:

    输入:values = [1,2,3,-9]
    输出:"Alice"
    解释:Alice 要想获胜就必须在第一个回合拿走前三堆石子,给 Bob 留下负分。
    如果 Alice 只拿走第一堆,那么她的得分为 1,接下来 Bob 拿走第二、三堆,得分为 5 。之后 Alice 只能拿到分数 -9 的石子堆,输掉比赛。
    如果 Alice 拿走前两堆,那么她的得分为 3,接下来 Bob 拿走第三堆,得分为 3 。之后 Alice 只能拿到分数 -9 的石子堆,同样会输掉比赛。
    注意,他们都应该采取 最优策略 ,所以在这里 Alice 将选择能够使她获胜的方案。
    示例 3:

    输入:values = [1,2,3,6]
    输出:"Tie"
    解释:Alice 无法赢得比赛。如果她决定选择前三堆,她可以以平局结束比赛,否则她就会输。
    示例 4:

    输入:values = [1,2,3,-1,-2,-3,7]
    输出:"Alice"
    示例 5:

    输入:values = [-1,-2,-3]
    输出:"Tie"
     

    提示:

    1 <= values.length <= 50000
    -1000 <= values[i] <= 1000

    /**
     * @param {number[]} stoneValue
     * @return {string}
     */
    // 一看就dp ,不过不会做
    var stoneGameIII = function(stoneValue) {
      let n = stoneValue.length, dp = new Array(n + 1).fill(0);
      
      for (let i = n - 1; i >= 0; i--) {
        let max = -Infinity, sum = 0;
        
        for (let j = i; j < Math.min(i + 3, n); j++) {
          sum += stoneValue[j];
          let temp = sum - dp[j + 1]; // temp = 此人拿的石子和 - 对手拿石子的和
          max = Math.max(max, temp);
        }
        
        dp[i] = max;
      }
      
      let ans = dp[0] == 0
        ? 'Tie'
        : dp[0] < 0
          ? 'Bob'
          : 'Alice';
      
      return ans;
    };
    

      

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/number-of-steps-to-reduce-a-number-in-binary-representation-to-one
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 相关阅读:
    【科创人独家】科界CTO林镇南:言必真,行必果,没有尽力而为,只有全力以赴
    【科创人+极客邦科技】百企贡献资源,携手抗击疫情
    【科创人新春篇】创投圈人脉王吴世春:肺炎,Long China,精益创业,回归听云…
    SAP QM 在Quality Notification里维护Internal Note
    地摊重现江湖,疫情带给我们的意外收获
    SAP QM Quality Notification的凭证流
    SAP QM 如何将一个附件挂在一个Quality Notification单据上?
    K项目轶事之被客户通报批评
    SAP MM VL34事务代码批量创建Inbound Delivery
    城市的房价稳定,就能不断吸引人才?
  • 原文地址:https://www.cnblogs.com/zhangzs000/p/12640593.html
Copyright © 2020-2023  润新知