2 solutions ^^
Idea explanation\n\n\n\n\nGrey nodes - internal nodes, pink (#) - external nodes. \nNote that in any legit binary tree number(internal)-number(external) == -1.\
**Idea explanation**\n\n![image](https://assets.leetcode.com/users/images/5cb45b50-f19f-43ee-b710-e82d389980b5_1618330517.505618.png)\n<br>\n\nGrey nodes - internal nodes, pink (`#`) - external nodes. \nNote that in any legit **binary tree** `number(internal)-number(external) == -1`.\nHere\'s how it\'s stated and proven [in Sedgwick\'s book](http://index-of.co.uk/Algorithms/Algorithms_in_C_-_Sedgewick.pdf)\n<br>\n\n![image](https://assets.leetcode.com/users/images/5d3a521f-51bd-49d6-bebb-412f950944fc_1618329065.3934822.png)\n\n<br>\n\nMoreover if you have a list of internal and external nodes (in preorder) so that `number(internal)-number(external) == -1` you can cook up a binary tree using "greedy" approach (put current node in the next available slot according to the preorder).\n<br>\n\n![image](https://assets.leetcode.com/users/images/4f985e0b-f6ea-4e37-ae42-12ed935ed436_1618337397.7040095.png)\n\n<br>\n\nIf you have intoduced some internal and external nodes `number(internal)-number(external)+1` counts the number of **vacant slots** (green rectangles) as every internal node(except for the root) introduces `2-1=1` extra slot while every external node deletes `1` slot (parent root introduces `2` slots). If `number(internal)-number(external) == -1` you have no more slots left.\nBut if you still have nodes left in the list you can\'t fit them into the constructed tree - you have no vacant slots left so you can\'t construct the binary tree from such a list.\n>  The algo is as follows: traverse the list keeping track of the difference between the number of internal nodes (not `#`) and external (`#`) ones.   When `number(internal)-number(external) == -1` check whether you have more nodes in the list. If yes, return `false`, if no - return `true`.\nIf `number(internal)-number(external) == -1` is never fullfilled than return `false`.\nIn other words the only time when `number(internal)-number(external) == -1` is at the end of the list !\n\n**Counter:** time `O(N)`, space `O(1)`\n```\nbool isValidSerialization(string p) \n{\n\tint c{0};\n\tfor(stringstream ss{p}; getline(ss, p, \',\'); )\n\t\tif(p[0]==\'#\' ? --c : ++c, c==-1)\n\t\t\treturn ss.eof();\n\treturn c==-1;\n}\n```\n||\n```\nbool isValidSerialization(string p) \n{\n    stringstream ss{p};\n\tint c{0};\n\tfor( ; c!=-1 and !ss.eof(); getline(ss, p, \',\'), p[0]==\'#\' ? --c : ++c);\n\treturn c==-1 and ss.eof();\n}\n```\n**Stack:** time `O(N)`, space `O(N)`\n\nYou can keep track current position in the tree with the help of the stack. In this way you can **simulate** insertions into binary tree.\n\n<br>\n\n![image](https://assets.leetcode.com/users/images/3803048b-09cd-4955-a909-bb43cf4269df_1618324945.9085522.png)\n\n<br>\n\n```\nbool isValidSerialization(string p) \n{\n\tstack<int> s;\n\tfor(stringstream ss{p}; getline(ss, p, \',\'); )\n\t\tif(p[0]==\'#\')\n\t\t{\n\t\t\tfor( ; !empty(s) and s.top(); s.pop());\n\t\t\tif(empty(s)) return ss.eof();\n\t\t\ts.top()=1;\n\t\t}\n\t\telse\n\t\t\ts.push(0);\n\treturn empty(s);\n}\n```
['C', 'C++']