这道题很简单,从题目中给出的几种倒数的求法和我们对求导的理解,得出通过递归即能求解,写这篇博客的目的是感觉这道题描述不是很好,尤其是里面有句"输入保证合法。注意要带着括号",让我以为测试用例中没有像((((x)*(x))))这样外面有多余的括号的情况,而测试用例里面竟有这样的,这时需要将最外面的多余括号保留到最终的求导结果中,所以写这篇博客,为了减少大家在测试用例上浪费的时间,还有从题目中可以看出,求导时同级运算具有右结合性(即先算右边的),即如(x*x*x)'=(1*x*x+x*{x*x}') ,这里用花括号的目的是说明此对括号不是本身字符串里面的。
题目详情:
根据导数公式求导数
(a + b)' = a' + b'
(a - b)' = a' - b'
(a * b)' = (a' * b + a * b')
(a / b)' = (a' * b - a * b') / b^2
ln(a)' = (a')/(a)
x' = 1
const' = 0
输入保证合法。注意要带着括号,注意不要优化,例如 0*a不能写成0, 1*a也不能写成a。详见样例。
输入格式
每行一个多项式
输出格式
每行一个多项式,对应多项式的导数
答题说明:
输入样例
x*x/x
-45.78*x+x
-2.45*x*x+ln(x-3)
输出样例
((1*x+x*1)*x-x*x*1)/x^2
(0*x-45.78*1)+1
((0*x-2.45*1)*x-2.45*x*1)+(1-0)/(x-3)
友情提醒:
1、本题用OJ模式答题,答题时可把下面输入框内预留的函数全部直接去掉,自己另起函数名实现本题功能。
我的解法,其实上面基本已经说出了我的做法,这里补充下:
首先将表达式的外层无用括号去掉(返回结果时再添加上),然后尝试将表达式以+,-,*,/将其分割成左右两个子表达式,什么样的算术运算符能将表达式分割成两个子表达式呢,显然是不在括号里面的算术运算符,还有+ - 的分割优先级高于* /,同优先级具有右结合性,然后按照求导规则对左右分别求导,返回结果;如果不能将其分割成两个子表达式,那么这是对表达式按ln对数求导。
需要注意:1.最外层的多余括号;2.右结合性
代码如下:
#include<iostream>
#include<string>
//统计str最外层的括号对数,如:(((x)*(x)*5))为2
int getOutBrackets(const std::string&str){
int max=0;//最外层最多有几对括号
for(int i=0;i<str.size()/2;++i)
if(str[i]=='('&&str[str.size()-i-1]==')')
++max;
else break;
int lBracket=0;
int end=str.size()-max;
for(int i=max;i<end;++i)
if(str[i]!='('&&str[i]!=')')
continue;
else if(str[i]=='(')
++lBracket;
else if(lBracket==0)
--max;
else
--lBracket;
return max;
}
std::string diff(std::string&str){
int out=getOutBrackets(str);
if(out>0)
return str.substr(0,out)+diff(str.substr(out,str.size()-2*out))+str.substr(str.size()-out,out);
if(std::string::npos==str.find('x'))
return "0";
else if(1==str.size()&&'x'==str[0])
return "1";
else{//size>=2, str contains x
int hasR=0;//右括号的数量
int pos[4]={0,0,0,0};//begin with 1
//题目中看出是求导时的右结合性,所以从后向前遍历
std::string::size_type i=str.size()-1;
for(;i>=1;--i){
if('0'<=str[i]&&'9'>=str[i]||'.'==str[i]||'l'==str[i]||'n'==str[i]||'x'==str[i])
continue;
if(str[i]==')')
++hasR;
else if(str[i]=='(')
--hasR;
else if(str[i]=='+'){
if(!hasR){
pos[0]=i;
break;
}
}else if(str[i]=='-'){
if(!hasR){
pos[1]=i;
break;
}
}else if(str[i]=='*'){
if(!hasR&&i>pos[2])
pos[2]=i;
}else if(!hasR&&i>pos[3])
pos[3]=i;
}
if(pos[0]>0)
return diff(str.substr(0,pos[0]))+'+'+diff(str.substr(pos[0]+1));
else if(pos[1]>0)
return diff(str.substr(0,pos[1]))+'-'+diff(str.substr(pos[1]+1));
else if(pos[2]>pos[3]){
std::string left=str.substr(0,pos[2]);
std::string right=str.substr(pos[2]+1);
if('-'==left[0])
return '('+diff(left)+'*'+right+left+'*'+diff(right)+')';
else
return '('+diff(left)+'*'+right+'+'+left+'*'+diff(right)+')';
}else if(pos[2]<pos[3]){
std::string left=str.substr(0,pos[3]);
std::string right=str.substr(pos[3]+1);
return '('+diff(left)+'*'+right+'-'+left+'*'+diff(right)+")/"+right+"^2";
}else{
std::string left=str.substr(3,str.size()-4);
return '('+diff(left)+")/"+'('+left+')';
}
}
}
int main(int argc,char** argv){
std::string str,d;;
while(std::cin>>str)
std::cout<<diff(str)<<std::endl;
return EXIT_SUCCESS;
}