首页 > 试题广场 >

彩色宝石项链

[编程题]彩色宝石项链
  • 热度指数:18796 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
有一条彩色宝石项链,是由很多种不同的宝石组成的,包括红宝石,蓝宝石,钻石,翡翠,珍珠等。有一天国王把项链赏赐给了一个学者,并跟他说,你可以带走这条项链,但是王后很喜欢红宝石,蓝宝石,紫水晶,翡翠和钻石这五种,我要你从项链中截取连续的一小段还给我,这一段中必须包含所有的这五种宝石,剩下的部分你可以带走。如果无法找到则一个也无法带走。请帮助学者找出如何切分项链才能够拿到最多的宝石。

输入描述:
我们用每种字符代表一种宝石,A表示红宝石,B表示蓝宝石,C代表紫水晶,D代表翡翠,E代表钻石,F代表玉石,G代表玻璃等等,我们用一个全部为大写字母的字符序列表示项链的宝石序列,注意项链是首尾相接的。每行代表一种情况。


输出描述:
输出学者能够拿到的最多的宝石数量。每行一个
示例1

输入

ABCYDYE
ATTMBQECPD

输出

1
3

发表于 2018-12-29 22:12:58 回复(0)
public class Rubine {
 public static void main(String[] args) {
  final String rubine = "AXBXCXDXEXXABXCXDXXABCDXEX";
  String str = rubine + rubine;
  String str2 = "ABCDXE";
  String result = cut(str, str2);
  System.out.println(result+"给王后");
  System.out.println("你可以拿走"+(str.length()-result.length())/2+"个");
 }
 static String cut(String str1, String str2) {
  int len = str1.length();
  int len2 = str2.length();
  String temp = null;
  for (int j = len2; j < len; j++) {
   for (int i = 0; i < len - len2; i++) {
    temp = str1.substring(i, i + j);
    if (temp.contains("A") && temp.contains("B") && temp.contains("C") && temp.contains("D")&& temp.contains("E")&& temp.contains("X")) {
     return temp;
    }
   }
  }
  return null;
 }
}
//
ABCDXE给王后
你可以拿走23个
发表于 2018-11-28 08:51:22 回复(0)
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;
    }
}
发表于 2018-08-25 18:20:39 回复(0)

根据题意截取处需要包含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;
    }
}
发表于 2018-08-06 15:41:00 回复(0)
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;
    }
}

发表于 2018-07-24 22:20:29 回复(0)
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;
    }
}

发表于 2018-06-14 19:46:16 回复(0)
最高赞答案已经说的很清楚,我按照他的思路写了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;
    }
}

发表于 2018-05-13 17:14:46 回复(0)

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;
    }

}
}

发表于 2018-05-11 13:43:35 回复(0)
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;
    }
}

发表于 2018-03-11 10:47:22 回复(0)
//将所有的包含五个宝石的子串找出来取最小值 简单粗暴
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String str = scanner.nextLine();
        LinkedList<Character> list = new LinkedList<>();
        for (Character character : str.toCharArray()) {
            list.add(character);
        }
        int min = list.size();
        for (int i = 0; i < list.size(); i++) {
            int temp = getLength(list);
            if(temp<min) {
                min=temp;
            }
            Character first = list.getFirst();//将头部转移到尾部
            list.addLast(first);
            list.removeFirst();
        }
        System.out.println(list.si***);    
    }

    private static int getLength(LinkedList<Character> list) {
        Map<Character, Boolean> map = new HashMap<>();
        map.put('A', false);
        map.put('B', false);
        map.put('C', false);
        map.put('D', false);
        map.put('E', false);
        int count = 0;
        LinkedList<Character> newList = new LinkedList<>();
        for (Character character : list) {
            if(map.get(character)!=null&&map.get(character)==false) {
                map.put(character, true);//已经找到的宝石就不再找了
                count++;
                newList.add(character);//从第一块子串宝石开始记录
                if(count>=5) {
                    //正好全部找齐
                    return newList.size();
                }
                continue;
            }
            if(count>0) {
                newList.add(character);//记录子串
            }
        }
        return 0;
}
}
发表于 2018-03-09 11:12:53 回复(0)
//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);
        }
    }
}

编辑于 2017-12-11 16:09:09 回复(0)

这道题可以当做环形字符串求最短子字符串问题,将输入的字符串相连然后在相连的字符串上进行查找,记录下每个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;
    }
}

编辑于 2017-12-03 15:40:41 回复(0)
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);
        }
    }
}

发表于 2017-11-28 01:11:02 回复(0)
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;   }
}
觉得做变成题首先一定要清晰的理解题目的意思,然后有个清晰的阶梯思路,只需要按照自己的思路来进行解题即可
发表于 2017-11-22 20:50:11 回复(0)
参考了一个大神的思路,直接使用暴力破解法,因为王后需要分割的那一份项链至少有五个宝石,因此可以从5开始到总长度进行遍历,然后在每次遍历从第一个宝石位置开始,连续取i个宝石串,组成一个子字符串,然后进行判断是否满足五种宝石全部都存在的条件,如果存在,则输入length-i即为最终的结果
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;
	}
}

发表于 2017-08-31 23:22:40 回复(2)
使用暴力
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;
			}
		}
	}
		
}
	



发表于 2017-08-28 02:42:10 回复(0)

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Main {

public static void main(String[] args) {
try (Scanner scanner = new Scanner(System.in)) {
Set<Character> set = new HashSet<>();
set.add('A');
set.add('B');
set.add('C');
set.add('D');
set.add('E');
while (scanner.hasNext()) {
char[] c = scanner.nextLine().toCharArray();
int min = c.length;
for (int j = 0; j < c.length; j++) {
if (!set.contains(c[j]))
continue;
int i = j;
Set<Character> nowFound = new HashSet<>();
do {
if (!set.contains(c[i]) || nowFound.contains(c[i]))
continue;
nowFound.add(c[i]);
if (nowFound.size() == 5) {
int len = ((i-j+c.length)%c.length)+1;
if (len < min)
min = len;
}
} while ((i = (i + 1) % c.length) != j);
if(min==5)break;
}
System.out.println(c.length - min);
}
}
}

}

发表于 2017-08-14 20:53:00 回复(0)