798. 得分最高的最小轮调(拆分)

193 阅读3分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

不是因为看到了希望才坚持,而是因为坚持了才能看到希望。共勉

每日刷题第59天 2021.03.09

798. 得分最高的最小轮调

题目描述

  • 给你一个长桌子,桌子上盘子和蜡烛排成一列。给你一个下标从 0 开始的字符串 s ,它只包含字符 '' 和 '|' ,其中 '' 表示一个 盘子 ,'|' 表示一支 蜡烛 。
  • 同时给你一个下标从 0 开始的二维整数数组 queries ,其中 queries[i] = [lefti, righti] 表示 子字符串 s[lefti...righti] (包含左右端点的字符)。对于每个查询,你需要找到 子字符串中 在 两支蜡烛之间 的盘子的 数目 。如果一个盘子在 子字符串中 左边和右边 都 至少有一支蜡烛,那么这个盘子满足在 两支蜡烛之间。
  • 比方说,s = "|||||" ,查询 [3, 8] ,表示的是子字符串 "||**|" 。子字符串中在两支蜡烛之间的盘子数目为 2 ,子字符串中右边两个盘子在它们左边和右边 都 至少有一支蜡烛。
  • 请你返回一个整数数组 answer ,其中 answer[i] 是第 i 个查询的答案。

解题思路

  • A=[2,3,1,4,0]为例:

  • A[0]=2移动到2号索引位置[4,0,2,3,1]其对应的K3=(0-A[0]+5)%5

  • 根据公式K=(i-A[i]+N)%N可以计算出,A[i]移动到其索引i=A[i]时对应的K的数组为:[3,3,1,4,4]

  • 为了更好的理解上面数组的由来,不妨写出K为上述数字中对应值时数组A的情况

    • 3:K3时对应的数组为:[4,0,2,3,1],此时2、3位置的值与索引相同
    • 1:K1时对应的数组为:[3,1,4,0,2],此时1位置的值与索引相同
    • 4:K4时对应的数组为:[0,2,3,1,4],此时0、4位置的值与索引相同
  • 此时若将K再加1,本来索引与值正好相等,然而索引却变小了1,因此可以知道K+1时对应的这些位置的分值便会减少,不妨记录下、当某个位置的分值由原本的有效到无效时的K的值:

  • 最后由diffs还原point,显然diffs[0]就是point[0]

  • diffs[i] = point[i] - point[i - 1],所以point[i] = diffs[i] + point[i - 1];

  • 定义一个mark先等于point[0],即为不调整时的得分,之后用mark累加diffs数组

  • 因为,mark = diffs[0] + diffs[1] = point[0] + point[1] - point[0] = point[1],这可以推广到i的情况

  • 所以diffs累加到i的结果就是point[i],从中选出最大的即可

AC代码

var bestRotation = function (A) {
    // 保存结果
    let result = 0;
    // 记录保存数组长度
    let arrLength = A.length;
    // 记录移动K次 节点值等于下标的数量,默认数量都为0
    const normalArr = new Array(arrLength).fill(0);
    // 记录每个节点的分数
    let tem = 0;
    for (let i = 0; i < arrLength; i++) {
        if (A[i] > i) {
            // 移动 arrLength + i - A[i]后,该节点值等于下标,所以 
            normalArr[arrLength + i - A[i]]++;
        } else {
            // 移动 i - A[i]后,该节点值等于下标,所以 
            normalArr[i - A[i]]++;
            // 记录初次的分数
            tem++;
        }
    }
    // 保存最高分数
    let max = tem;
    for (let K = 1; K < arrLength; K++) {
        // 每次移动只需要判断这次移动 有多少数组变为不符合要求的,将原来的减去该参数即可
        tem = tem - normalArr[K - 1] + 1;
        // 只有当有更优解的时候 继续新的result
        if (tem > max) {
            max = tem;
            result = K;
        }
    }
    return result;
};

总结

  • 困难题,第一次接触拆分的思想,之前接触的快速排序的分治思想,和这个比较相似。