首页 > 其他分享 >LeeCode 92双周赛复盘

LeeCode 92双周赛复盘

时间:2022-11-28 20:15:05浏览次数:63  
标签:遍历 int 个数 length 双周 LeeCode grid 92 回文

T1: 分割圆的最少切割次数

思维题:

  • n 为偶数时,可以对半切割,切割 \(\frac{n}{2}\)次即可

  • n 为奇数时,不满足对称性,需要切割 n 次

  • n 为 1 时,不需要切割

public int numberOfCuts(int n) {
    if (n == 1) {
        return 0;
    }
    if (n % 2 == 0) {
        return n / 2;
    }
    
    return n;
}

T2: 行和列中一和零的差值

思路:按要求模拟即可,第一次遍历统计,第二次遍历计算。

public int[][] onesMinusZeros(int[][] grid) {
    // 第一遍遍历统计第 i 行 0 的数目和第 j 列 0 的数目
    int m = grid.length;
    int n = grid[0].length;
    
    int[] zeroRow = new int[m];
    int[] zeroCol = new int[n];

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            if (grid[i][j] == 0) {
                zeroRow[i] += 1;
                zeroCol[j] += 1;
            }
        }
    }

    // 构建差值矩阵
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            grid[i][j] = (n - zeroRow[i]) + (m - zeroCol[j]) - (zeroRow[i]) - (zeroCol[j]);
        }
    }

    return grid;
}

T3: 商店的最小代价

思路:前后缀统计

  • 第一次遍历统计字符串中 Y 的个数,即在 0 小时关门的代价

  • 第二次遍历计算在1~N 小时关门的代价

public int bestClosingTime(String customers) {
    int pos = 0;
    int cost = 0;
    for (int i = 0; i < customers.length(); i++) {
        if (customers.charAt(i) == 'Y') {
            cost += 1;
        }
    }

    if (cost == 0) {
        return pos;
    }

    int min = cost;
    for (int i = 1; i <= customers.length(); i++) {
        if (customers.charAt(i - 1) == 'Y') {
            cost -= 1;
        }
        else {
            cost += 1;
        }

        if (cost < min) {
            min = cost;
            pos = i;
        }
    }

    return pos;
}

T4: 统计回文子序列的数目

思路:动态规划 + 前缀/后缀和

回文子序列的长度固定为5,则其形式必须为xyzyx(x、y、z可以相等),即回文中心为单个字符,左右包括两个对称的双字符序列。

由于字符串只包含0~9的数字,所以 xy 一共只有100种

  • 枚举所有回文中心 i,统计s[0, i - 1]中 xy 的个数,s[i + 1, s.length() - 1] 中 yx 的个数
  • \(ans = \sum_{i = 0}^{s.length() - 1} {\sum_{0}^{99} {count_{ab} * count_{ba}}}\)

如何高效统计 s[0, i-1] 以及 s[i + 1, s.length() - 1] 中各对字符的个数呢?

  1. 利用动态规划的思想,统计 s[0, i - 1] 中 xy 的个数,正向遍历字符串
  2. \(\begin{cases}dp[i][j][k] = dp[i - 1][j][k] + prefix[j] \quad (s[i] == k) \\dp[i][j][k] = dp[i - 1][j][k] \quad (s[i] != k)\end{cases}\)
  3. 上述公式中 prefix[j] 表示 s[0, i - 1] 中 j 的个数
  4. 由于动态规划过程中当前状态只取决于上一状态,可以将其简化为 \(dp[j][k] += prefix[j] \quad (s[i] == k)\)
  5. 统计 s[i + 1, s.length() - 1] 中 yx 的个数也是类似的道理,需要逆向遍历字符串并维护一个后缀数组suffix
/**
 * 核心思路:回文串长度为5, 等价于回文中心是单个数字,且左右各有两个对称的数字, 即 12321
 * 
 * 枚举所有的回文中心 i (0 <= i <= s.length() - 1)
 * 统计 s[0 ... i - 1] 中 xy 的个数 count1, xy只有 100 种情况
 * 统计 s[i + 1 ... s.length() - 1] 中 yx 的个数 count2
 * 
 * ans = \sum_{0}^{s.length() - 1} {\sum_{0}^{99} {count1 * count2}}
 * @param s
 * @return
 */
