题目要求:java
有一条彩色宝石项链,是由不少种不一样的宝石组成的,包括红宝石,蓝宝石,钻石,翡翠,珍珠等。有一天国王把项链赏赐给了一个学者,并跟他说,你能够带走这条项链,可是王后很喜欢红宝石,蓝宝石,紫水晶,翡翠和钻石这五种,我要你从项链中截取连续的一小段还给我,这一段中必须包含全部的这五种宝石,剩下的部分你能够带走。若是没法找到则一个也没法带走。请帮助学者找出如何切分项链才可以拿到最多的宝石。数组
输入描述:app
咱们用每种字符表明一种宝石,A表示红宝石,B表示蓝宝石,C表明紫水晶,D表明翡翠,E表明钻石,F表明玉石,G表明玻璃等等,咱们用一个所有为大写字母的字符序列表示项链的宝石序列,注意项链是首尾相接的。每行表明一种状况。
输出描述:spa
输出学者可以拿到的最多的宝石数量。每行一个
示例1code
ABCYDYE ATTMBQECPD
1
3
初步的解法:求包含ABCDE的最短的子串。首尾相连是为了不环处理。ip
package snippet; import java.util.Scanner; public class Snippet { public static void main(String[] args) { Scanner in = new Scanner(System.in); while (in.hasNext()) { StringBuffer buff = new StringBuffer(in.nextLine()); buff.append(buff); char s[] = buff.toString().toCharArray(); int length = s.length; int num[] = new int[5]; int min = length / 2; for (int i = 0; i <= length / 2 - 1; i++) { int count = 0; if (s[i] >= 'F') continue; else { for (int j = i; j <= length / 2 + i - 1; j++) { int temp = (int) (s[j] - 'A'); if (temp < 5 && num[temp] == 0) { num[temp]++; count++; } if (count == 5) { min = Math.min(min, j - i + 1); for (int k = 0; k < 5; k++) { num[k] = 0; } break; } } } } System.out.println(length / 2 - min); } } }
本身的代码中,利用一个整形数组来存放5种目标宝石是否存在的标志,能够进一步减小空间复杂度,利用boolean数组,减小为5个字节;进一步减小能够利用1个整形数值的5个2进制位来表示是否存在。get
package snippet; import java.util.Scanner; public class Souhu2 { public static void main(String[] args) { Scanner in = new Scanner(System.in); while (in.hasNext()) { StringBuffer buff = new StringBuffer(in.nextLine()); buff.append(buff); //省去环处理 char s[] = buff.toString().toCharArray(); int length = s.length; int min = length / 2; for (int i = 0; i <= length / 2 - 1; i++) { int count = 0; if (s[i] >= 'F') continue; else { for (int j = i; j <= length / 2 + i - 1; j++) { int num = (int) (s[j] - 'A'); if (num < 5) count |= 1 << num; if (count == 31) { min = Math.min(min, j - i + 1); break; } } } } System.out.println(length / 2 - min); } } }
Sourceit