不申請變數和空間反轉字串

2021-09-09 02:57:59 字數 3777 閱讀 3802

要求:不申請變數和空間 反轉字串 ,用乙個函式實現。 異或^交換或者加減交換的典型應用! via 筆試題

基本思路:從 兩頭往中間做字元交換 。字串最後乙個字元是 '/0' ,表示結束,沒有實際意義,可以將它 當作中間變數 ,等處理完成後,再將最後乙個字元置 '/0' 即可

void reverse (char *s)

if(strlen(s) == 1) // 當為乙個字元時無需交換或奇數個

return;

if(*(s)) // 0 個或偶數個

*s = *s + *(s+strlen(s)-1);

*(s+strlen(s)-1) = *s - *(s+strlen(s)-1);

*s = *s - *(s+strlen(s)-1);

// 實現字串首末字元互換, 但加法可能會溢位

*(unsigned short*) (s+strlen(s)-1) = (*(s+strlen(s)-1))<<8;

// 把字串的最後乙個位元組往後移了一位, 利用了 0 = 『/0』

// 當然也可以利用上面交換字元的方法,不過移位利用了 0 = 『/0』 的效率更高

// 上面四步的本質是實現三個數兩兩互換,最簡單的是兩次兩兩互換

// 但是目前結尾符是已知的,直接把第乙個放到結尾處,最後乙個放第乙個,將

// 最後乙個用結尾符填上即可,只需三步,易於理解,前提是 有變數儲存字串的 // 長度

// 但是由於 不能申請臨時變數,移動了結尾符號後, strlen 函式就不能用 了

// 因此上述強制轉換的方式是唯一的

// 然後將去掉了首尾字元的新串傳進去,遞迴呼叫

reverse (s+1);

*(unsigned short*)(s+strlen(s)) = *(s+strlen(s)+1);

// 將 『/0』 逐步後移,還原更改後的子串

else

return;

圖示過程:字串 abcdef

s+1 = str = abcdef』/0』 abcdef』/0』 > fbcdea』/0』 > fbcde』/0』a

s+1 = str = bcde』/0 fbcde』/0』a > fecdb』/0』a > fecd』/0』ba

s+1 = str = cd』/0』 fecd』/0』ba > fedc』/0』ba > fed』/0』cba

s+1 = str =』/0』 ,遞迴返回,此時 s= cd』/0』 已經在上一步改為 d』/0』c > dc』/0』 > edcb』/0』 > fedcba』/0』

考慮串的長度為奇數的情況,當為奇數時,最後傳進去的 串長度為 1 ,此時無需互動 ,應該直接退出。 因此在入口處補上判斷奇偶的條件

if(strlen(s) == 1)

return;

當然也可以在遞迴呼叫前 判斷改動後的字串長度 if( strlen (str+ 1) >= 2 ) 時 ,才呼叫,可以消除奇數的影響

當原始字串為乙個時, 第一次就應該無任何處理的,所以在入口處判斷更合理哦

優化,不申請任何變數,支援鏈式操作,返回 char *

char * reverse (char *s)

if(strlen(s) == 1)

return s;

if(*(s))

*s = *s + *(s+strlen(s)-1);

*(s+strlen(s)-1) = *s - *(s+strlen(s)-1);

*s = *s - *(s+strlen(s)-1);

// 實現字串首末字元互換,但加法可能會溢位

*(unsigned short*)(s+strlen(s)-1) = (*(s+strlen(s)-1))<<8;

reverse (s+1);

*(unsigned short*)(s+strlen(s)) = *(s+strlen(s)+1);

return s; // 此句沒有,程式就錯了,因為遞迴的最外層是進入 if(*(s)) 的,此時無返回值

申請了 乙個變數儲存串的長度 ,一般面試這個程式就可以了,能寫出這個其實已經很牛 b 了,整上面那個, 估計別人開始懷疑是以前做過這個題目了,呵呵,還得裝傻點

char * reverse (char *s)

if(strlen(s) == 1)

return s;

if(*(s))

int len = strlen(s);

*(s+len) = *s;

*s = *(s+len-1);

*(s+len-1) = '/0';

// 首尾字元及結束符交換位置

// 去掉首尾字元後再遞迴呼叫

reverse (s+1);

//*(unsigned short*)(s+strlen(s)) = *(s+strlen(s)+1);

*(s+len-1) = *(s+len);

*(s+len) = '/0'; // 恢復原來改變後的串

return s;

將字串的最後乙個元素遞迴移動到隊頭,遞迴到達尾部,異或 ^ 交換,隊尾元素前移一格,返回上層,再次交換,最後即將隊尾移到隊頭

void tail2head(char* s)

if(strlen(s)==1)

return;

else if(strlen(s)==2)

s[0] = s[1]^s[0];

s[1] = s[1]^s[0];

s[0] = s[1]^s[0];

return;

else if(strlen(s)>2)

tail2head(s+1);

s[0] = s[1]^s[0];

s[1] = s[1]^s[0];

s[0] = s[1]^s[0];

遞迴一次移動隊尾至隊頭,更新隊頭至下乙個元素,再次呼叫 tail2head ,最後即可全部逆序

char* reverse(char *s)

if(strlen(s)>1)

tail2head(s);

reverse(s+1);

return s;

此法元素移動次數最多,但是思路比較清晰 ,另外整個功能用了兩個遞迴函式實現,打破了通常只有乙個介面函式的固定思維

main()

char streven[10] = "abcdef";

char strood[10] = "1234567";

char strone[10] = "1";

char strtwo[10] = "12";

printf("string 'abcdef' reversed is '%s'/n",reverse(streven));

printf("string '1234567' reversed is '%s'/n",reverse(strood));

printf("string '1' reversed is '%s'/n",reverse(strone));

printf("string '12' reversed is '%s'/n",reverse(strtwo));

return 0;

//string 'abcdef' reversed is 'fedcba'

//string '1234567' reversed is '765123?' 當串的長度為奇數時好像還有點問題

//string '1234567' reversed is '7654321' 補充了判斷條件後無誤

//string '1' reversed is '1'

//string '12' reversed is '21'

不申請新的空間,字串反轉

申請了 乙個變數儲存串的長度 一般面試這個程式就可以了,能寫出這個其實已經很牛 b 了,整上面那個,估計別人開始懷疑是以前做過這個題目了,呵呵,還得裝傻點 圖示過程 字串 abcdef s 1 str abcdef 0 abcdef 0 fbcdea 0 fbcde 0 a s 1 str bcde...

以單詞為單位反轉字串,要求不申請任何空間

問題描述 存在乙個可讀寫的字串,其中包括若干單詞,單詞間以空格區分,要求以單詞為單位對字串進行反轉。演算法思想 1 利用異或運算可以進行不申請空間進行字元交換 2 利用遞迴的思想 3 使用strchr函式區分單詞 解決方案 1 利用遞迴和異或運算進行字元交換,這一步將完成字串的整體反轉 遞迴進行字元...

字串反轉和句子反轉(字串逆序和句子逆序)

昨天乙個哥們面試,面試官給他出一道題 將字串反轉,如qwert,反轉為trewq 將乙個句子反轉,如do one thing,反轉為thing one do。首先,這個題目可以可以分為兩個題目來做。1 反轉字串。2 反轉句子。1 反轉字串 我這裡用了兩種方法 1 定義乙個反轉函式,裡面定義乙個beg...