题目详情
给定一个字符串,仅由a,b,c 3种小写字母组成。当出现连续两个不同的字母时,你可以用另外一个字母替换它,如
- 有ab或ba连续出现,你把它们替换为字母c;
- 有ac或ca连续出现时,你可以把它们替换为字母b;
- 有bc或cb 连续出现时,你可以把它们替换为字母a。
你可以不断反复按照这个规则进行替换,你的目标是使得最终结果所得到的字符串尽可能短,求最终结果的最短长度。
输入:字符串。长度不超过200,仅由abc三种小写字母组成。
输出: 按照上述规则不断消除替换,所得到的字符串最短的长度。
例如:输入cab,输出2。因为我们可以把它变为bb或者变为cc。
输入bcab,输出1。尽管我们可以把它变为aab -> ac -> b,也可以把它变为bbb,但因为前者长度更短,所以输出1。
public class Main {
private static int minLength=1;
public static int minLength(String s) {
s=s.replace("^(\\s+)|(\\s+)$","");
if(checkStr(s)){
changeStr(s,1);
}else{
try {
throw new Exception("输入的字符串不符合格式要求!");
} catch (Exception e) {
e.printStackTrace();
}
}
return minLength;
}
/**
* 每次取字符串的前三个字符进行递归操作
* <pre>
* 需判断操作的起始下标,如cccabacab的前三个字符为c,则保留前1个c,从ccabacab中取前三个操作。
* <pre>
* @param s
*/
public static void changeStr(String s,int startIndex){
if(s.length()<3){
if(s.length()==2){
String str=changeChar(s.charAt(0),s.charAt(1));
System.out.println(str);
minLength=str.length();
}
return;
}else{
String remainStr="";
if(startIndex==s.length()){
minLength=s.length();
return;
}
if(startIndex<3){
startIndex=0;
}else{
startIndex=startIndex-2;
remainStr=s.substring(0,startIndex);
}
char ch1=s.charAt(startIndex);
char ch2=s.charAt(startIndex+1);
char ch3=s.charAt(startIndex+2);
String new_ch=changeChar(ch2,ch3);
String newStr="";
//取前三个字符两两交换,初始时第二个与第三个
if(new_ch.length()==2){//如果交换的字符相等则必须交换另外两个
new_ch=changeChar(ch1,ch2);
newStr=remainStr+new_ch+ch3+s.substring(startIndex+3);
}else if(String.valueOf(ch1).equals(new_ch)){//如果交换后的字符与第一个相同,考虑第四个字符的情况
if(s.length()>3){
char ch4=s.charAt(startIndex+3);
if(ch4!=ch1){
newStr=remainStr+ch1+new_ch+s.substring(startIndex+3);
}else{
new_ch=changeChar(ch1,ch2);
newStr=remainStr+new_ch+ch3+s.substring(startIndex+3);
}
}else{
new_ch=changeChar(ch1,ch2);
newStr=remainStr+new_ch+ch3+s.substring(startIndex+3);
}
}else{
newStr=remainStr+ch1+new_ch+s.substring(startIndex+3);
}
startIndex=startIndex(newStr);
changeStr(newStr,startIndex);
}
}
/**
* 开始交换字母的起始下标
* <pre>
* 如:bbbbca 从第三个b开始操作,即前面的bb保留,操作bca
* <pre>
* @param s
* @return
*/
public static int startIndex(String s){
int startIndex=1;
char[] chs=s.toCharArray();
for(int i=1;i<chs.length;i++){
if(chs[i]!=chs[i-1]){
break;
}else{
startIndex++;
}
}
return startIndex;
}
public static String changeChar(char c1,char c2){
if((c2+c1)==195){
return String.valueOf((char)99);
}else if((c2+c1)==196&&c1!=c2){
return String.valueOf((char)98);
}else if((c2+c1)==197){
return String.valueOf((char)97);
}else{
return String.valueOf(new char[]{c1,c2});
}
}
public static boolean checkStr(String s){
if(s.equals("")||s==null){
return false;
}
char[] chs=s.toCharArray();
for(int i=0;i<chs.length;i++){
if(chs[i]=='a'||chs[i]=='b'||chs[i]=='c'){
continue;
}else{
return false;
}
}
return true;
}
public static void main(String[] agrs){
String s="abcbca" ;
//changeStr(s,1);
int mixLen=minLength(s);
System.out.println(minLength);
}
}
【2016-12-28 修改】:
dp - 分析:
字符串abc转换结果有 abc -> {cc,aa}
字符串abcb的转换结果分两种:
(1)在字符串abc的所有结果集的基础上合并,即有{cc(b),aa(b)} -> {b}
(2)另一种是字符串的ab(cb)转换 -> {aba}, {aba}的转换为在字符串ab上的集合的基础上转换,
字符aba的转换重复(1),(2)步骤,最终 abcb -> {aba} ->{b},所以字符串abcb ->{b}
(3) 合并(1),(2)的结果集,返回最终字符串abcb的所有合并结果,结果由容器去掉重复。
package com.davinci;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
public class MyTest {
public String getMergeStr(String str){
ArrayList<HashSet<String>> arrList = new ArrayList<HashSet<String>>();
HashSet<String> set = new HashSet<String>();
set.add(String.valueOf(str.charAt(0)));
arrList.add(set);
for(int i =1 ;i<str.length();i++){
HashSet<String> prevResult = arrList.get(i-1);
char prevChar = str.charAt(i-1);
char currChar = str.charAt(i);
HashSet<String> currentResult = transform(prevResult,currChar);
if(i-2 >=0 ){
HashSet<String> prevPrevResult = arrList.get(i-2);
if(prevChar != currChar){
String mergerStr = toMergeStr(String.valueOf(prevChar),currChar);
HashSet<String> result = transform(prevPrevResult,mergerStr.charAt(0));
currentResult.addAll(result);
}
}
arrList.add(i, currentResult);
}
//返回结果
HashSet<String> l = arrList.get(str.length()-1);
return Arrays.deepToString(l.toArray());
}
public HashSet<String> transform(HashSet<String> prevResult , char c){
HashSet<String> set = new HashSet<String>();
for(String str : prevResult){
String result = toMergeStr(str,c);
set.add(result);
}
return set;
}
/**
* 返回合并的字符
* <p>
* e.g "aaaa"字符串追加字符'b'后,经转换,最终得到的是"b"
*
* </p>
* @param str 由字符{a,b,c}组成
* @param c 字符 [a|b|c]
* @return
*/
public String toMergeStr(String str , char c){
int len = str.length();
char firstChar = str.charAt(0);
boolean isOdd = (len & 1)== 1 ? true : false;
if(c == firstChar){ //相同字符,添加后面
str = str + c ;
return str;
}else{
if(isOdd){ //奇位数
if((c +firstChar) == 195 ){ // a + b = 97 + 98
return String.valueOf((char)99);
}
if((c +firstChar) == 196 ){
return String.valueOf((char)98);
}
if((c +firstChar) == 197 ){
return String.valueOf((char)97);
}
}else{
return String.valueOf(c);
}
}
return str;
}
}
结果:
输入:bcab
结果:[b, bbb]
输入:cab
结果:[bb, cc]
输入:abcabc
结果:[cc, aa, aaaa, cccc]