劍指offer之字符串替換問題

題目一:函數將字符串中的字符‘※’號移到字符串的前部分,前面的非‘※’字符後移,但不能改變非字符的先後順序,函數返回串中非’*'字符的數量。(要求儘可能的佔用少的時間和輔助空間)。例如:原始串爲"au※※toc※※h※※i※ps",處理後爲"※※※※※※※autochips",函數返回9。

思路:使用倆個標記 i, j 都指向字符串的末尾,然後 i 往前走,若遇到非字符則將其位置的值拷到 j 位置,然後 i, j 同時向前移動, i 走完之後,將j位置到 i 之間的位置都賦爲※。

代碼如下:

//字符串問題:一個換一個
int MoveSignToFroat(char* str)
{
	assert(str != NULL);  //參數檢查
	if (str == NULL)
	{
		return -1; //錯誤返回-1
	}

	int count = 0, result = 0;
	int len = strlen(str);
	int i = len;
	int j = i;
	
	while (i >= 0)
	{
		if (str[i] != '*')
		{
			str[j--] = str[i];
		}
		i--;
	}

	while (j >= 0)  //賦值*
	{
		str[j--] = '*';
		count++;
	}

	result = len - count;

	return result;
}

測試用例:

void Print(char* str)
{
	for (int i = 0; i <= (int)strlen(str); i++)
	{
		printf("%c ", str[i]);
	}
	printf("\n");
}

int main()
{
	char ch[] = "au**toc**h**i*ps";
	int len = sizeof(ch) / sizeof(ch[0]);
	printf("原始串爲:");
	Print(ch);

	int result = MoveSignToFroat(ch);
	printf("原串裏面有%d個非*字符\n", result);

	printf("改變後爲:");
	Print(ch);
	
	return 0;
}

時間複雜度和空間複雜度分別爲:O(n),O(1)
測試結果:
在這裏插入圖片描述

題目二:將字符串中連續的※刪除,只保留一個※,例如,“a※b※※c※※※d”->"a b c d"

思路:使用倆個標記 i, j 都指向字符串的開始,判斷 i 位置和 i + 1 位置的值都是※嗎?,若是連續※,則 i 往後走,若不是連續※,則將 i 位置的值賦給 j 位置,最後結束後將 j 位置置爲’\0’.

代碼如下:

void DeleteMoreBlank(char *str)//O(n),O(1)
{
	int i = 0;
	int j = 0;
	for (; str[i] != '\0'; i++)
	{
		if (str[i] == '*'&& str[i + 1] == '*')    //連續空格
		{
			//什麼都不做
		}
		else       // 不是連續空格
		{
			str[j] = str[i];
			j++;
		}
	}
	str[j] = '\0';
}

測試用例:

int main()
{
	char str[] = "a*b**c***d";
	printf("原始串爲:");
	printf("%s\n", str);
	
	DeleteMoreBlank(str);
	
	printf("刪除後爲:");
	printf("%s ", str);

	return 0;
}

時間複雜度和空間複雜度分別爲:O(n),O(1)
測試結果:
VS2013環境下測試

題目三:請實現一個函數,把字符串中的每個空格替換成“%20"。例如輸入“We are happy.", 則輸出“We%20are%20happy"。

思路:若原字符串數組空間足夠大,遍歷字符串,可以得到空格的數目count和字符串的長度num,則替換後的總長度len = num + count * 2,然後使用 i 標記原字符串的最後一個字符,j標記len,然後str[len] = ‘\0’;字符串從後往前遍歷,若是字符,拷貝到 j 位置,若是空格,則 j 位置拷貝 ‘0’、‘2’、’%’,每次拷完 j–;

代碼如下:

void BlankToSign(char* str)
{
	int count = 0;  //統計空格的數量
	int i = 0;
	int j = 0;
	while (str != '\0')
	{
		if (str[i] == ' ')
		{
			count++;
		}
		i++;
	}

	j = i + count * 2;

	for (; i > 0; i--)
	{
		if (str[i] != ‘ ’)
		{
			str[j] = str[i];
			j--;
		}
		else
		{
			str[j--] = '0';
			str[j--] = '2';
			str[j--] = '%';
		}
	}
}

測試用例:

int main()
{
	char str[50] = "  We are happy!   ";
	printf("%s\n", str);
	BlankToSign(str);
	printf("%s\n", str);

	return 0;
}

測試結果:
VS2013環境下測試

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