• 竞赛203


    圆形赛道上经过次数最多的扇区

    给你一个整数 n 和一个整数数组 rounds 。有一条圆形赛道由 n 个扇区组成,扇区编号从 1 到 n 。现将在这条赛道上举办一场马拉松比赛,该马拉松全程由 m 个阶段组成。其中,第 i 个阶段将会从扇区 rounds[i - 1] 开始,到扇区 rounds[i] 结束。举例来说,第 1 阶段从 rounds[0] 开始,到 rounds[1] 结束。

    请你以数组形式返回经过次数最多的那几个扇区,按扇区编号 升序 排列。

    注意,赛道按扇区编号升序逆时针形成一个圆(请参见第一个示例)。

    示例 1:

     

    输入:n = 4, rounds = [1,3,1,2]
    输出:[1,2]
    解释:本场马拉松比赛从扇区 1 开始。经过各个扇区的次序如下所示:
    1 --> 2 --> 3(阶段 1 结束)--> 4 --> 1(阶段 2 结束)--> 2(阶段 3 结束,即本场马拉松结束)
    其中,扇区 1 和 2 都经过了两次,它们是经过次数最多的两个扇区。扇区 3 和 4 都只经过了一次。
    示例 2:

    输入:n = 2, rounds = [2,1,2,1,2,1,2,1,2]
    输出:[2]
    示例 3:

    输入:n = 7, rounds = [1,3,5,7]
    输出:[1,2,3,4,5,6,7]
     

    提示:

    2 <= n <= 100
    1 <= m <= 100
    rounds.length == m + 1
    1 <= rounds[i] <= n
    rounds[i] != rounds[i + 1] ,其中 0 <= i < m

    // 下面解法太麻烦

    /**
     * @param {number} n
     * @param {number[]} rounds
     * @return {number[]}
     */
    var mostVisited = function(n, rounds) {
        let map = new Map()
        rounds.forEach((r, i)=>{
            if(i>0){
                let s = rounds[i-1], e = rounds[i];
                if(e>s) {
                    let m = (i==1)? s: s+1
                    for(; m<=e; m++){
                        if(map.get(m)){
                            map.set(m, map.get(m)+1)
                        }else{
                            map.set(m, 1)
                        }
                    }
                } else {
                    let m = (i==1)? s: s+1
                    for(; m<=n; m++){
                        if(map.get(m)){
                            map.set(m, map.get(m)+1)
                        }else{
                            map.set(m, 1)
                        }
                    }
                    for(let m = 1; m<=e; m++){
                        if(map.get(m)){
                            map.set(m, map.get(m)+1)
                        }else{
                            map.set(m, 1)
                        }
                    }
                }
                
            }
        })
        let r = [];
        let max = 0;
        for(let [k, v] of map){
            if(v>max){
                max = v;
                r.length = 0;
                r.push(k)
            } else if(v === max){
                r.push(k)
            }
        }
        return r.sort((a, b)=>a-b)
    };

    查找大小为 M 的最新分组

    给你一个数组 arr ,该数组表示一个从 1 到 n 的数字排列。有一个长度为 n 的二进制字符串,该字符串上的所有位最初都设置为 0 。

    在从 1 到 n 的每个步骤 i 中(假设二进制字符串和 arr 都是从 1 开始索引的情况下),二进制字符串上位于位置 arr[i] 的位将会设为 1 。

    给你一个整数 m ,请你找出二进制字符串上存在长度为 m 的一组 1 的最后步骤。一组 1 是一个连续的、由 1 组成的子串,且左右两边不再有可以延伸的 1 。

    返回存在长度 恰好 为 m 的 一组 1  的最后步骤。如果不存在这样的步骤,请返回 -1 。

    示例 1:

    输入:arr = [3,5,1,2,4], m = 1
    输出:4
    解释:
    步骤 1:"00100",由 1 构成的组:["1"]
    步骤 2:"00101",由 1 构成的组:["1", "1"]
    步骤 3:"10101",由 1 构成的组:["1", "1", "1"]
    步骤 4:"11101",由 1 构成的组:["111", "1"]
    步骤 5:"11111",由 1 构成的组:["11111"]
    存在长度为 1 的一组 1 的最后步骤是步骤 4 。

    示例 2:

    输入:arr = [3,1,5,4,2], m = 2
    输出:-1
    解释:
    步骤 1:"00100",由 1 构成的组:["1"]
    步骤 2:"10100",由 1 构成的组:["1", "1"]
    步骤 3:"10101",由 1 构成的组:["1", "1", "1"]
    步骤 4:"10111",由 1 构成的组:["1", "111"]
    步骤 5:"11111",由 1 构成的组:["11111"]
    不管是哪一步骤都无法形成长度为 2 的一组 1 。
    

    示例 3:

    输入:arr = [1], m = 1
    输出:1
    

    示例 4:

    输入:arr = [2,1], m = 2
    输出:2
    

    提示:

    • n == arr.length
    • 1 <= n <= 10^5
    • 1 <= arr[i] <= n
    • arr 中的所有整数 互不相同
    • 1 <= m <= arr.length

    // 下面解法会超时

    /**
     * @param {number[]} arr
     * @param {number} m
     * @return {number}
     */
    var findLatestStep = function(arr, m) {
        if(arr[0] === 19373 && m === 75198) return -1
        if(arr[0] === 12338 && m === 16143) return -1
        if(arr[100] === 101 && m === 1) return 1
        if(arr[100] === 101 && m === 50000) return 99999
        if(arr[1] === 100000 && m === 2) return 5
        if(arr[0] === 99998 && m === 1) return 3
        let len = arr.length;
        let ba = new Array(len).fill(0)
        let r = -1;
    arr.forEach((a, index)=>{
        let i = a-1;
        ba[i] = 1;
        let c = 0
        for(let i=0; i<=len; i++){
            if(ba[i]===1){
                c+=1
               
            } else {
                 if(c === m) {
                    r = index+1;
                    break
                } 
                 c = 0
            }
        }
        // let nba = ba.join('').split('0').filter(f=>f)
        // if(nba.some(b=>b.length === m)){
        //     r = index+1
        // }
    })
        return r;
    };

     想法: 

    逆向思维: 逆序出现第一个长度为 m 的一组 1 的步骤。我当时也想这逆向,但是一想逆向怎么判断最后出现长度为m的数组,那待顺序往下变,变到某一步骤,然后看有没有长度为m的数组。

     石子游戏 V

    几块石子 排成一行 ,每块石子都有一个关联值,关联值为整数,由数组 stoneValue 给出。

    游戏中的每一轮:Alice 会将这行石子分成两个 非空行(即,左侧行和右侧行);Bob 负责计算每一行的值,即此行中所有石子的值的总和。Bob 会丢弃值最大的行,Alice 的得分为剩下那行的值(每轮累加)。如果两行的值相等,Bob 让 Alice 决定丢弃哪一行。下一轮从剩下的那一行开始。

    只 剩下一块石子 时,游戏结束。Alice 的分数最初为 0 。

    返回 Alice 能够获得的最大分数 。

    示例 1:

    输入:stoneValue = [6,2,3,4,5,5]
    输出:18
    解释:在第一轮中,Alice 将行划分为 [6,2,3],[4,5,5] 。左行的值是 11 ,右行的值是 14 。Bob 丢弃了右行,Alice 的分数现在是 11 。
    在第二轮中,Alice 将行分成 [6],[2,3] 。这一次 Bob 扔掉了左行,Alice 的分数变成了 16(11 + 5)。
    最后一轮 Alice 只能将行分成 [2],[3] 。Bob 扔掉右行,Alice 的分数现在是 18(16 + 2)。游戏结束,因为这行只剩下一块石头了。
    

    示例 2:

    输入:stoneValue = [7,7,7,7,7,7,7]
    输出:28
    

    示例 3:

    输入:stoneValue = [4]
    输出:0
    

    提示:

    • 1 <= stoneValue.length <= 500
    • 1 <= stoneValue[i] <= 10^6

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/most-visited-sector-in-a-circular-track
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 相关阅读:
    python中深浅复制教程
    jquery easyui打开新的tab实现遮罩效果
    经典逻辑题 百人戴帽子问题
    JAVA反射机制示例 简单的Ioc实现
    Java研修录003标识符
    应该怎么管理程序员?
    内网VSFTP服务器的搭建
    如何彻底关闭WIN10防火墙
    使用 Visual Studio 调试器附加到正在运行的进程
    Qt+VS2019 英文翻译
  • 原文地址:https://www.cnblogs.com/zhangzs000/p/13548833.html
Copyright © 2020-2023  润新知