剑指offer面试题4:替换空格和合并两个有序数组

17 篇文章 0 订阅

题目:请实现一个函数,把字符串中的每个空格替换成20%。例如:输入“We are happy.” 输出“We20%are20%happy


看完题目会想到,原来一个空格字符,替换后变成‘2’、‘0’、‘%’三个字符,意味着字符串变长。

有两种解决方案:

一:创建新的字符串并在新的字符串上做替换,我们可以分配足够多的内存。

二:在原来的字符串上做替换,那么就有可能覆盖修改在该字符串后面的内存。


这里我们在原来的字符串上做替换,并且保证输入的字符串后面有足够多的空余内存。

一般比较直观的做法是从头开始扫描字符串,每一次碰到空格字符时做替换。由于是将一个字符替换成三个字符,必须将空格后的字符向后移两个字节,防止被覆盖。


而按照这种做法,每替换一次空格都要从头遍历一次,并且移动后面的字符,显然这种方法是不合适、效率很低。

假设字符串的长度是n,对每个空格字符,需要移动后面O(n)个字符,因此对含有O(n)个空格字符而言总的时间效率是O(n^2)


这样我们就需要寻求高效的做法。我们可以先遍历一遍一次字符串,统计出空格字符个数,并由此计算出替换后字符串的总长度。然后从字符串的后面开始复制和替换。


经分析,所有的字符都只复制一次,因此这个算法的时间效率是O(n)。

具体实现代码:

void ReplaceBlank(char string[], int length)
{
	if (NULL == string || length <= 0)
	{
		return;
	}

	int stringlen = 0;
	int Blank = 0;
	int i = 0;
	while (string[i] != '\0')
	{
		if (string[i] == ' ')
			Blank++;
		i++;
	}
	//记录原始字符串长度
	stringlen = i;
	int NewLength = stringlen + Blank * 2;

	if (NewLength > length)
		return;

	while (stringlen >= 0 && NewLength > stringlen)
	{
		if (string[stringlen] == ' ')
		{
			string[NewLength--] = '%';
			string[NewLength--] = '0';
			string[NewLength--] = '2';
		}
		else
		{
			string[NewLength--] = string[stringlen];
		}
		stringlen--;
	}
}

相关类型:

有两个排序的数组A1,A2 内存在A1末尾有足够多的空余空间容纳A2。实现一个函数,把A2的所有数字插入到A1中并且所有的数字是排序的。

思路很简单,从尾到头比较A1和A2中的数字,并把较大的数字复制到A1合适的位置。

实现代码:

//合并两个有序数组
#include<stdio.h>
#include<stdlib.h>

int* MergeArray(int* arr1, int* arr2,int length1,int length2)
{
	if (NULL == arr1 || NULL == arr2 )
		return 0;

	int Len = length1 + length2 - 1;
	length1--;
	length2--;
	while (length1 >= 0 && length2 >= 0)
	{
		if (arr1[length1] < arr2[length2])
		{
			arr1[Len--] = arr2[length2--];
			//length2--;
		}
		else
		{
			arr1[Len--] = arr1[length1--];
		}
		
	}
	if (length1 >= 0)
	{
		while (length1>=0)
		{
			arr1[Len] = arr1[length1--];
			Len--;
		}
	}
	else if (length2 >= 0)
	{
		while (length2>=0)
		{
			arr1[Len] = arr2[length2--];
			Len--;
		}
	}
	return arr1;
}

void display(int arr[],int num)
{
	for (int i = 0; i < num; i++)
	{
		printf("%d ", arr[i]);
	}
}

int main()
{
	int Arr1[20] = {3, 5, 7, 9, 11, 15 };
	int Arr2[7] = { 2, 4, 6, 8, 10, 13, 16 };

	MergeArray(&Arr1, &Arr2, 6, 7);
	display(Arr1, sizeof(Arr1) / sizeof(Arr1[0]));
	system("pause");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值