在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[512]; 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 = 0; i < str.size();) { if (str[i] == ' ') { i = i + 1; continue; } if (str[i] == '(') { strstack.push(std::string("(")); int spaceIndex = str.find(' ', i); std::string tmp = str.substr(i + 1, spaceIndex - i - 1); 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 = 0; for (int i = 0; i<=tmps.size() - 1; ++i) { temp += atoi(tmps[i].c_str()); } strstack.push(to_string(temp)); } // sub else if (curOp == "sub") { int temp = 0; if (tmps.size() > 0) temp = atoi(tmps[tmps.size() - 1].c_str()); for (int i = tmps.size() - 2; i >= 0; --i) { temp -= atoi(tmps[i].c_str()); } strstack.push(to_string(temp)); } // mul else if (curOp == "mul") { int temp = 0; if (tmps.size() > 0) temp = atoi(tmps[tmps.size() - 1].c_str()); for (int i = tmps.size() - 2; i >= 0; --i) { temp *= atoi(tmps[i].c_str()); } strstack.push(to_string(temp)); } // div else if (curOp == "div") { int temp = 0; if (tmps.size() > 0) temp = atoi(tmps[tmps.size() - 1].c_str()); for (int i = tmps.size() - 2; i >= 0; --i) { int data1 = atoi(tmps[i].c_str()); if (data1 == 0) { 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 0; }
