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

目录

基本计算器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();
 }
}
相关推荐
楠寻寻2 分钟前
Java中注解与反射的详细介绍
java·开发语言·学习·java-ee·idea
Algorithm15764 分钟前
k3s主从节点设置详细流程
java·k8s
萧鼎9 分钟前
从零开始构建:Python自定义脚本自动化你的日常任务
开发语言·python·自动化
API1997010811013 分钟前
VVIC商品详情接口技术解析与实战代码示例
开发语言·python·json·php
Mr.D学长14 分钟前
毕设 深度学习图像搜索算法-图像搜索引擎(源码分享)
python·毕业设计·毕设
zhooyu19 分钟前
C++和OpenGL实现3D游戏编程【连载14】——VBO、VAO和EBO应用
开发语言·c++·游戏·游戏程序·游戏策划
QuantumStack25 分钟前
【C++ 真题】B2003 输出第二个整数
开发语言·c++·算法
小七蒙恩28 分钟前
Java面试宝典-WEB学习
java·前端·面试
yaoxin52112330 分钟前
第四十章 创建安全对话 - 启用 IRIS Web 服务以支持 WS-SecureConversation
前端·python·安全
椰椰椰耶30 分钟前
【Spring】Spring MVC的项目准备和连接建立
java·spring·mvc