输入描述:
输入一个字符串,字符串中包含了全量字符集和已占用字符集,两个字符集用@相连。@前的字符集合为全量字符集,@后的字符集为已占用字符集合。已占用字符集中的字符一定是全量字符集中的字符。字符集中的字符跟字符之间使用英文逗号分隔。字符集中的字符表示为字符加数字,字符跟数字使用英文冒号分隔,比如a:1,表示1个a字符。字符只考虑英文字母,区分大小写,数字只考虑正整形,数量不超过100,如果一个字符都没被占用,@标识符仍在,例如a:3,b:5,c:2@输出描述:
可用字符集。输出带回车换行。示例1:
输入:a:3,b:5,c:2@a:1,b:2输出:a:2,b:3,c:2
说明:全量字符集为3个a,5个b,2个c。已占用字符集为1个a,2个b。由于已占用字符集不能再使用,因此,剩余可用字符为2个a,3个b,2个c。因此输出a:2,b:3,c:2。注意,输出的字符顺序要跟输入一致。不能输出b:3,a:2,c:2。如果某个字符已全被占用,不需要输出。例如a:3,b:5,c:2@a:3,b:2,输出为b:3,c:2。
用正则表达式分割。
#include
using namespace std;
int main()
{
string str;
getline(cin, str);
int i = 0, n = str.size();
while(i < n && str[i] != '@') i++;
string all = str.substr(0, i);
i++;
string used;
if(i < n) used = str.substr(i);
regex re(R"(([a-zA-Z]):(\d+))");
vector hash(256, 0);
int cnt = 0;
vector input;
for(sregex_token_iterator it(all.begin(), all.end(), re), end; it != end; it++)
{
string sub = *it;
smatch m;
if(regex_match(sub, m, re))
{
string character = m[1];
int val = stoi(m[2]);
hash[character[0]] = val;
if(val > 0) cnt++;
input.emplace_back(character[0]);
}
}
for(sregex_token_iterator it(used.begin(), used.end(), re), end; it != end; it++)
{
string sub = *it;
smatch m;
if(regex_match(sub, m, re))
{
string ch = m[1];
int val = stoi(m[2]);
hash[ch[0]] -= val;
if(hash[ch[0]] == 0) cnt--;
}
}
for (int j = 0; j < input.size(); ++j)
{
if(hash[input[j]] > 0)
{
printf("%c:%d", input[j], hash[input[j]]);
cnt--;
if(cnt > 0) printf(";");
}
}
return 0;
}
题目描述:
常用的逻辑计算有And(表示为&);Or(表示为|);Not(表示为!)。其中,他们的优先级关系是Not(!)>And(&)>Or(|)。
输入描述:
1、测试用例中间无空格,无需考虑空格。
2、测试用例表达式只会出现如下字符:“0”,“1”,“(”,“)”,“&”,“|”,“!”。
3、测试用例所给的输入都是合法输入,无需要考虑非法输入。
4、测试用例长度不会超过128个字符。
5、括号可以重复嵌套。
例如:
1 | ( 1 & 0 ) 返回值:1
1 & 0 | 0 & 1 返回值:0
! 0 & 1 | 0 返回值:1
( ( ! 0 & 1 ) ) | 0 返回值:1
输出描述:
输出逻辑运算后的最终结果:0或者1
示例1:
输入:! ( 1 & 0 ) | 0 & 1输出:1
示例2:
输入:! ( 1 & 0 ) & 0 | 0输出:0
中缀转后缀,再用后缀表达式求值。
(1) 中缀转后缀的步骤:使用栈存储运算符,预定义运算符的优先级。然后,遍历中缀表达式:
(a) 如果是左括号,压栈;
(b) 如果是右括号,直到栈顶是左括号为止,持续出栈,附到后缀表达式后面。之后,将左括号出栈。
(c) 如果是运算符,从栈顶将所有优先级大于等于当前的运算符持续出栈,直到栈顶运算符优先级小于当前运算符为止。之后,将当前运算符压栈。
(d) 如果是操作数,直接附到后缀表达式的后面。
最后,直到栈为空为止,持续出栈,附到后缀表达式后面。
(2) 使用后缀表达式求值相比之下就很简单,使用栈存储操作数,当遍历到运算符时,取出栈顶的1个或者2个元素进行运算,将结果压栈。最后,栈中剩下的那一个值就是运算结果。
#include
using namespace std;
//中缀转后缀
void convert(string& in, string& post)
{
vector hash(256, 0);
hash['&'] = 1;
hash['!'] = 2;
stack op;
for(char c : in)
{
if(c == '(') op.push('(');
else if(c == ')')
{
while(!op.empty() && op.top() != '(')
{
post += op.top();
op.pop();
}
op.pop();
}
else if(c == '&' || c == '|' || c == '!')
{
while(!op.empty() && hash[op.top()] >= hash[c])
{
post += op.top();
op.pop();
}
op.push(c);
}
else if(isdigit(c)) post += c;
}
while(!op.empty())
{
post += op.top();
op.pop();
}
}
//使用后缀表达式计算
char calc(string& post)
{
stack st;
for(char c : post)
{
if(c == '0') st.push(false);
else if(c == '1') st.push(true);
else if(c == '!')
{
bool top = st.top();
st.pop();
st.push(!top);
}
else if(c == '&')
{
bool a = st.top();
st.pop();
bool b = st.top();
st.pop();
st.push(a & b);
}
else if(c == '|')
{
bool a = st.top();
st.pop();
bool b = st.top();
st.pop();
st.push(a | b);
}
}
return st.top() ? '1' : '0';
}
int main()
{
string str;
while(getline(cin, str))
{
string post;
convert(str, post);
printf("%c\n", calc(post));
}
return 0;
}
https://www.nowcoder.com/practice/9999764a61484d819056f807d2a91f1e?tpId=37&&tqId=21273&rp=1&ru=/ta/huawei&qru=/ta/huawei/question-ranking
同样是中缀转后缀的做法,但是要注意'-'的处理,如果是做负号用,需要变成减法的形式。
对于比较弱的数据,'-'作负号用时只出现在首位或者'('的后面,所以只需要判断下'-'是否是在首位,或者'('的后面,如果是就变成"0-"即可。
//先把括号换掉
for(char& c : str)
{
if(c == '[' || c == '{') c = '(';
else if(c == ']' || c == '}') c = ')';
}
//处理负号
string tmp;
int i = 0, n = str.size();
while(i < n)
{
if(str[i] == '-')
{
if(i == 0 || str[i-1] == '(')
{
tmp += "0-";
i++;
}
else tmp += str[i++];
}
else tmp += str[i++];
}
对于比较强的数据,如2*-(2*3+(6+3)*5)这种,就要严谨的判断负号作用的起点和终点,然后变成"(0-...)"的形式:
(1) 首先判断是否是负号:当'-'前面为空,或者前面的字符不是数字,就是负号
(2) 然后判断负号作用的起点和终点:如果'-'后面的字符是数字,那么'-'的作用范围就是后面的连续数字字符串。否则,'-'的后面是'(',那么要一直往后统计左括号和右括号的个数,直到二者匹配,说明括号匹配结束,找到了'-'的作用范围。
//先把括号换掉
for(char& c : str)
{
if(c == '[' || c == '{') c = '(';
else if(c == ']' || c == '}') c = ')';
}
//处理负号
string tmp;
int i = 0, j = 0, n = str.size();
while(i < n)
{
if(str[i] == '-')
{
//‘-’的前面不是')',并且'-'的前面也不是数字,那么'-'是负号,要变成 (0-...)
if(tmp.empty() || (tmp.back() != ')' && !isdigit(tmp.back())))
{
if(i + 1 < n && isdigit(str[i+1]))
{
j = i + 2;
while(j < n && isdigit(str[j])) j++;
//[i+1...j-1]
tmp += "(0-" + str.substr(i+1, j - i - 1) + ")";
i = j;
}
else if(i + 1 < n && str[i+1] == '(')
{
int leftcnt = 1;
j = i + 2;
while(j < n)
{
if(str[j] == ')')
{
if(--leftcnt == 0) break;
}
else if(str[j] == '(') leftcnt++;
j++;
}
//[i+1...j]
tmp += "(0-" + str.substr(i+1, j - i);
i = j;
}
else i++;
}
else tmp += str[i++];
}
else tmp += str[i++];
}
总体代码:数据较弱,不需要复杂的判断'-'的方法。
#include
using namespace std;
int priority[128] = {0};
vector inToPost(const string& in)
{
stack op;
vector ans;
int i = 0, j = 0, n = in.size();
while(i < n)
{
if(in[i] == '(')
{
op.push(in[i++]);
}
else if(in[i] == ')')
{
while(!op.empty() && op.top() != '(')
{
ans.emplace_back(string(1, op.top()));
op.pop();
}
op.pop();
i++;
}
else if(isdigit(in[i]))
{
j = i + 1;
while(j < n && isdigit(in[j])) j++;
ans.emplace_back(in.substr(i, j - i));
i = j;
}
else
{
while(!op.empty() && op.top() != '(' && priority[op.top()] >= priority[in[i]])
{
ans.emplace_back(string(1, op.top()));
op.pop();
}
op.push(in[i++]);
}
}
while(!op.empty())
{
ans.emplace_back(string(1, op.top()));
op.pop();
}
return ans;
}
int calc(const vector& postorder)
{
stack st;
for(const auto& s : postorder)
{
if(isdigit(s[0])) st.push(stoi(s));
else
{
int b = st.top();
st.pop();
int a = st.top();
st.pop();
if(s == "+") st.push(a+b);
else if(s == "*") st.push(a*b);
else if(s == "/") st.push(a/b);
else st.push(a - b);
}
}
return st.top();
}
int main(){
priority['*'] = priority['/'] = 1;
string str;
while(getline(cin, str))
{
if(str.empty()) break;
//先把括号换掉
for(char& c : str)
{
if(c == '[' || c == '{') c = '(';
else if(c == ']' || c == '}') c = ')';
}
//处理负号
string tmp;
int i = 0, n = str.size();
while(i < n)
{
if(str[i] == '-')
{
if(i == 0 || str[i-1] == '(')
{
tmp += "0-";
i++;
}
else tmp += str[i++];
}
else tmp += str[i++];
}
printf("%d\n", calc(inToPost(tmp)));
}
return 0;
}