關於一道題的思考

題目詳情

給定一個字符串,僅由a,b,c 3種小寫字母組成。當出現連續兩個不同的字母時,你可以用另外一個字母替換它,如


  1. 有ab或ba連續出現,你把它們替換爲字母c;
  2. 有ac或ca連續出現時,你可以把它們替換爲字母b;
  3. 有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]







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章