其他分享
首页 > 其他分享> > LeetCode-241题-C语言实现

LeetCode-241题-C语言实现

作者:互联网

1. 原题题目

【题目来源:LeetCode第241题】给定一个含有数字和运算符的字符串,为表达式添加括号,改变其运算优先级以求出不同的结果。你需要给出所有可能的组合的结果。有效的运算符号包含 +, - 以及 * 。
如给定字符串: 2+1-1,有如下两种计算方法 ((2+1)-1) = 2 和 (2+(1-1)) = 2,则程序输出结果应该是[2,2]

2 题目分析

由于原问题比较复杂,因此考虑能不能采用递归思想将其简化。以操作符为分界,可以将表达式字符串分为两个部分,问题就变成求解两个更为简单的字符串的可能取值,于是问题便得到简化。最终结果就是两个部分的解分别执行相应的运算。
整个递归过程如下:

  1. 若字符串表达式全部由数字构成,则将其转为整形数并且返回。
  2. 若不是全部由数字构成,则进行递归处理直到满足递归出口条件,并且计算两个部分的可能取值。

仍然采用 2+1-1为例, 以操作符为分界,将表达式字符串分成两个部分共有如下两种分法:

  1. + 分界,可分为 21-1 两部分,前半部分直接返回 2,后半部分继续递归处理又可以分为 11 两部分,由于满足递归出口条件则直接返回 11,并计算 1-1 = 0,最后计算 2+0 = 2
  2. - 分界,可分为 2+11 两部分,前半部分继续递归处理又可以分为 21 两部分,由于满足递归出口条件则直接返回 21,并计算 2+1 = 3,后半部分直接返回 1, 最后计算 3-1 = 2

3 代码实现

题目要求采用malloc进行空间申请,并且返回其地址,返回数据的个数由函数的指针参数进行接收,其原型如下:int* diffWaysToCompute(char* expression, int* returnSize)

完整代码如下:

// 根据操作数和操作符进行相应计算
int calc(int num1, int num2, char op)
{
	if (op == '+')
		return num1 + num2;
	else if (op == '-')
		return num1 - num2;
	else
		return num1 * num2;
}

// 判断一个字符是不是数字字符
int isnum(char c1)
{
	return (c1 >= '0' && c1 <= '9');
}

// 判断一个字符是不是操作符
int isop(char* c1)
{
	return *c1 == '+' || *c1 == '-' || *c1 == '*';
}

/*
	该函数为真正的实现过程,exp-字符串表达式, len-表达式长度 retsize -接收结果个数
*/
int* diffWaysToCompute1(char* exp, int len, int* retsize)
{
	int icnt = 0;
	int* res = NULL;
	int index = 0;
    int retsize1 = 0;
	int retsize2 = 0;

    res = (int*)malloc(sizeof(int));

	// 若全是数字,则直接返回
	while (icnt < len)
	{
		if (!isnum(*(exp + icnt))) break;
		icnt++;
	}

	if (icnt == len)
	{
		*res = atoi(exp);  
		*retsize = 1;
	}
	else
	{
        for (int i = 0; i < len; i++) // 遍历字符串,根据运算符对字符串进行分割
		{
			if (isop(exp + i)) // 若是运算符则进行切分并递归
			{
				int* res1 = diffWaysToCompute1(exp, i, &retsize1); // 递归计算左半字符串
				int* res2 = diffWaysToCompute1(exp + i + 1, len - i - 1, &retsize2); // 递归计算右半字符串
				// 根据左右表达式串的结果重新申请空间,用realloc是因为需要将之前循环中产生的最终结果进行保存
                int* tmp = (int*)realloc(res, (index + retsize1 * retsize2) * sizeof(int));
                res = tmp;
				for (int m = 0; m < retsize1; m++)
				{
					for (int n = 0; n < retsize2; n++)
					{
						res[index++] = calc(res1[m], res2[n], exp[i]); //计算表达式
					}
				}
				free(res1); // res1和res2是在上一层递归中malloc申请的,使用完释放
				free(res2);
			}
		}
        *retsize = index; // 返回最终结果个数
	}
	return res;
}


int* diffWaysToCompute(char* expression, int* returnSize) {
	//之所以采用添加长度参数的diffWaysToCompute1进行递归,主要是为了节省内存空间
	return diffWaysToCompute1(expression, strlen(expression), returnSize);
}

注: 代码中没有考虑表达式不合法的情况,默认输入的表达式是合法的

标签:return,递归,int,C语言,241,exp,字符串,LeetCode,表达式
来源: https://blog.csdn.net/Nothing249/article/details/122697357