力扣第 106 场双周赛题解
题目链接:https://leetcode.cn/contest/biweekly-contest-106/
# T1. 判断一个数是否迷人
链接:https://leetcode.cn/problems/check-if-the-number-is-fascinating/
# 解题思路
hash 计数:
统计每一位数组出现的次数
# 代码
class Solution {  | |
public boolean isFascinating(int n) {  | |
int[] cnt = new int[10];  | |
calc(n, cnt);  | |
calc(2 * n, cnt);  | |
calc(3 * n, cnt);  | |
for (int i = 1; i < 10; ++i) {  | |
if (cnt[i] != 1) return false;  | |
        } | |
return true;  | |
    } | |
private void calc(int n, int[] cnt) {  | |
while (n > 0) {  | |
++cnt[n % 10];  | |
n /= 10;  | |
        } | |
    } | |
} | 
# T2. 找到最长的半重复子字符串
链接:https://leetcode.cn/problems/find-the-longest-semi-repetitive-substring/description/
# 解题思路
滑动窗口:
- 首先记录所有的重复位置
 - 对重复位置进行枚举统计(从第二个重复位置开始)
 
具体看代码注释
# 代码
class Solution {  | |
public int longestSemiRepetitiveSubstring(String s) {  | |
int n = s.length();  | |
if (n < 3) return n;  | |
        // 记录重复的位置下标 | |
int[] repeat = new int[n - 1];  | |
        // 重复位置下标的数量 | |
int cnt = 0;  | |
for (int i = 0; i < n - 1; ++i) {  | |
if (s.charAt(i) == s.charAt(i + 1)) {  | |
repeat[cnt++] = i;  | |
            } | |
        } | |
        // 只有一个重复位置,直接返回原字符串的长度 | |
if (cnt < 2) return n;  | |
        // 有 n-1 个重复位置,说明是相同字符串组成的字符串 | |
if (cnt == n - 1) return 2;  | |
        // 当前的起始位置 | |
int pre = 0;  | |
int ans = 0;  | |
        // 对重复位置进行枚举统计 | |
        // 从第二个重复位置开始(允许有一个重复位置存在) | |
for (int i = 1; i < cnt; ++i) {  | |
ans = Math.max(ans, repeat[i] - pre + 1);  | |
            // 跳过前一个重复的位置 | |
pre = repeat[i - 1] + 1;  | |
        } | |
        // 最后一段也要处理 | |
return Math.max(ans, n - pre);  | |
    } | |
} | 
# T3.
链接: