diff --git a/CMakeLists.txt b/CMakeLists.txt
index ee86b3ff..75cbbe62 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1586,6 +1586,7 @@ add_task(valid-palindrome)
add_task(valid-palindrome-ii)
add_task(valid-palindrome-iv)
add_task(valid-parentheses)
+add_task(valid-parenthesis-string)
add_task(valid-perfect-square)
add_task(valid-sudoku)
add_task(valid-triangle-number)
diff --git a/PROBLEM_LIST.md b/PROBLEM_LIST.md
index 8b01708c..e8a2f94d 100644
--- a/PROBLEM_LIST.md
+++ b/PROBLEM_LIST.md
@@ -562,6 +562,7 @@
| 671. | [Second Minimum Node In a Binary Tree](https://leetcode.com/problems/second-minimum-node-in-a-binary-tree/) | [C++](./solutions/second-minimum-node-in-a-binary-tree/solution.hpp) | | | | |
| 673. | [Number of Longest Increasing Subsequence](https://leetcode.com/problems/number-of-longest-increasing-subsequence/) | [C++](./solutions/number-of-longest-increasing-subsequence/solution.hpp) | | | | |
| 674. | [Longest Continuous Increasing Subsequence](https://leetcode.com/problems/longest-continuous-increasing-subsequence/) | [C++](./solutions/longest-continuous-increasing-subsequence/solution.hpp) | | | | |
+| 678. | [Valid Parenthesis String](https://leetcode.com/problems/valid-parenthesis-string/) | [C++](./solutions/valid-parenthesis-string/solution.hpp) | | O(N) / O(1)| | |
| 680. | [Valid Palindrome II](https://leetcode.com/problems/valid-palindrome-ii/) | [C++](./solutions/valid-palindrome-ii/solution.hpp) | | | | |
| 682. | [Baseball Game](https://leetcode.com/problems/baseball-game/) | [C++](./solutions/baseball-game/solution.hpp) | | | | |
| 684. | [Redundant Connection](https://leetcode.com/problems/redundant-connection/) | [C++](./solutions/redundant-connection/solution.hpp) | | O(N) / O(N)| | |
diff --git a/README.md b/README.md
index 1c3f6f65..596e8c5b 100644
--- a/README.md
+++ b/README.md
@@ -656,6 +656,7 @@ Due to [restrictions](https://github.com/orgs/community/discussions/23920) on th
| 671. | [Second Minimum Node In a Binary Tree](https://leetcode.com/problems/second-minimum-node-in-a-binary-tree/) | [C++](./solutions/second-minimum-node-in-a-binary-tree/solution.hpp) | | | | |
| 673. | [Number of Longest Increasing Subsequence](https://leetcode.com/problems/number-of-longest-increasing-subsequence/) | [C++](./solutions/number-of-longest-increasing-subsequence/solution.hpp) | | | | |
| 674. | [Longest Continuous Increasing Subsequence](https://leetcode.com/problems/longest-continuous-increasing-subsequence/) | [C++](./solutions/longest-continuous-increasing-subsequence/solution.hpp) | | | | |
+| 678. | [Valid Parenthesis String](https://leetcode.com/problems/valid-parenthesis-string/) | [C++](./solutions/valid-parenthesis-string/solution.hpp) | | O(N) / O(1)| | |
| 680. | [Valid Palindrome II](https://leetcode.com/problems/valid-palindrome-ii/) | [C++](./solutions/valid-palindrome-ii/solution.hpp) | | | | |
| 682. | [Baseball Game](https://leetcode.com/problems/baseball-game/) | [C++](./solutions/baseball-game/solution.hpp) | | | | |
| 684. | [Redundant Connection](https://leetcode.com/problems/redundant-connection/) | [C++](./solutions/redundant-connection/solution.hpp) | | O(N) / O(N)| | |
@@ -1095,4 +1096,3 @@ Due to [restrictions](https://github.com/orgs/community/discussions/23920) on th
| 1381. | [Design a Stack With Increment Operation](https://leetcode.com/problems/design-a-stack-with-increment-operation/) | [C++](./solutions/design-a-stack-with-increment-operation/solution.hpp) | | O(Q) / O(Q)| | |
| 1382. | [Balance a Binary Search Tree](https://leetcode.com/problems/balance-a-binary-search-tree/) | [C++](./solutions/balance-a-binary-search-tree/solution.hpp) | | O(N) / O(N)| | |
| 1383. | [Maximum Performance of a Team](https://leetcode.com/problems/maximum-performance-of-a-team/) | [C++](./solutions/maximum-performance-of-a-team/solution.hpp) | | | | |
-| 1385. | [Find the Distance Value Between Two Arrays](https://leetcode.com/problems/find-the-distance-value-between-two-arrays/) | [C++](./solutions/find-the-distance-value-between-two-arrays/solution.hpp) | | | | |
diff --git a/solutions/valid-parenthesis-string/CMakeLists.txt b/solutions/valid-parenthesis-string/CMakeLists.txt
new file mode 100644
index 00000000..edcea951
--- /dev/null
+++ b/solutions/valid-parenthesis-string/CMakeLists.txt
@@ -0,0 +1 @@
+add_catch(test_valid_parenthesis_string test.cpp)
diff --git a/solutions/valid-parenthesis-string/solution.hpp b/solutions/valid-parenthesis-string/solution.hpp
new file mode 100644
index 00000000..9227cae8
--- /dev/null
+++ b/solutions/valid-parenthesis-string/solution.hpp
@@ -0,0 +1,75 @@
+#pragma once
+
+#include
+#include
+
+// Time: O(N)
+// Space: O(1)
+
+namespace stack {
+
+// Time: O(N)
+// Space: O(N)
+class Solution {
+public:
+ static bool checkValidString(std::string s) {
+ std::stack openBrackets, asterisks;
+ for (int i = 0; i < std::ssize(s); ++i) {
+ if (s[i] == '(') {
+ openBrackets.push(i);
+ } else if (s[i] == '*') {
+ asterisks.push(i);
+ } else if (s[i] == ')') {
+ if (!openBrackets.empty()) {
+ openBrackets.pop();
+ } else if (!asterisks.empty()) {
+ asterisks.pop();
+ } else {
+ return false;
+ }
+ } else {
+ throw;
+ }
+ }
+
+ while (!openBrackets.empty() && !asterisks.empty()) {
+ if (asterisks.top() < openBrackets.top()) {
+ return false;
+ }
+ openBrackets.pop();
+ asterisks.pop();
+ }
+ return openBrackets.empty();
+ }
+};
+
+} // namespace stack
+
+namespace opt {
+
+// Time: O(N)
+// Space: O(1)
+class Solution {
+public:
+ static bool checkValidString(std::string s) {
+ int open = 0, close = 0;
+ for (auto c : s) {
+ if (c == '(') {
+ ++open, ++close;
+ } else if (c == ')') {
+ --open, --close;
+ } else if (c == '*') {
+ --open, ++close;
+ } else {
+ throw;
+ }
+ open = std::max(0, open);
+ if (close < 0) {
+ return false;
+ }
+ }
+ return open == 0;
+ }
+};
+
+} // namespace opt
diff --git a/solutions/valid-parenthesis-string/test.cpp b/solutions/valid-parenthesis-string/test.cpp
new file mode 100644
index 00000000..08c06876
--- /dev/null
+++ b/solutions/valid-parenthesis-string/test.cpp
@@ -0,0 +1,39 @@
+#include
+
+#include
+
+TEST_CASE("Simple") {
+ struct TestCase {
+ std::string s;
+ bool expected;
+ };
+
+ std::vector test_cases{
+ {
+ .s = "()",
+ .expected = true,
+ },
+ {
+ .s = "(*)",
+ .expected = true,
+ },
+ {
+ .s = "(*))",
+ .expected = true,
+ },
+ };
+
+ SECTION("STACK") {
+ for (const auto &[s, expected] : test_cases) {
+ const auto actual = stack::Solution::checkValidString(s);
+ REQUIRE(expected == actual);
+ }
+ }
+
+ SECTION("MEMORY OPTIMIZED") {
+ for (const auto &[s, expected] : test_cases) {
+ const auto actual = opt::Solution::checkValidString(s);
+ REQUIRE(expected == actual);
+ }
+ }
+}