如何移除栈末尾的0?及栈处理字符串时区分首尾0的方法
搞定栈的两个问题:移除特定0 + 处理字符串前导0的压栈难题
嘿,我来帮你解决这两个栈相关的问题!咱们一个一个来捋清楚:
一、移除栈末尾的0
首先得明确你说的“栈末尾”是栈顶的0还是栈底的0——毕竟栈是FILO结构,这俩位置的处理方式完全不一样:
- 如果是要移除栈顶连续的0:这很简单,直接循环判断栈顶元素,只要是0且栈不为空,就执行
pop()就行。伪代码大概是这样:while (!stack.isEmpty() && getVP(stack.top()) == 0) { stack.pop(); } - 如果是要移除栈底的0(也就是最早压入栈的那些0):栈没法直接碰到底部元素,得借个临时栈中转一下:
- 把原栈的所有元素挨个弹出来,压进临时栈——这时候临时栈的栈顶就是原栈的栈底。
- 从临时栈弹元素,过滤掉开头的连续0(也就是原栈的底部0),直到碰到非0元素或者栈空。注意如果全是0的话,记得留一个0,别全弹没了。
- 把临时栈剩下的元素再弹回原栈就搞定了。
伪代码参考:
Stack tempStack; // 把原栈元素转移到临时栈 while (!stack.isEmpty()) { tempStack.push(stack.pop()); } // 过滤临时栈顶的连续0(对应原栈底的0) bool hasNonZero = false; while (!tempStack.isEmpty()) { int val = getVP(tempStack.top()); if (val == 0 && !hasNonZero) { tempStack.pop(); } else { hasNonZero = true; break; } } // 把剩下的元素转回去 while (!tempStack.isEmpty()) { stack.push(tempStack.pop()); } // 处理全0的情况,确保栈里至少有一个0 if (stack.isEmpty()) { stack.push(getVP((void*)&'0')); }
二、处理字符串数组时,移除原字符串开头的0(从尾部压栈导致的区分难题)
你的场景是:遍历字符串从尾部到头部压栈,结果原字符串的开头0被压到了栈最底部,和中间/末尾的0混在一起,没法直接区分。这里给你三个实用方案:
方案1:先预处理字符串,再压栈(最推荐)
在压栈之前,先把每个字符串的前导0去掉,然后再从处理后的字符串尾部开始压栈。这样从根源上就避免了栈里混入不需要的前导0,后续操作也省心。
比如处理"004912500"的伪代码:
string s = "004912500"; // 找到第一个非0字符的位置 size_t firstNonZero = s.find_first_not_of('0'); if (firstNonZero == string::npos) { // 字符串全是0,根据需求要么留一个0,要么设为空 s = "0"; } else { // 截取从第一个非0字符开始的子串 s = s.substr(firstNonZero); } // 现在从处理后的字符串尾部压栈 for (int i = s.size() - 1; i >= 0; i--) { stack.push(getVP(&s[i])); // 假设getVP能把字符转成对应的int值 }
方案2:压栈后用临时栈过滤栈底的前导0
如果必须先压栈再处理,那就用类似第一个问题里的临时栈方法——因为原字符串的开头0是最后被压入栈的,也就是在栈的最底部,对应临时栈的栈顶。只要过滤掉临时栈顶的连续0(记得留一个全0的情况),再转回去就行,步骤和第一个问题的栈底过滤一致。
方案3:统计前导0数量,压栈时直接跳过
在遍历字符串之前,先数清楚原字符串有多少个前导0,然后在压栈的时候,跳过对应位置的字符。比如"004912500"有2个前导0,那循环到索引0和1的时候就不压栈:
string s = "004912500"; size_t firstNonZero = s.find_first_not_of('0'); int skipNum = (firstNonZero == string::npos) ? s.size() - 1 : firstNonZero; // 全0的话跳过s.size()-1个,留最后一个0 for (int i = s.size() - 1; i >= 0; i--) { if (i < skipNum) { continue; // 跳过前导0的位置 } stack.push(getVP(&s[i])); }
内容的提问来源于stack exchange,提问作者Tula Malek
相关产品推荐
相关产品推荐

