刪除字符

原題

刪除字符串中的“b”和“ac”,需要滿足如下的條件:

  1. 字符串只能遍歷一次

  2. 不能夠使用額外的空間

例如:

  1. acbac ==> ""

  2. aaac ==> aa

  3. ababac ==> aa

  4. bbbbd ==> d

進一步思考:如何處理aaccac呢,需要做哪些改變呢?

分析

首先要明白從字符串中刪除某些字符該如何實現,顯而易見我們可以把保留的字符拷貝新的字符串中來實現刪除。但是題目要求不能使用額外的空間。那就是將要刪除的字符全部交換到字符串的尾部,然後設置一個'\0'表示字符串的結尾。

其次,如果要刪除的都是單個字符的字符串,就很直接:我們使用i和j兩個變量遍歷字符串,i表示不會刪除的字符的位置,j從0開始,只要i所在位置的字符不是要刪除的字符,就str[j]=str[i](str表示字符串),然後j++指向下一個位置。一次遍歷即可,不需要額外申請空間,只需要兩個變量。

但是,現在刪除的字符串中有多個字符的,如:“ac”。那要如何處理呢?這裏介紹一個小技巧:狀態機。這裏,我們有兩個狀態:ONE和TWO。TWO表示,前一個字符時‘a’的狀態,其他的都用ONE表示。還是採用前面所描述的遍歷方法:

  1. 如果當前狀態爲ONE,則拷貝:str[j]=str[i];但如果當前字符滿足以下兩種狀態的任一個,則不進行拷貝:

    • 當前字符是‘a’,我們要考慮下一個字符是c

    • 當前字符是‘b’,因爲我們要刪除b

  2. 如果當前狀態爲TWO:

    • 當前字符不是‘c’,那麼我們要先拷貝前一個字符‘a’

    • 然後考慮當前字符,如果不是‘b’或者‘a’,則拷貝字符

狀態轉換非常簡單,就是每次都檢查,是前一個字符爲‘a’。基本代碼如下:

void stringFilter(char* str){
	bool state=false;//前一個不是‘a’
	unsigned int j=0;
	for(int i=0;str[i]!='\0';++i){
		if(!state&&str[i]!='a'&&str[i]!='b'){
			str[j]=str[i];
			j++;
		}
		if(state&&str[i]!='c'){
			str[j]='a';
			j++;
			if(str[i]!='a'&&str[i]!='b'){
				str[j]=str[i];
				j++;
			}
		}
		state=(str[i]=='a')?true:false;
	}
	if(state){
		str[j]='a';
		j++;
	}
	str[j]='\0';
}

調用:

<span style="color:#3e3e3e;">int _tmain(int argc, _TCHAR* argv[])
{
	char str[]="ababac";//這裏一定不能聲明爲char* str="ababac",會出現</span><span style="font-family: Consolas, 'Courier New', Courier, mono, serif; line-height: 18px;">寫入位置時發生衝突的錯誤</span><span style="color:#3e3e3e;">
	stringFilter(str);
	cout<<str;
	system("pause");
	return 0;
}</span>
上面不能那樣聲明的原因是:char* str="ababac"; str指向的是靜態存儲區,"ABCD"是位於常量區的,那麼這些值就不能被修改。指針str只是指向了這個位置(指針str存在棧中)。而char str[]="ababac"; 這個數組的存儲空間是在棧中開闢的,就是在棧中開闢了整個數組,用來存儲數組元素,所以,可以被修改。

下面進一步考慮: 根據上面的算法,我們考慮aaccac,最終得到ac。ac在題目中要求的也是要刪除的。是否要刪除這個ac,就需要和面試官進行交流了,無論如何,總是要考慮這種情況。還是採用上面的算法,怎麼解決刪除之後還可以刪除的情況?其實非常簡單,只需要做很小的修改,我們在循環最後加上這個代碼即可:

if(j>1&&str[j-2]=='a'&&str[j-1]=='c')
        j=j-2;

原文鏈接:http://mp.weixin.qq.com/s?__biz=MjM5ODIzNDQ3Mw==&mid=200437914&idx=1&sn=c69d73c76291562856f8221ecc491ac4#rd


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