最大公约数
牛客链接:NC151 最大公约数
题解1:辗转相减法
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 求出a、b的最大公约数。
* @param a int
* @param b int
* @return int
*/
int gcd(int a, int b) {
// write code here
int z= b;
while(a!=b){
if(a>b)
a = a-b;
if(b>a)
b -= a;
}
return b;
}
};
题解2:辗转相除法
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 求出a、b的最大公约数。
* @param a int
* @param b int
* @return int
*/
int gcd(int a, int b) {
// write code here
if(a<b)
swap(a, b);
int z = b;
while(a%b!=0){
z = a%b;
a = b;
b = z;
}
return z;
}
};
最小公倍数
牛客链接:HJ108 求最小公倍数
解题思路:最小公倍数 = 两数之积除以最大公约数
#include<iostream>
using namespace std;
//递归求最大公约数 (x > y)
int gcd(int x, int y){
if(y==0)
return x;
else
return gcd(y,x%y);
}
int main(){
int x,y;
cin>>x;
cin>>y;
if(x<y)
swap(x,y);
cout<< x*y/gcd(x,y);
}
计算器(一)
牛客链接:NC240 计算器(一)
解法1
公式可以分为:左表达式值 + 符号位 + 右表达式值
我们可以考虑所有数字为+号,当出现-的时候,表示后续右表达式值为负数,最终还是执行加法操作。
当遇到 ‘( ’的时候,将之前的计算结果与符号位放入栈中,当遇到‘)’的时候,去除符号位,表示当前括号内的值的真实大小,在取出结果栈中的之前结果求和,就是当前正确的结果。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return int整型
*/
int calculate(string s) {
// write code here
stack<int> num;
stack<char> sign;
int temp = 0, res = 0, sig = 1;
for(int i =0;i<s.size();++i){
if(i<s.size() && s[i] - '0'>=0 && s[i] - '0'<=9){ //防止有>9的数字
temp = temp * 10 + (s[i] - '0');
}
else if(i<s.size() && (s[i] == '-' or s[i] == '+')){ //确定当前位的符号位,默认为+
res += sig * temp;
temp = 0;
sig = (s[i]=='+')?1:-1;
}
else if(i<s.size() && s[i] == '('){ //遇到(
num.push(res);
sign.push(sig);
res = 0; //初始化括号内计算值与符号
sig = 1;
}
else if(i<s.size() && s[i] == ')') { //遇到)
res += sig*temp;
temp = 0;
res *= sign.top();
sign.pop();
res += num.top();
num.pop();
}
}
res += sig*temp; //最终的一个数字求和(i== s.size()时退出循环)
return res;
}
};
解法2
将所有的括号拆开,即1-(1-2) = 1-1+2, 所以要保留括号外的那个字符,从而正确获得括号内的用于求和的值。
class Solution {
public:
int calculate(string s) {
stack<int> sign;
int res = 0, tmp = 0, sig = 1;
// 分别位最后的答案,临时数,符号
sign.push(sig);
// 我们开辟的栈用于存储符号
for (auto &it : s) {
if(it>='0' && it<='9') tmp = tmp*10 + it-'0';
else{
res += sig * tmp; //遇到符号,计算之前的结果
tmp = 0; //默认下一数字的值
switch(it){ //判断符号真实正负
case '+':
sig = 1 * sign.top();
break;
case '-':
sig = -1 * sign.top();
break;
case '(':
sign.push(sig);
break;
default:
sign.pop();
break;
}
}
}
res += sig * tmp;
// 把最后一个也算进去
return res;
}
};
计算器(二)
牛客链接:NC241 计算器(二)
和上面一题类似,但是去掉了括号,加入了乘除。我们这里通过一个栈保存局部的结果(将乘法除法以及减法算出来的结果看成是一部分,最终只存在加法操作),用两个变量保存是否当前是在执行局部乘法或者除法操作,如果是要先进行乘法和除法的运算。
#include <numeric>
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @return int整型
*/
int calculate(string s) {
// write code here
stack<int> nums;
int temp = 0, res =0, sig = 1;
bool mult = false, div = false; //是否正在进行乘除法
for(char c:s){
if(c>='0' && c<='9') temp = temp*10 + c-'0';
else{
if(mult){ //正在执行乘法操作
temp *= nums.top(); //弹出首个保存的值,用于执行乘法。
mult = false;
nums.pop();
}
else if(div){ //正在执行除法操作
temp = nums.top()/temp;
div = false;
nums.pop();
}
if(c == '+' ) //加法减法直接连同符号位一起保存进栈
{
nums.push(temp*sig);
sig = 1;
temp = 0;
}
else if(c == '-' )
{
nums.push(temp*sig);
sig = -1;
temp = 0;
}
else if(c == '*' ) //乘除法,将当前乘数或者除数保存进结果,之后获得下一个值之后,在将head元素拿出来使用。
{
nums.push(temp*sig);
mult = true;
sig = 1;
temp = 0;
}
else if(c == '/' )
{
nums.push(temp*sig);
div = true;
sig = 1;
temp = 0;
}
}
}
res = 0;
while(div or mult) //如果最后一个操作是乘除,先解决乘除法
{
if(mult){
temp*=nums.top();
mult = false;
nums.pop();
}
else if(div){
temp=nums.top()/temp;
div = false;
nums.pop();
}
}
nums.push(temp*sig); //将结果加入栈
while(nums.size() >0){
res+=nums.top();
nums.pop();
}
return res;
}
};