我们用每种字符代表一种宝石,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; } } } }