public int countPalindromes(String s) {
    char[] arr = s.toCharArray();
    
    int[] prefix = new int[10];
    int[] suffix = new int[10];

    int[][] prefix2 = new int[10][10];
    int[][] suffix2 = new int[10][10];

    // 逆序遍历, 统计 xy 个数
    // dp[pos][x][y] = dp[pos + 1][x][y] + suffix[y]  if (cur == x)
    // dp[pos][x][y] = dp[pos + 1][x][y]              if (cur != x)
    for (int i = arr.length - 1; i >= 0; i--) {
        int cur = arr[i] - '0';
        for (int j = 0; j <= 9; j++) {
            suffix2[cur][j] += suffix[j];
        }

        suffix[cur] += 1;
    }

    int ans = 0;
    for (int i = 0; i < arr.length; i++) {
        int cur = arr[i] - '0';
        suffix[cur] -= 1;

        // 去除后序遍历计算的包括当前位置的xy个数
        for (int j = 0; j <= 9; j++) {
            suffix2[cur][j] -= suffix[j];
        }

        for (int j = 0; j <= 9; j++) {
            for (int k = 0; k <= 9; k++) {
                ans += (long) prefix2[k][j] * suffix2[j][k];
            }
        }

        for (int j = 0; j <= 9; j++) {
            prefix2[j][cur] += prefix[j];
        }
        prefix[cur] += 1;
    }

    return (int) (ans % MOD);
}

标签:遍历,int,个数,length,双周,LeeCode,grid,92,回文
From: https://www.cnblogs.com/ylyzty/p/16933460.html

相关文章

  • https://www.cnblogs.com/liyue3/p/16924616.html
    Android12源码网盘下载路径:“iTOP-3588开发板\01_【1TOP-RK3588开发板】基础资料\03_iTOP-RK3588开发板Android12源码”源码是分卷压缩包,需要全部下载下来放在同......
  • sql92和SQL99的区别
    SQL92和SQL99都是用来表示多表的联合查询使用的,两者在开发中,具体使用哪一种都是可以的,但是在书写和阅读的过程中,具体表现在以下:1、笛卡尔积中的区别①SQL92中的笛卡尔积:s......
  • 【LeeCode】136. 只出现一次的数字
    【题目描述】给你一个 非空 整数数组 ​​nums​​ ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。你必须设计并实现线性时间复杂度......
  • leetcode-929-easy
    UniqueEmailAddressesEveryvalidemailconsistsofalocalnameandadomainname,separatedbythe'@'sign.Besideslowercaseletters,theemailmaycontai......
  • 【LeeCode】169. 多数元素
    【题目描述】​​https://leetcode.cn/problems/majority-element/description/?favorite=2cktkvj​​给定一个大小为 ​​n​​ 的数组 ​​nums​​ ,返回其中的多数元......
  • 【LeeCode】229. 多数元素 II
    【题目描述】​​https://leetcode.cn/problems/majority-element-ii/description/​​给定一个大小为 n 的整数数组,找出其中所有出现超过 ​​​⌊n/3⌋​​​ 次的......
  • 第一次双周赛
    https://pintia.cn/problem-sets/1591416544356323328/exam/problems/1591417091146764289T1只需要判断前后有没有L,在把这里涂成C最后输出即可,i=0要特判#include<bit......
  • 【LeeCode】46. 全排列
    【题目描述】​​https://leetcode.cn/problems/permutations/?favorite=2cktkvj​​给定一个不含重复数字的数组 ​​nums​​ ,返回其 所有可能的全排列 。你可以 按......
  • 【Leecode】有效括号
    【题目描述】给定一个只包括 ​​'('​​,​​')'​​,​​'{'​​,​​'}'​​,​​'['​​,​​']'​​ ​​s​​ ,判断字符串是否有效​有效字符串需满足:左括号必须用相同......
  • 【LeeCode】M选N
    【题目描述】M选N组合算法, 有m长度的数组,从中随机选出n个,一般m远大于n【示例】例如求5中选3的组合:1,2,3   1,2,4   1,3,4  2,3,4   1,2,5   1,3......