0

I'm doing leetcode 297. Serialize and Deserialize Binary Tree, and I'm trying to solve it with std::sregex_token_iterator (other than using std::istringstream/std::ostringstream).

My solution is to append a whitespace when reading(serializing) a TreeNode value into the string, and using whitespace as delimieter when deserializing.

But due to "Definition for a binary tree node" (TreeNode(int x) : val(x), left(NULL), right(NULL) {}), I have to cast elements pointed by sregex_token_iterator to ints.

I have read cppreference std::regex_token_iterator, and I'm still not sure if the type of the element dereferenced by sregex_token_iterator is std::string. (At first I thought it is definitely std::string type.)

But error occured when I tried to do some attempts, like:

int val = stoi(*it);
TreeNode* node = new TreeNode(val);

or

string item = *it;
int val = stoi(item);
TreeNode* node = new TreeNode(val);

which all result in error

terminate called after throwing an instance of 'std::invalid_argument'
  what():  stoi

And I've googled, but I didn't find question simiar to mine.

Below is my code:

/*
 * @lc app=leetcode id=297 lang=cpp
 *
 * [297] Serialize and Deserialize Binary Tree
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Codec {
public:
    // Encodes a tree to a single string.
    string serialize(TreeNode* root) {
        string data;
        serialize(root, data);
        return data;
    }
   
    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
        // whitespace
        regex rgx {"\\s+"};
        auto it = sregex_token_iterator {data.begin(), data.end(), rgx, -1};
        auto it_end = sregex_token_iterator();
        TreeNode* root = deserialize(data, rgx, it, it_end);
        return root;
    }
private:
    void serialize(TreeNode* node, string& data) {
        if (!node) {
            data += "# ";
            return;
        }
        data += node->val;
        data += " ";
        serialize(node->left);
        serialize(node->right);
    }

    TreeNode* deserialize(string& data, regex& rgx, sregex_token_iterator& it, sregex_token_iterator& it_end) {
        if (*it == "#") {
            return nullptr;
        }
        /*** Error Here: ***/
        // int val = stoi(*it);
        string item = *it;
        int val = stoi(item);
        TreeNode* node = new TreeNode(val);

        /* left tree */
        ++it;
        node->left = deserialize(data, rgx, it, it_end);
        /* right tree */
        ++it;
        node->right = deserialize(data, rgx, it, it_end);
        return node;
    }
};
// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));
// @lc code=end

Is there any way to solve this casting problem without changing much of the code above? (i.e. do not change deserialize function from recursive one to iterative one.)

/*** Edit ***/

But after I revised it according to @Cubbi with data += to_string(node->val), another error occured:

Line 2778: Char 16: runtime error: reference binding to null pointer of type
'const std::__cxx11::regex_token_iterator<__gnu_cxx::__normal_iterator<
const char *, std::__cxx11::basic_string<char>>, char, std::__cxx11::regex_traits<char>>::
value_type' (aka 'const sub_match<__gnu_cxx::__normal_iterator<const char *, std::__cxx11::
basic_string<char>>>') (regex.h)

, but I have initialized it and it_end (while in my solution it_end is not necessary) and still cannot find any possible errors.

Another try, adding:

if (it == it_end) {
   return nullptr;
}

in deserialize() recursive function, but surprisingly get an error with respect to vector which I didn't use it in my code.

Line 1056: Char 34: runtime error: addition of unsigned offset to 0x6080000000a0 overflowed to 0x608000000058 (stl_vector.h)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:1061:34
Learning
  • 13
  • 4

1 Answers1

1

The error says the contents of the string are not parseable as an integer. Because this line

    data += node->val;

is not doing what you think it's doing. Append a to_string(node->val) and then you will be able to reverse it with stoi.

Cubbi
  • 46,567
  • 13
  • 103
  • 169
  • But after I revised it, another error occured: – Learning Jul 14 '22 at 23:17
  • @Learning "binding to null pointer" was because you keep incrementing and dereferencing `it` without ever checking if it reached `it_end`. What debugger are you using that doesn't show this? – Cubbi Jul 15 '22 at 03:21
  • @Learning also, before you go that far, look, in debugger, at what `serialize` is returning. even with a to_string, It is not what deserialize expects – Cubbi Jul 15 '22 at 03:26