英雄会-字符串消除

题目要求:

    给定一个字符串,仅由a,b,c 3种小写字母组成。当出现连续两个不同的字母时,你可以用另外一个字母替换它,如 有ab或ba连续出现,你把它们替换为字母c; 有ac或ca连续出现时,你可以把它们替换为字母b; 有bc或cb 连续出现时,你可以把它们替换为字母a。 你可以不断反复按照这个规则进行替换,你的目标是使得最终结果所得到的字符串尽可能短,求最终结果的最短长度。

题目分析:

     输入:字符串。长度不超过200,仅由abc三种小写字母组成。 输出: 按照上述规则不断消除替换,所得到的字符串最短的长度。 例如:输入cab,输出2。因为我们可以把它变为bb或者变为cc。 输入bcab,输出1。尽管我们可以把它变为aab -> ac -> b,也可以把它变为bbb,但因为前者长度更短,所以输出1。

    在字符串消除的过程中关键在于处理类似:acbb的情况,这种情况下,不能简化为bbb而应该是aab。遇到这种情况我们可以分两种情况处理:首先,找到第一个与其后面字符不一致的字符,记录该字符的位置,并执行替换操作,得到子串(1)。其次,从第一次得出的字符位置后面一个开始查找与其不一致的字符,若没有找到不一致的字符,则递归对字符串(1)处理,如果找到这样一个位置则得出子串(2)。从第一次查找到的字符的位置后一个位置开始比较子串(1)和(2)。取相同字符少的子串进行处理。依次递归,直到子串中所有的字符都相同的时候,返回最终子串的长度。

    举例:1>输入acbb,第一个与其后面字符不一致的字符为a,索引为0,替换得到子串1:bbb

                2>从步骤1>中a的索引后面一个位置也就是c开始查找与c字符不一致字符的位置,找到了b字符,替换得到子串2:aab

                3>从第一个查找到的字符位置后一个位置开始比较子串(1)和(2),这里也就是0的后面就是1的位置开始比较,子串1为bb,子串2为ab从而舍弃相同字符比较多的bbb

                4>递归对(3)得到的子串处理直到字符串所有字符都相等的时候。

示例代码:

查找替换:

char turn ( char c1 , char c2 )
{
   return 'a' + 'b' + 'c' - c1 - c2 ;
}

void reduce( char * st , char * ss , unsigned i )
{
   strncpy( st , ss , i );
   st[i] = turn ( ss[i] , ss[i+1] );
   strcpy( st + i + 1 , ss + i + 2 );
}

int swap_str(char *pcStr, char* psDst, int nIndex)
{

	while(pcStr[nIndex] != '\0' && pcStr[nIndex + 1] != '\0')
	{
		if(pcStr[nIndex] != pcStr[nIndex + 1])
		{
			reduce(psDst, pcStr, nIndex);
			break;
		}
		nIndex++;
	}
	if(pcStr[nIndex] != '\0')
	{
		return (nIndex);
	}
	else
	{
		return -1;
	}
}

计算相同字符个数:

int count_same_chars(const char* str)
{
	if(str != NULL)
	{
		int nCount = 0;
		char c = *str;
		
		while((*str != '\0') && (c == *str))
		{
			str++;
			nCount++;
		}
		return (nCount);
	}	
	return (-1);
}

min_length函数:

int min_length(const char* str)
{
	int nCount = 0;	
	int nIndex = 0;
	char acSubStr1[256] = {0};
	char acSubStr2[256] = {0};
		
	printf("string :%s\n", str);
	nCount = count_same_chars(str);

	if(nCount == strlen(str))
	{
		return (nCount);
	}	

	nIndex = swap_str(str, acSubStr1, 0);
	if(nIndex >= 0)
	{
		swap_str(str, acSubStr2, nIndex + 1);
	}

	if(acSubStr2[0] == '\0')
	{
		return (min_length(acSubStr1));
	}
	else if(count_same_chars(acSubStr1 + nIndex + 1) >  count_same_chars(acSubStr2 + nIndex + 1))
	{
		return (min_length(acSubStr2));
	}
	else
	{
		return (min_length(acSubStr1));
	}
	return (-1);	
}

测试输出:

int main()
{
	int nIndex= 0;
	char *test[] = {
	"abc",
	"bacb",
	"bbb",
	"acbb",
	"acbbb",
	};

	for(nIndex = 0; nIndex < sizeof(test)/sizeof(test[0]); nIndex++)
	{
		min_length(test[nIndex]);
		printf("\n");
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值