- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
java解法
- 解题思路
- 问题描述:
给定一个只包含字符 A、S、D、W 的字符串,找到一个最短子串,移除该子串后剩下的字符串中这四种字符的数量相等。
方法:
统计字符数量:先统计字符串中 A、S、D、W 各字符的数量。
计算超出部分:确定每种字符需要移除的多余数量,如果字符数量没有超标,直接返回 0。
滑动窗口:利用滑动窗口技术,动态调整子串范围,寻找满足条件的最短子串:
右边界扩展窗口,直到包含所有多余字符;
左边界收缩窗口,尝试找到更短的符合条件的子串。
滑动窗口关键点:
窗口内的字符数量动态变化,满足条件的窗口是:count 数组中所有值小于等于 0。
每次满足条件时,记录当前窗口长度并继续收缩。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println(minReplacementLength(scanner.next()));
}
public static int minReplacementLength(String moves) {
int[] count = new int[4];
for (char move : moves.toCharArray()) {
count[getIndex(move)]++;
}
int avg = moves.length() / 4;
int requiredSteps = 0;
for (int i = 0; i < 4; i++) {
count[i] -= avg;
if (count[i] > 0) {
requiredSteps += count[i];
} else {
count[i] = 0;
}
}
if (requiredSteps == 0) return 0;
int left = 0, right = 0, minLength = moves.length() + 1;
while (right < moves.length()) {
count[getIndex(moves.charAt(right))]--;
while (isBalanced(count)) {
minLength = Math.min(minLength, right - left + 1);
count[getIndex(moves.charAt(left))]++;
left++;
}
right++;
}
return minLength;
}
private static int getIndex(char move) {
switch (move) {
case 'A': return 0;
case 'S': return 1;
case 'D': return 2;
case 'W': return 3;
default: return -1;
}
}
private static boolean isBalanced(int[] count) {
for (int c : count) {
if (c > 0) return false;
}
return true;
}
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
C++解法
- 解题思路
- 问题描述
给定一个由字符 W、A、S 和 D 组成的字符串,要求找到一个最短的子串,移除该子串后,剩余字符串中这四种字符的数量均相等。
方法
统计字符总数:首先统计字符串中每个字符 W、A、S 和 D 的数量。
判断是否已经满足条件:如果所有字符的数量已经相等,直接返回 0。
滑动窗口:
用两个指针 left 和 right 表示窗口的左右边界。
窗口右边界向右扩展,减少窗口内字符的数量。
当窗口内的字符数量满足条件(即剩余字符串中所有字符的数量不超过目标值)时,尝试收缩窗口,寻找更短的子串。
关键点
每次窗口内字符数量发生变化时,判断是否满足剩余字符串中字符均衡的条件。
保持窗口动态变化,直到遍历整个字符串。
#include
#include
#include
using namespace std;
int find_min_replacement(string &s) {
unordered_map<char, int> count;
int n = s.size();
int required = n / 4;
for (char c : s) {
count[c]++;
}
if (count['W'] == required && count['A'] == required &&
count['S'] == required && count['D'] == required) {
return 0;
}
int left = 0, right = 0;
int min_len = n;
while (right < n) {
count[s[right]]--;
while (count['W'] <= required && count['A'] <= required &&
count['S'] <= required && count['D'] <= required) {
min_len = min(min_len, right - left + 1);
count[s[left]]++;
left++;
}
right++;
}
return min_len;
}
int main() {
string s;
cin >> s;
cout << find_min_replacement(s) << endl;
return 0;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
C解法
更新中
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
JS解法
更新中
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
注意:
如果发现代码有用例覆盖不到的情况,欢迎反馈!会在第一时间修正,更新。
解题不易,如对您有帮助,欢迎点赞/收藏
评论记录:
回复评论: