給定一個字符串,僅由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]