【优选算法】(第三十四篇)

目录

基本计算器II(medium)

题目解析

讲解算法原理

编写代码

字符串解码(medium)

题目解析

讲解算法原理

编写代码


基本计算器II(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给你⼀个字符串表达式s,请你实现⼀个基本计算器来计算并返回它的值。整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在[-2^31,2^31-1]的范围内。注意:不允许使⽤任何将字符串作为数学表达式计算的内置函数,⽐如eval()。
⽰例1:
输⼊:s="3+2*2"输出:7
⽰例2:
输⼊:s="3/2"输出:1
⽰例3:
输⼊:s="3+5/2"输出:5
提⽰:• 1<=s.length<=3*10^5• s由整数和算符('+','-','*','/')组成,中间由⼀些空格隔开• s表⽰⼀个有效表达式
• 表达式中的所有整数都是⾮负整数,且在范围[0,2^31-1]内• 题⽬数据保证答案是⼀个32-bit整数

题⽬解析:

⼀定要认真看题⽬的提⽰,从提⽰中我们可以看到这道题:• 只有「加减乘除」四个运算;
• 没有括号;
• 并且每⼀个数都是⼤于等于 0 的;
这样可以⼤⼤的「减少」我们需要处理的情况。 

讲解算法原理

解法(栈):
算法思路:

由于表达式⾥⾯没有括号,因此我们只⽤处理「加减乘除」混合运算即可。根据四则运算的顺序,我们可以先计算乘除法,然后再计算加减法。由此,我们可以得出下⾯的结论:
• 当⼀个数前⾯是 '+' 号的时候,这⼀个数是否会被⽴即计算是「不确定」的,因此我们可以先压
⼊栈中;
• 当⼀个数前⾯是 '-' 号的时候,这⼀个数是否被⽴即计算也是「不确定」的,但是这个数已经
和前⾯的-号绑定了,因此我们可以将这个数的相反数压⼊栈中;
• 当⼀个数前⾯是 '*' 号的时候,这⼀个数可以⽴即与前⾯的⼀个数相乘,此时我们让将栈顶的元
素乘上这个数;
• 当⼀个数前⾯是 '/' 号的时候,这⼀个数也是可以⽴即被计算的,因此我们让栈顶元素除以这个
数。
当遍历完全部的表达式的时候,栈中剩余的「元素之和」就是最终结果。

编写代码

c++算法代码:

class Solution
{
public:
 int calculate(string s) 
 {
 vector<int> st; // ⽤数组来模拟栈结构
 int i = 0, n = s.size();
 char op = '+';
 while(i < n)
 {
 if(s[i] == ' ') i++;
 else if(s[i] >= '0' && s[i] <= '9')
 {
 // 先把这个数字给提取出来
 int tmp = 0;
 while(i < n && s[i] >= '0' && s[i] <= '9') 
 tmp = tmp * 10 + (s[i++] - '0');
 if(op == '+') st.push_back(tmp);
 else if(op == '-') st.push_back(-tmp);
 else if(op == '*') st.back() *= tmp;
 else st.back() /= tmp;
 }
 else
 {
 op = s[i];
 i++;
 }
 }
 int ret = 0;
 for(auto x : st) ret += x;
 return ret;
 }
};

java算法代码:

class Solution
{
 public int calculate(String _s) 
 {
 Deque<Integer> st = new ArrayDeque<>();
 char op = '+';
 int i = 0, n = _s.length();
 char[] s = _s.toCharArray();
 while(i < n)
 {
 if(s[i] == ' ') i++;
 else if(s[i] >= '0' && s[i] <= '9')
 {
 int tmp = 0;
 while(i < n && s[i] >= '0' && s[i] <= '9')
 {
 tmp = tmp * 10 + (s[i] - '0');
 i++;
 }
 if(op == '+') st.push(tmp);
 else if(op == '-') st.push(-tmp);
 else if(op == '*') st.push(st.pop() * tmp);
 else st.push(st.pop() / tmp);
 }
 else
 {
 op = s[i];
 i++;
 }
 }
 // 统计结果
 int ret = 0;
 while(!st.isEmpty())
 {
 ret += st.pop();
 }
 return ret;
 }
}

字符串解码(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给定⼀个经过编码的字符串,返回它解码后的字符串。
编码规则为:k[encoded_string],表⽰其中⽅括号内部的encoded_string正好重复k次。注意k保证为正整数。
你可以认为输⼊字符串总是有效的;输⼊字符串中没有额外的空格,且输⼊的⽅括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表⽰重复的次数k,例如不会出现像3a或2[4]的输⼊。
⽰例1:
输⼊:s="3[a]2[bc]"
输出:"aaabcbc"
⽰例2:
输⼊:s="3[a2[c]]"
输出:"accaccacc"
⽰例3:
输⼊:s="2[abc]3[cd]ef"
输出:"abcabccdcdcdef"

讲解算法原理

解法(两个栈):
算法思路:

对于 3[ab2[cd]] ,我们需要先解码内部的,再解码外部(为了⽅便区分,使⽤了空格):• 3[ab2[cd]] -> 3[abcd cd] -> abcdcd abcdcd abcdcd
在解码 cd 的时候,我们需要保存 3 ab 2 这些元素的信息,并且这些信息使⽤的顺序是从后往前,正好符合栈的结构,因此我们可以定义两个栈结构,⼀个⽤来保存解码前的重复次数 k (左括号前的数字),⼀个⽤来保存解码之前字符串的信息(左括号前的字符串信息)。

编写代码

c++算法代码:

class Solution
{
public:
 string decodeString(string s) 
 {
 stack<int> nums;
 stack<string> st;
 st.push("");
 int i = 0, n = s.size();
 while(i < n)
 {
 if(s[i] >= '0' && s[i] <= '9')
 {
 int tmp = 0;
 while(s[i] >= '0' && s[i] <= '9')
 {
 tmp = tmp * 10 + (s[i] - '0');
 i++;
 }
 nums.push(tmp);
 }
 else if(s[i] == '[')
 {
 i++; // 把括号后⾯的字符串提取出来
 string tmp = "";
 while(s[i] >= 'a' && s[i] <= 'z')
 {
 tmp += s[i];
 i++;
 }
 st.push(tmp);
 }
 else if(s[i] == ']')
 {
 string tmp = st.top();
 st.pop();
 int k = nums.top();
 nums.pop();
 while(k--)
 {
 st.top() += tmp;
 }
 i++; // 跳过这个右括号
 }
 else
 {
 string tmp;
 while(i < n && s[i] >= 'a' && s[i] <= 'z')
 {
 tmp += s[i];
 i++;
 }
 st.top() += tmp;
 }
 }
 return st.top();
 }
};

java算法代码:

class Solution
{
 public String decodeString(String _s) 
 {
 Stack<StringBuffer> st = new Stack<>();
 st.push(new StringBuffer()); // 先放⼀个空串进去 Stack<Integer> nums = new Stack<>();
 int i = 0, n = _s.length();
 char[] s = _s.toCharArray();
 while(i < n)
 {
 if(s[i] >= '0' && s[i] <= '9')
 {
 int tmp = 0;
 while(i < n && s[i] >= '0' && s[i] <= '9')
 {
 tmp = tmp * 10 + (s[i] - '0');
 i++;
 }
 nums.push(tmp);
 }
 else if(s[i] == '[')
 {
 i++; // 把后⾯的字符串提取出来
 StringBuffer tmp = new StringBuffer();
 while(i < n && s[i] >= 'a' && s[i] <= 'z')
 {
 tmp.append(s[i]);
 i++;
 }
 st.push(tmp);
 }
 else if(s[i] == ']')
 {
 // 解析
 StringBuffer tmp = st.pop();
 int k = nums.pop();
 while(k-- != 0)
 {
 st.peek().append(tmp);
 }
 i++;
 }
 else
 {
 StringBuffer tmp = new StringBuffer();
 while(i < n && s[i] >= 'a' && s[i] <= 'z')
 {
 tmp.append(s[i]);
 i++;
 }
 st.peek().append(tmp);
 }
 }
 return st.peek().toString();
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值