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

目录

基本计算器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.题目描述

给定⼀个经过编码的字符串,返回它解码后的字符串。

编码规则为:kencoded_string,表⽰其中⽅括号内部的encoded_string正好重复k次。注意k保证为正整数。

你可以认为输⼊字符串总是有效的;输⼊字符串中没有额外的空格,且输⼊的⽅括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表⽰重复的次数k,例如不会出现像3a或24的输⼊。

⽰例1:

输⼊:s="3a2bc"

输出:"aaabcbc"

⽰例2:

输⼊:s="3a2\[c]"

输出:"accaccacc"

⽰例3:

输⼊:s="2abc3cdef"

输出:"abcabccdcdcdef"

讲解算法原理

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

对于 3ab2\[cd] ,我们需要先解码内部的,再解码外部(为了⽅便区分,使⽤了空格):• 3ab2\[cd] -> 3abcd 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();
 }
}
相关推荐
2601_962106641 分钟前
HashMap入门|工号-姓名键值存储、两种遍历方式、根据key/value查
java
czq_26867194877 分钟前
Python打卡第46天
开发语言·python
Pniubi20 分钟前
力扣54.螺旋矩阵
算法·leetcode·矩阵
杨凯凡34 分钟前
Spring Framework 7 API 版本管理实战:请求头路由、兼容迁移与废弃策略
java·rest api·springframework·spring boot 4·api版本管理
T_Wizard1 小时前
同一个问题写了 4 遍:官方 SDK / HTTP / Spring AI / LangChain4j,到底该选哪个
java·ai编程
hai_android1 小时前
AudioTrack 深度解析:从原理到实战
android·java·kotlin
斯维赤1 小时前
限流、熔断、降级,你真的分得清吗?
java·后端·架构
Flynt1 小时前
日涨4000星的OSINT工具,我拿Linus的用户名和一个随机字符串实测了一遍
python·安全
Evand J3 小时前
【MATLAB例程介绍】(17)永磁同步电机(PMSM)基于自适应无迹卡尔曼滤波(AUKF)的电流噪声在线估计。测量噪声协方差自适应与转速估计对比仿真
开发语言·matlab·卡尔曼滤波·无迹卡尔曼滤波·pmsm·电机滤波
choumou_M3 小时前
算法_1:由浅入深学习快速排序QuickSort
学习·算法·排序算法