Get One Valid parentheses Pair

本文介绍了一种从包含括号的字符串中提取有效括号序列的方法。该算法通过两次扫描(从左到右和从右到左)来确定有效的括号对,并使用计数器跟踪有效括号的数量。代码实现采用C++编写,并提供了一个示例。

Best Method I have seen so far. Scan the target string from left  to right, and then from right to left. Use a counter to remember the valid parentheses.

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

string getValidString(const string s) {
  if(s.size() == 0) return s;
  int left = 0, right = 0;
  string tmp, result;
  for(auto c : s) {
    if(c == '(') {
      left++;
      tmp += '(';
    } else if(c == ')') {
      if(left > 0) {
        left--;
        tmp += ')';
      }
    } else {
      tmp += c;
    }
  }

  for(int i = tmp.size() - 1; i >= 0; --i) {
    if(tmp[i] == ')') {
      right++;
      result += ')';
    } else if(tmp[i] == '(') {
      if(right > 0) {
        right--;
        result += '(';
      }
    } else {
      result += tmp[i];
    }
  }
  reverse(result.begin(), result.end());
  return result;
}

int main(void) {
  string res = getValidString("((a)");
  cout << res << endl;



/***************************************************************************** * * This file is copyright (c) 2023 PTC, Inc. * All rights reserved. * * Name: HTTP-profile * Description: A simple HTTP example profile that queries weather data * from a weather REST-API. * Version: 0.3.0 * Revision history: * 0.3.0 Added bulkId property to the Tag object. * Added quality property to the CompleteTag object. * Added bulkId property to the OnValidateTagResult. ******************************************************************************/ /** * @typedef {string} MessageType - Type of communication "Read", "Write". */ /** * @typedef {string} DataType - KEPServerEx datatype "Default", "String", "Boolean", "Char", "Byte", "Short", "Word", "Long", "DWord", "Float", "Double", "BCD", "LBCD", "Date", "LLong", "QWord". */ /** * @typedef {number[]} Data - Array of data bytes. Uint8 byte array. */ /** * @typedef {object} Tag * @property {string} Tag.address - Tag address. * @property {DataType} Tag.dataType - Kepserver data type. * @property {boolean} Tag.readOnly - Indicates permitted communication mode. * @property {integer} Tag.bulkId - Integer that identifies the group into which to bulk the tag with other tags. */ /** * @typedef {object} CompleteTag * @property {string} Tag.address - Tag address. * @property {*} Tag.value - (optional) Tag value. * @property {string} Tag.quality - (optional) Tag quality "Good", "Bad", or "Uncertain". */ /** * @typedef {object} OnProfileLoadResult * @property {string} version - Version of the driver. * @property {string} mode - Operation mode of the driver "Client", "Server". */ /** * @typedef {object} OnValidateTagResult * @property {string} address - (optional) Fixed up tag address. * @property {DataType} dataType - (optional) Fixed up Kepserver data type. Required if input dataType is "Default". * @property {boolean} readOnly - (optional) Fixed up permitted communication mode. * @property {integer} bulkId - (optional) Integer that identifies the group into which to bulk the tag with other tags. * Universal Device Driver assigns the next available bulkId, if undefined. If defined for one tag, * must define for all tags. * @property {boolean} valid - Indicates address validity. */ /** * @typedef {object} OnTransactionResult * @property {string} action - Action of the operation: "Complete", "Receive", "Fail". * @property {CompleteTag[]} tags - Array of tags (if any active) to complete. Undefined indicates tag is not complete. * @property {Data} data - The resulting data (if any) to send. Undefined indicates no data to send. */ /** Global variable for driver version */ const VERSION = "2.0"; /** Global variable for driver mode */ const MODE = "Client" /** Global variable for action */ const ACTIONCOMPLETE = "Complete" const ACTIONFAILURE = "Fail" const ACTIONRECEIVE = "Receive" /** Global variables for communication modes used in transactions */ const READ = "Read" const WRITE = "Write" /** * Retrieve driver metadata. * * @return {OnProfileLoadResult} - Driver metadata. */ function onProfileLoad() { return { version: VERSION, mode: MODE }; } /** * Validate an address. * * @param {object} info - Object containing the function arguments. * @param {Tag} info.tag - Single tag. * * @return {OnValidateTagResult} - Single tag with a populated '.valid' field set. * * * Unlike physical devices an address doesn't mean anything for the http protocol * However, we can still use this function to our advantage. The HTTP GET request * returns a JSON object. We can use this object to return multiple tag values. * Example JSON: * { * "visibility": 1000 * "wind": { * "speed": 8.38 * "direction": "north" * } * "weather": [ * { * "main": "sunny" * "description": "partly sunny" * } * { * "main": "sunny" * "description": "mostly sunny" * } * ] * } * * There are three types of addresses we can allow in this case * 1. <key> ex. Tag address = “visibility” * 2. <key>:<value> ex. Tag address = “wind:speed” * 3. <key>[<index>]:<value> ex. Tag address = “weather[0]:main” * * We will use this address to help parse the data in onData */ function onValidateTag(info) { // Format the address for validation info.tag.address = info.tag.address.toLowerCase(); /* * The regular expression to compare address to. * ^, & Starting and ending anchors respectively. The match must occur between the two anchors * [a-z]+ At least 1 or more characters between 'a' and 'z' * [0-9]+ At least 1 or more digits between 0 and 9 * ()? Whatever is in the parentheses can appear 0 or 1 times */ let regex = /^[a-z]+(\[[0-9]+\]:[a-z]+$)?(:[a-z]+)?$/; try { // Validate the address against the regular expression if (regex.test(info.tag.address)) { info.tag.valid = true; } else { info.tag.valid = false; } return info.tag } catch (e) { // Use log to provide helpful information that can assist with error resolution log("Unexpected error (onValidateTag): " + e.message); info.tag.valid = false; return info.tag; } } /** * Handle request for a tag to be completed. * * @param {object} info - Object containing the function arguments. * @param {MessageType} info.type - Communication mode for tags. Can be undefined. * @param {Tag[]} info.tags - Tags currently being processed. Can be undefined. * * @return {OnTransactionResult} - The action to take, tags to complete (if any) and/or data to send (if any). */ function onTagsRequest(info) { // Writes are not permitted if (info.type === WRITE){ return {action: ACTIONFAILURE} // data field not needed in "Failure" case } // Build the request as a string let host = "192.241.169.168"; // IP address of api.openweathermap.org // TODO: Fill in the two lines below. See README.md for details let zip = "{{ZIP_CODE}}"; // Zip code let appId = "{{API_KEY}}"; // API key let request = "GET http://" + host + "/data/2.5/weather?APPID=" + appId + "&zip=" + zip + ",us HTTP/1.1\r\n"; request += "Host: " + host + "\r\n"; request += "\r\n"; // Convert string to bytes let readData = stringToBytes(request); return { action: ACTIONRECEIVE, data: readData }; } /** * Handle incoming data. * * @param {object} info - Object containing the function arguments. * @param {MessageType} info.type - Communication mode for tags. Can be undefined. * @param {Tag[]} info.tags - Tags currently being processed. Can be undefined. * @param {Data} info.data - The incoming data. * * @return {OnTransactionResult} - The action to take, tags to complete (if any) and/or data to send (if any). */ function onData(info) { // Writes are not permitted if (info.type === WRITE){ return {action: ACTIONFAILURE} // tags field not needed in "Failure" case } // Convert the response to a string let stringResponse = ""; for (let i = 0; i < info.data.length; i++) { stringResponse += String.fromCharCode(info.data[i]); } // Get the JSON body of the response let jsonStr = stringResponse.substring(stringResponse.indexOf('{'), stringResponse.lastIndexOf('}') + 1 ); log(`JsonSubstr: ${jsonStr}`) // Parse the JSON string let jsonObj = JSON.parse(jsonStr); // Array to hold tag values let values = []; let action = ACTIONFAILURE; // Evaluate each tag's address and get the JSON value info.tags.forEach(function (tag) { let case1 = /^[a-z]+$/; // Example: Tag address matches "visibility" let case2 = /^[a-z]+:[a-z]+$/; // Example: Tag address matches "wind:speed" let case3 = /^[a-z]+\[[0-9]+\]:[a-z]+$/; // Example: Tag address matches "forecast[0]:main" // let tagValue = null; tag.value = null; if (case1.test(tag.address)) { // Get the JSON values from the provided key tag.value = jsonObj[tag.address]; } else if (case2.test(tag.address)) { // Split the address at the colon let keyValuePair = tag.address.split(':'); // Get the value by parsing the JSON with the Parent key and child key let parentValue = jsonObj[keyValuePair[0]]; tag.value = parentValue[keyValuePair[1]]; } else if (case3.test(tag.address)) { // Get the key value pair as well as the index let keyValuePair = tag.address.split(':'); let parentKey = keyValuePair[0].split('['); let index = parentKey[1].replace(']', ''); // Get the value by parsing the JSON with the Parent key, index and child key let parentValue = jsonObj[parentKey[0]][index]; tag.value = parentValue[keyValuePair[1]]; } // Determine if all tags were parsed successfully if (tag.value != undefined || tag.value != null) { action = ACTIONCOMPLETE; } }); log(JSON.stringify(info.tags)) return { action: action, tags: info.tags }; } /** * Helper function to translate string to bytes. * Required. * * @param {string} str * @return {Data} */ function stringToBytes(str) { let byteArray = []; for (let i = 0; i < str.length; i++) { let char = str.charCodeAt(i) & 0xFF; byteArray.push(char); } // return an array of bytes return byteArray; } 以上案例代码中onProfileLoad 、onValidateTag 、onTagsRequest 、onData、stringToBytes  函数名都是核心函数 分析核心函数 的作用,同时替换案例 的API 并适配了新的数据格式 : 新API地址:http://192.168.17.201:39320/?read=Test.AutoWash.HD1 新API 数据返回 格式 :{"message":"欢迎来到 OPC UA Web 服务"} Tag :取 message 字段 API 没有API_KEY ,可直接 GET 访问就有返回格式, 保留了案例代码 的核心函数结构, 输出JavaScript 代码 。再事整体检查可行性、验证结果 输出完整的 JavaScript 代码。
最新发布
10-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值