我们用每种字符代表一种宝石,A表示红宝石,B表示蓝宝石,C代表紫水晶,D代表翡翠,E代表钻石,F代表玉石,G代表玻璃等等,我们用一个全部为大写字母的字符序列表示项链的宝石序列,注意项链是首尾相接的。每行代表一种情况。
输出学者能够拿到的最多的宝石数量。每行一个
ABCYDYE ATTMBQECPD
1 3
import java.util.Scanner;
/**
* 维护窗口包含5种字母
*arr数组记录窗口5种宝石数量
*/
public class Main {
static int[] arr;
public static void main(String[] args) {
Scanner sc= new Scanner(System.in);
while (sc.hasNext()) {
String s=sc.nextLine();
System.out.println(cal(s));
}
sc.close();
}
private static int cal(String s) {
if (s.length()<=5)
return 0;
arr=new int[5];
char[] str=(s+s).toCharArray();
int min=str.length;
int begin=0;
for (int i = 0; i < str.length; i++) {
int index=str[i]-'A';
if (index<5) {
arr[index]++;
}
while (begin<i) {
int beginC=str[begin]-'A';
//begin指向的非A-E
if (beginC>=5) {
begin++;
}else if (arr[beginC]>1) {//begin指向的字母数量足够
begin++;
arr[beginC]--;
}else{
break;
}
}
//判断窗口是否符合条件
if (IsWindowOk()) {
int newLen=i-begin+1;
if (min>newLen)
min=newLen;
}
}
if (min>=s.length())
return 0;
return s.length()-min;
}
private static boolean IsWindowOk() {
for (int i = 0; i < 5; i++) {
if (arr[i]<1)
return false;
}
return true;
}
}
根据题意截取处需要包含A-E五种字符,可以不连续。如ABCYDYE,因为是首尾相连所以可以组成一个字符为EABCYD的串,也就是在Y处截断,最多拿走Y这个宝石。
暴力遍历法基本思路:视每一个字符索引位都为起始点,进行遍历查询,每一轮遍历记录是否达到5个字符包含,如果以包含判断当前索引位与当前起始点的距离即为再多数量。
import java.util.Scanner;
public class MaxGem {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String data = sc.next();
int [] containNum=new int[5];
int max=0;
for(int i=0;i<data.length();i++)
{
int j=i;
for(int z=0;z<data.length();z++)
{
int index = (j++) % data.length();
char c = data.charAt(index);
if(c=='A') containNum[0]=1;
else if(c=='B') containNum[1]=1;
else if(c=='C') containNum[2]=1;
else if(c=='D') containNum[3]=1;
else if(c=='E') containNum[4]=1;
if(checkIsAllContain(containNum) && ((data.length()-1)-z)>max)
{
max=(data.length()-1)-z;
}
}
containNum=new int[5];
}
System.out.println(max);
}
public static boolean checkIsAllContain(int[] containNum)
{
for(int i:containNum)
{
if(i==0)
{
return false;
}
}
return true;
}
}
public static int getnum(String str){
char[] ch = str.toCharArray();
int length = ch.length;
StringBuffer sf = new StringBuffer();
String s;
int result = length;
for(int l=0,r=0;l<length;){
s = sf.toString();
if(s.contains("A") && s.contains("B") && s.contains("C") && s.contains("D") && s.contains("E")){
result = Math.min(s.length(),result);
if(s.length() == 5){
return length - 5;
}
sf.deleteCharAt(0);
l++;
}else{
sf.append(ch[r%length]);
r++;
}
}
return length - result;
}
}
import java.util.*;
public class Main {
public static Character[] mCharacters = new Character[]{'A', 'B', 'C', 'D', 'E'};
public static HashSet<Character> sHashSet = new HashSet(Arrays.asList(mCharacters));
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String string = scanner.next().toUpperCase();
char[] chars = string.toCharArray();
ArrayList<Character> arrayList = new ArrayList<>();
for (int i = 0; i < chars.length; i++) {
arrayList.add(chars[i]);
}
// System.out.println(sHashSet);
// System.out.println(arrayList.containsAll(sHashSet));
System.out.println(arrayList.size() - getMinLenContainA2E(arrayList));
}
static int sfrom, sto;
public static int getMinLenContainA2E(ArrayList<Character> arrayList) {
int charLen = arrayList.size();
if (!arrayList.containsAll(sHashSet)) {
return charLen;
}
//为了方便,将arrayList扩充1倍
ArrayList<Character> theList = new ArrayList<>();
theList.addAll(arrayList);
theList.addAll(arrayList);
HashSet<Character> currSet = (HashSet<Character>) sHashSet.clone();//表示当前缺少的A2E字符
HashMap<Character, Integer> currMap = new HashMap<>();//表示当前子串A2E分别出现的次数
for (Character c :
currSet) {
currMap.put(c, 0);
}
int minLen = Integer.MAX_VALUE;
int from = 0, to = 0;
char ch = arrayList.get(to);
if (sHashSet.contains(ch)) {//属于A2E
currSet.remove(ch);
currMap.put(ch, currMap.get(ch) + 1);
}
while (from < charLen) {
while (!currSet.isEmpty()) {//当前子串不满足,to右移
to++;
ch = theList.get(to);
if (sHashSet.contains(ch)) {//属于A2E
currSet.remove(ch);
currMap.put(ch, currMap.get(ch) + 1);
}
}
// while (currMap.get((ch = theList.get(from))) > 1) {//说明可以删除
// from++;
// currMap.put(ch, currMap.get(ch) - 1);
// }
//改写上面的
for (int i = 0; i < theList.size(); i++) {
ch = theList.get(from);
if (!sHashSet.contains(ch)) {//不属于A2E,可以直接删
from++;
} else if (sHashSet.contains(ch) && currMap.get(ch) > 1) {//属于A2E且可以删除
from++;
currMap.put(ch, currMap.get(ch) - 1);
} else {
//== 1 删除from处字符会导致不满足
break;
}
}
int currLen = to - from + 1;
if (currLen < minLen) {
minLen = currLen;
sfrom = from;//记录一下吧
sto = to;//用于得到最短子串
}
from++;//删除原from处字符会导致不满足
currSet.add(ch);
currMap.put(ch, 0);
}
return minLen;
}
}
最高赞答案已经说的很清楚,我按照他的思路写了java版本的代码,更明了一点吧
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Scanner;
public class Main {// Main
public static void main(String[] args) throws FileNotFoundException {
// File f = new
// File("E:\\Users\\Administrator\\eclipse-workspace\\shiXi\\src\\common\\inputFile.txt");
// Scanner sc = new Scanner(f);
Scanner sc = new Scanner(System.in);
Solution solu = new Solution();
while (sc.hasNextLine()) {//输入字符串
String string = sc.nextLine();
int res = solu.helper(string);
System.out.println(res);
}
}
}
class Solution{
/**
* 还给皇后的宝石,必须包含5种中的每一种,每一种的数量只要大于等于1
*
* 尺取法,比全完暴力解O(n^2),更快O(n)
*
* 完全暴力解也是s+s两边连起来
* @param
* @return
*/
public int helper(String s) {
s=s+s;//环的问题,考虑变成两个连续的处理
HashMap<Character, Integer> map=new HashMap<>();
int start=0,end=0,count=0;//count是那5种宝石已经有的种类数量
int res=Integer.MAX_VALUE;//res是最短给皇后的,len-res就是最多给学者的
while(true) {
while(end< s.length() && count < 5 ) {
char c=s.charAt(end);
if(c == 'A' || c == 'B' || c == 'C' || c == 'D' || c == 'E' ) {
if(!map.containsKey(c)) {
count++;
}
map.put(c, map.getOrDefault(c, 0)+1);
}
end++;
}
if(count<5) {
break;
}
res=Math.min(res, end-start);//计算长度,
//要移动start了
char c2=s.charAt(start);//start这个位置的字符
if(c2=='A' || c2 == 'B' || c2 == 'C' || c2 == 'D' || c2 == 'E' ) {
if(map.containsKey(c2)) {//如果map里面还有c2
if(map.get(c2) == 1) {//如果只剩一个了
count--;
map.remove(c2);
}else {
map.put(c2, map.get(c2)-1);
}
}
}
start++;
}
return s.length()/2-res;
}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
while(sc.hasNextLine()) {
String s=sc.nextLine();
System.out.println(minshi(s));
}
}
public static int minshi(String s) {
char[] arr=s.toCharArray();
int Min=Integer.MAX_VALUE;
int min=Integer.MAX_VALUE;
for(int i=0;i<arr.length;i++) { //i为首部位置
for(int j=i+4;j-i<arr.length;j++) { //j为尾部位置,因取5种,所以从第五位开始遍历
ArrayList<Character> list=new ArrayList<>();
for(int k=i;k<=j;k++) { //将i到j之间数放入表中。
list.add(arr[k%arr.length]);}
if(list.contains('A')&&list.contains('B')&&list.contains('C')&&list.contains('D')&&list.contains('E')) {
min=list.size(); //取除第一次凑齐时的长度。
break;
}
}
Min=Math.min(Min, min); //从不同头部取最小。
}
if(Min==Integer.MAX_VALUE) {
return 0;
}else {
return arr.length-Min;
}
}
}
import java.io.*;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;
public class Main {
//fixed code
static Scanner in;
static PrintWriter out;
static Long startTime = null;
static final int mod = (int) 1e9 + 7;
static final int inf = 0x3f3f3f3f;
static final long inff = 0x3f3f3f3f3f3f3f3fL;
static final int maxn = (int) 1e6 + 5;
//fixed code
public static void main(String[] args) throws Exception {
//Test.main();
try {
System.setIn(new FileInputStream("night_input"));
startTime = System.currentTimeMillis();
} catch (FileNotFoundException e) {
}
in = new Scanner(new BufferedInputStream(System.in));
out = new PrintWriter(new BufferedOutputStream(System.out));
/////////////////////////////////////////////
while (in.hasNext()) {
String zb = in.next();
char[] str = (zb+zb).toCharArray();
Deque<Character> ch = new ArrayDeque<>();
Deque<Integer> loc = new ArrayDeque<>();
int[] cnt = new int[128];
Arrays.fill(cnt, 0);
int ans = inf;
for (int i = 0; i < str.length; ++i) {
if (str[i] <= 'E') {
++cnt[str[i]];
ch.offerLast(str[i]);
loc.offerLast(i);
while (check(cnt)) {
ans = Math.min(ans, loc.peekLast() - loc.peekFirst() + 1);
cnt[ch.pollFirst()]--;
loc.pollFirst();
}
}
}
out.println(ans == inf ? 0 : str.length - ans - zb.length());
}
////////////////////////////////////////////
out.flush();
if (startTime != null) {
out.println("\ntime: " + (System.currentTimeMillis() - startTime) + " (ms)");
}
in.close();
out.close();
}
static boolean check(int[] cnt) {
for (char i = 'A'; i <= 'E'; ++i) {
if (cnt[i] <= 0) return false;
}
return true;
}
} //Mark下此题:将字符串连接,直接正则筛选含ABCDE(无顺序)最小字符串即可
//求正则大神解答
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
String str = in.nextLine();
String strs = str + str;
int left = 0, right = str.length();
int min = right - left;
while (right < strs.length()) {
HashMap<Character, Integer> map = new HashMap<>();
for (int i = left; i < right; i++) {
if (strs.charAt(i) == 'A' || strs.charAt(i) == 'B' || strs.charAt(i) == 'C' ||
strs.charAt(i) == 'D' || strs.charAt(i) == 'E') {
Integer count = map.get(strs.charAt(i));
map.put(strs.charAt(i), count == null? 1: count+1);
}
}
if (map.size() == 5 && right - left >= 5) {
if (min > right - left)
min = right - left;
left++;
} else {
right++;
}
}
System.out.println(str.length() - min);
}
}
}
这道题可以当做环形字符串求最短子字符串问题,将输入的字符串相连然后在相连的字符串上进行查找,记录下每个A、B、C、D、E的最新出现位置,一旦五个字符全部出现,就开始计算其分割长度,记录其切割最小的长度,(也就是能得到最多宝珠的长度),最后输出时记得查询字符串的长度是原先长度的一半
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
String bracelet = in.next();
bracelet = bracelet + bracelet;
int poi[] = new int[5];
Arrays.fill(poi,-1);
int most = 0;
for(int i=0;i<bracelet.length();i++){
if(bracelet.charAt(i)-'A'<5){
poi[bracelet.charAt(i)-'A']=i;
}
if(check(poi)){ int max =0; int min =Integer.MAX_VALUE; for(int j=0;j<5;j++){ max = Math.max(max,poi[j]); min = Math.min(min,poi[j]); } most = Math.max(bracelet.length()/2-(max-min),most); }
}
System.out.println(most-1);
}
public static boolean check(int[] array){
for(int i=0;i<array.length;i++){
if(array[i]==-1){
return false;
}
}
return true;
}
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextLine()) {
String s = sc.nextLine();
if(s == null || s.equals("")) break;
List<String> list = Arrays.asList("A", "B", "C", "D", "E");
int length = s.length();
for (int i = 0; i < s.length(); i ++) {
List<String> temp = new ArrayList<>(list);
int current_length = 0;
for (int step = 0, index = i; step < s.length(); step ++, index = (index + 1) % s.length()) {
if(temp.size() == 0) break;
if(temp.contains(s.charAt(index) + "")) temp.remove(s.charAt(index) + "");
current_length ++;
}
if(current_length != 0) length = Math.min(length, current_length);
}
System.out.println(s.length() - length);
}
}
}
import java.util.Scanner; public class Main { public static void main(String args[]) { Scanner scanner = new Scanner(System.in); while (scanner.hasNext()) { String string = scanner.nextLine(); int min = 0; for (int i = string.length() - 1; i >= 0; i--) { if (string.charAt(i) == 'A' || string.charAt(i) =='B' || string.charAt(i) == 'C' || string.charAt(i) == 'D' || string.charAt(i) == 'E') { if (result(i, string) > min) { min = result(i, string); } } } System.out.println(min); } } private static int result(int index, String string) { string = normalize(index,string); int indexA = find('A', string); int indexB = find('B', string); int indexC = find('C', string); int indexD = find('D', string); int indexE = find('E', string); int min = indexA; min = Math.min(min, indexB); min = Math.min(min, indexC); min = Math.min(min, indexD); min = Math.min(min, indexE); return min; } private static String normalize(int index, String string) { StringBuffer sb = new StringBuffer(); sb.append(string); String string1 = sb.substring(index + 1, string.length()); String string2 = sb.substring(0, index + 1); sb.replace(0, sb.length(), string1 + string2); return sb.substring(0, sb.length()); } private static int find (char c, String string) { for (int i = string.length() - 1; i >= 0; i--) { if (string.charAt(i) == c) { return i; } } return -1; } }觉得做变成题首先一定要清晰的理解题目的意思,然后有个清晰的阶梯思路,只需要按照自己的思路来进行解题即可
import java.util.Scanner;
public class StringUtil {
//彩色宝石项链
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while(in.hasNext()){ //window输入ctrl+z结束,linux输入ctrl+A结束
String str = in.nextLine();
System.out.println(mine(str));
}
in.close();
}
//返回最多得到的宝石个数
public static int mine(String str) {
char[] arr = str.toCharArray();
int len = arr.length;
for(int i=5; i<len; i++){
for(int j=0; j<len; j++){
StringBuffer temp = new StringBuffer();
for(int k=j; k<j+i; k++){
temp.append(arr[k % len]);
}
String res = temp.toString();
if(res.contains("A") && res.contains("B") && res.contains("C") && res.contains("D") && res.contains("E")){
return len-i;
}
}
}
return 0;
}
} 使用暴力
import java.util.Scanner;
public class MainQiuZhao {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
System.out.println(getRes(cin.nextLine()));
}
public static int getRes(String str){
int len = str.length();
int res = Integer.MAX_VALUE;
if (len < 5) {
return 0;
} else {
//mStr解决循环问题
String mStr = str + str;
int length = mStr.length();
for (int i = 0; i < length - 5; i++) {
for (int j = i + 5; j <= length; j++) {
String tmp = mStr.substring(i, j);
if (tmp.contains("A") && tmp.contains("B")
&& tmp.contains("C") && tmp.contains("D")
&& tmp.contains("E")) {
res = Math.min(res, tmp.length());
//如果切割的目标长度为5直接返回,已经是最优
if(res==5){
return len-res;
}
//找的符合条件的子串,就跳出第二层循环
//因为后面的串长度会大于当前找到的子串
break;
}
tmp = null;
}
}
if (res != Integer.MAX_VALUE) {
return len - res;
} else {
return 0;
}
}
}
}