在17年校招中3道题目AC却无缘华为面试,大概是华为和东华互不待见吧!分享一道华为笔试原题,共同进步!

***************************************************************************************************************************************************************************

题目描述:

LISP语言唯一的语法就是括号要匹配。
形如(OP P1 P2 …),括号内元素由单个空格分割。
其中第一个元素OP为操作符,后续元素均为其参数,参数个数取决于操作符类型
注意:参数P1,P2也有可能是另外一个嵌套的(OP P1 P2 …)
其中OP类型为add/sub/mul/div(全小写),分别代表整数的加减乘除法
其中add/mul参数个数2或以上,sub/div参数个数为2
举例:
-输入:(mul 3 -7) 输出:-21
-输入:(add1 2 3) 输出:6
-输入:(sub (mul 2 4) (div 9 3)) 输出:5
-输入:(div 1 0) 输出:error

题目涉及数字均为整数,可能为负;不考虑32位溢出翻转
除零错误时,输出"error",除法遇除不尽,取整,即3/2=1

输入描述:
合法C字符串,字符串长度不超过512;用例保证了无语法错误

输出描述:
合法C字符串,字符包括'0'-'9'及负号'-'或者'error'

示例
输入 (add 1 2 3) 输出 6
*********************************************************

  这是数据结构中括号匹配问题的变形。在检验括号是否匹配的方法中,可用“期待的急迫程度”这个概念来描述。在算法中设置了一个栈,每读入一个括号,若是右括号,则或者使置于栈顶的最急迫的期待得以消解,或者是不合法的情况;若是左括号,则作为一个新的更急迫的期待压入栈中,自然使原有的在栈中的所有未消解的期待的急迫性降了一级。另外,在算法的开始和结束时,栈都应该是空的。
  同样的道理,针对LISP的括号匹配,我们不仅需要一个符号栈opstack去保存每一个括号里的操作符OP,还需要一个栈strstack去保存括号里的参数P1、P2及符号位。
  从头到尾对输入的C字符串进行遍历,当遇到左括号"("时,将"("压入strstack中,其后的操作符压入opstack栈中;当遇到参数P时,通过字符串分割,放入strstack中;当遇到右括号")"时,在strstack栈中依次弹出参数,压入tmps栈,直到遇到"("为止,那么tmps中为一个不包含子括号参数列表,运算符为opstack的栈顶元素,其中根据操作符和参数可以进行加减乘除运运算,这部分不讨论。注意,运算结果需要在压入strstack栈中作为参数P。
  如下图所示,以(sub (mul 2 4) (div 9 3))为例,在遇到第一个")"时,strstack中分别为{(,(,2,4},opstack中分别为{sub ,mul},则strstack中依次弹出4,2,(,运算符为opstack的栈顶元素mul,可以得到结果为8,其中运算结果再压入strstack中作为参数。

  程序输入输出,运行结果示意图:

  源码分享:

  代码同步更新于  https://github.com/wylloong/TinyPrograms/blob/master/Coding%20Interviews/LISPGenerateParentheses.cpp

#include <iostream>
#include <algorithm>
#include <string>
#include <stack>
#include <vector>
#include <cstdio>
#include <stdlib.h>
#include <cstring> using namespace std; int main()
{
char chs[];
bool error = false;
gets_s(chs);
//gets(chs); //old version
std::string str(chs);
std::stack<std::string> opstack; // operations
std::stack<std::string> strstack; // divided strings
for (int i = ; i < str.size();)
{
if (str[i] == ' ')
{
i = i + ;
continue;
}
if (str[i] == '(')
{
strstack.push(std::string("("));
int spaceIndex = str.find(' ', i);
std::string tmp = str.substr(i + , spaceIndex - i - );
opstack.push(tmp); // operation
i = spaceIndex;
}
else if (str[i] == ')')
{
std::string curOp = opstack.top();
opstack.pop();
std::vector<std::string> tmps; // strs temp
while (strstack.top() != "(")
{
tmps.push_back(strstack.top());
strstack.pop();
}
strstack.pop();
// add
if (curOp == "add")
{
int temp = ;
for (int i = ; i<=tmps.size() - ; ++i)
{
temp += atoi(tmps[i].c_str());
}
strstack.push(to_string(temp));
}
// sub
else if (curOp == "sub")
{
int temp = ;
if (tmps.size() > )
temp = atoi(tmps[tmps.size() - ].c_str());
for (int i = tmps.size() - ; i >= ; --i)
{
temp -= atoi(tmps[i].c_str());
}
strstack.push(to_string(temp));
}
// mul
else if (curOp == "mul")
{
int temp = ;
if (tmps.size() > )
temp = atoi(tmps[tmps.size() - ].c_str());
for (int i = tmps.size() - ; i >= ; --i)
{
temp *= atoi(tmps[i].c_str());
}
strstack.push(to_string(temp));
}
// div
else if (curOp == "div")
{
int temp = ;
if (tmps.size() > )
temp = atoi(tmps[tmps.size() - ].c_str());
for (int i = tmps.size() - ; i >= ; --i)
{
int data1 = atoi(tmps[i].c_str());
if (data1 == )
{
error = true;
break;
}
else
temp /= data1;
}
if (error)
break;
else
strstack.push(to_string(temp));
}
++i;
}
else // substrs
{
// get substring by ' ' or ')'
auto index = str.find(' ', i);
auto index2= str.find(')', i);
if (index < index2)
{
strstack.push(str.substr(i, index - i));
i = index;
}
else
{
strstack.push(str.substr(i, index2 - i));
i = index2;
}
}
}
if (error)
cout << "error";
else
cout << atoi(strstack.top().c_str());
return ;
}

华为笔试题--LISP括号匹配 解析及源码实现的更多相关文章

  1. [算法2-数组与字符串的查找与匹配] (.NET源码学习)

    [算法2-数组与字符串的查找与匹配] (.NET源码学习) 关键词:1. 数组查找(算法)   2. 字符串查找(算法)   3. C#中的String(源码)   4. 特性Attribute 与内 ...

  2. mvc5 解析route源码实现自己的route系统

    Asp.net mvc5 解析route源码实现自己的route系统   url route 路由系统的责任是找到匹配的路由,创建路由数据,并将请求分配给一个处理程序. 选择动作是 MVC 的处理程序 ...

  3. 浩哥解析MyBatis源码(十)——Type类型模块之类型处理器

    原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6715063.html 1.回顾 之前的两篇分别解析了类型别名注册器和类型处理器注册器,此二 ...

  4. 解析 ViewTreeObserver 源码(下)

    继上篇内容,本文介绍 ViewTreeObserver 的使用,以及体会其所涉及的观察者模式,期间会附带回顾一些基础知识.最后,我们简单聊一下 Android 的消息传递,附高清示意图,轻松捋清整个传 ...

  5. Jsoup解析网页源码时常用的Element(s)类

    Jsoup解析网页源码时常用的Element(s)类 一.简介 该类是Node的直接子类,同样实现了可克隆接口.类声明:public class Element extends Node 它表示由一个 ...

  6. 用Beautiful Soup解析html源码

    #xiaodeng #python3 #用Beautiful Soup解析html源码 html_doc = """ <html> <head> ...

  7. Python解析器源码加密系列之(二):一次使用标准c的FILE*访问内存块的尝试

    摘要:由于近期打算修改Python解释器以实现pyc文件的加密/解密,出于保密的要求,解密之后的数据只能放在内存中,不能写入到文件中.但是后续的解析pyc文件的代码又只能接受FILE*作为入参,所以就 ...

  8. HtmlAgilityPack --解析Html源码

    最近项目需要从网络上抓取一下数据解析Html源码,奈何正则表达式难写,于是网上搜索找到了“ HtmlAgilityPack”类库,敏捷开发,果然效率非同寻常. 在此做笔记,写下心得,顺便给自己总结一下 ...

  9. 二十三、并发编程之深入解析Condition源码

    二十三.并发编程之深入解析Condition源码   一.Condition简介 1.Object的wait和notify/notifyAll方法与Condition区别 任何一个java对象都继承于 ...

随机推荐

  1. Java 课程设计 "Give it up"小游戏设计(个人) 201521123077

    1.团队课程设计博客链接 http://www.cnblogs.com/agts/p/7067948.html 2.个人负责模块或任务说明 个人任务:实现游戏画面的制作,游戏逻辑的编写,以及一些模块与 ...

  2. 201521123037 《Java程序设计》第9周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. java异常继承架构 2. 书面作业 本次PTA作业题集异常 1. 常用异常 题目5-1 1.1 截图你的提交结果( ...

  3. 201521123104 《Java程序设计》第14周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 1.1 建立数据库,将自己的姓名.学号作为一条记录插入.(截图, ...

  4. [js高手之路]Node.js模板引擎教程-jade速学与实战4-模板引用,继承,插件使用

    一.block 模块复用 把需要复用的模块用block定义 block后面跟上模块的名字,引用一次block 内容就会被复用一次 编译之后的结果: 二,继承模板(extends) 在实际开发中,网站的 ...

  5. Vue跨门槛系列之实例的阐述

    学习.使用中结合vue官网的api和教程极佳! 前前篇文章上有提及到vue的简单介绍,详情请戳这里 (初试 Vue.js)  第一部分: 每个 Vue 应用都是通过 Vue 函数创建一个新的 Vue ...

  6. Python爬虫2----------运用代理访问

    为request添加一个代理,及将浏览器头部信息加入,随机从ip列表中拿出一个ip进行访问 注意函数参数的形式,如request.proxyhandler(协议,地址) import urllib.r ...

  7. hdfs存取文件机制

    HDFS和HBase是Hadoop中两种主要的存储文件系统,两者适用的场景不同,HDFS适用于大文件存储,HBASE适用于大量小文件存储.本文主要讲解HDFS文件系统中客户端是如何从Hadoop集群中 ...

  8. OC——关于KVO

    我们知道在WPF.Silverlight中都有一种双向绑定机制,如果数据模型修改了之后会立即反映到UI视图上,类似的还有如今比较流行的基于MVVM设计模式的前端框架,例如Knockout.js.其实在 ...

  9. oracle pl/sql 存储过程

    存储过程用于执行特定的操作,当建立存储过程时,既可以指定输入参数(in),也可以指定输出参数(out),通过在过程中使用输入参数,可以将数据传递到执行部分:通过使用输出参数,可以将执行部分的数据传递到 ...

  10. TComboBox组件重要属性和事件

    TComboBox组件的重要属性 CharCase--------此属性用于设置编辑框内文字的大小写 DropDownCount---此属性用于设置当用户下拉组合框时不需要加滚动条就能显示的项的个数 ...