【[20] 有效的括号】

2024-05-24 19:38:29 浏览数 (2)

  • @lc app=leetcode.cn id=20 lang=cpp
  • @lcpr version=30202
  • [20] 有效的括号 */ 这段代码是用来验证括号是否有效的,下面是注释的版本:
代码语言:javascript复制
using namespace std;
#include <algorithm>
#include <array>
#include <bitset>
#include <climits>
#include <deque>
#include <functional>
#include <iostream>
#include <list>
#include <queue>
#include <stack>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
代码语言:javascript复制
bool isValid(string s) {
std::stack<char> stack;
    for (char c : s) {
        if (c == '(' || c == '[' || c == '{') {
            stack.push(c);
        } else {
            if (stack.empty()) {
                return false;
            }
            char top = stack.top();
            if ((c == ')' && top != '(') || (c == ']' && top != '[') || (c == '}' && top != '{')) {
                return false;
            }
            stack.pop();
        }
    }
    return stack.empty();
    }

这段代码主要通过使用栈实现括号匹配。每遇到一个开括号就压入栈中,每遇到一个闭括号就检查是否与栈顶的开括号匹配,匹配则继续处理,不匹配则验证失败。最终如果栈为空,则说明所有的括号都已匹配,返回true;如果栈不为空,则说明存在未匹配的括号,返回false。

为了将给定的代码转换为C 98的版本(因为C 11引入了基于范围的for循环和auto类型推断等特性),我们需要替换基于范围的for循环并适当修改代码风格。以下是修改后的C 98兼容代码:

代码语言:javascript复制
#include <stack>
#include <string>

bool isValid(std::string s) {
    std::stack<char> stack;
    // 用传统的for循环替代基于范围的for循环
    for (size_t i = 0; i < s.length(); i  ) {
        char c = s[i];  // 获取当前字符
        // 检查字符是否为开括号
        if (c == '(' || c == '[' || c == '{') {
            stack.push(c);  // 将开括号压入栈
        } else {
            // 当遇到闭括号时,如果栈为空,说明没有相应的开括号可以匹配
            if (stack.empty()) {
                return false;
            }
            char top = stack.top();
            // 检查栈顶的开括号是否与当前闭括号匹配
            if ((c == ')' && top != '(') || (c == ']' && top != '[') || (c == '}' && top != '{')) {
                return false;  // 如果不匹配,返回false
            }
            stack.pop();  // 匹配成功,弹出栈顶的开括号
        }
    }
    // 最后检查栈是否为空,如果为空,则所有括号都正确匹配,返回true
    return stack.empty();
}

在这个版本中,我们使用size_t i = 0; i < s.length(); i 来代替原来基于范围的for循环,并直接通过下标访问字符串中的每个字符。这保证了代码是C 98标准兼容的。这种方式在处理字符串和数组元素时仍然是常见且有效的。

您提供的示例字符串 “(1)[]{}” 中包含了数字和括号。原始的括号验证代码只处理了括号字符,对于数字和其他非括号字符没有进行处理。如果需要该代码片段正确处理这种包含非括号字符的字符串,我们需要对原有代码进行一些简单修改,忽略非括号字符。

以下是修改过的代码,它会忽略所有非括号字符:

代码语言:javascript复制
#include <stack>
#include <string>

bool isValid(std::string s) {
    std::stack<char> stack;
    for (size_t i = 0; i < s.length(); i  ) {
        char c = s[i];
        // 只处理括号字符
        switch(c) {
            case '(':
            case '[':
            case '{': 
                stack.push(c); // 如果是开括号,压入栈
                break;
            case ')':
                if (stack.empty() || stack.top() != '(') return false; // 如果栈为空或栈顶不是匹配的开括号,返回false
                stack.pop();
                break;
            case ']':
                if (stack.empty() || stack.top() != '[') return false; // 同上
                stack.pop();
                break;
            case '}':
                if (stack.empty() || stack.top() != '{') return false; // 同上
                stack.pop();
                break;
            default:
                // 忽略所有非括号字符
                break;
        }
    }
    return stack.empty(); // 如果栈为空,说明所有开括号都被匹配了,返回true
}

在这个修改版中,我们通过一个switch语句来处理每个字符。如果字符是一个括号,它将进入相应的处理逻辑;如果是其他字符,如数字或字母,将直接忽略。这样的处理可以确保函数能适用于包含任意字符的字符串。

如果不想使用switch语句来处理字符,可以使用if语句来分别判断每种情况。下面是使用if语句改写的代码:

代码语言:javascript复制
#include <stack>
#include <string>

bool isValid(std::string s) {
    std::stack<char> stack;
    for (size_t i = 0; i < s.length(); i  ) {
        char c = s[i];
        // 处理开括号
        if (c == '(' || c == '[' || c == '{') {
            stack.push(c);
        // 处理闭括号
        } else if (c == ')' || c == ']' || c == '}') {
            if (stack.empty()) {
                return false;
            }
            char top = stack.top();
            if ((c == ')' && top != '(') || 
                (c == ']' && top != '[') || 
                (c == '}' && top != '{')) {
                return false;
            }
            stack.pop();
        }
        // 忽略所有非括号字符
    }
    // 检查栈是否为空
    return stack.empty();
}

在这个改写的版本中,我们用连串的if和else if语句来识别并处理开括号和闭括号,而忽略了所有非括号的字符。这种方法同样有效,并且没有使用switch语句,避免对某些开发者来说可能在逻辑判断上不够直观的问题。这两种代码(使用switch和使用if)在功能上是等价的,具体使用哪种取决于个人或项目的编码风格偏好。

0 人点赞