圆形赛道上经过次数最多的扇区
给你一个整数 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。