Ваше решение является примером возврата. Он не подчиняется перекрывающемуся свойству . Ссылка на решение dp, которой вы поделились, содержит правильный подход. Это также легко реализовать как recusrion, а также дп.
Если вы все еще хотите придерживаться своего подхода (или чего-то подобного), вы должны настроить свой путь, чтобы подчиняться свойству перекрывающихся подзадач. Я имею в виду подход, который вы, возможно, можете рассмотреть:
1. Start from the end of the given string.
2. Instead of a stack, maintain the count of left and right paranthesis.
3. Psudocode for recursion:
bool foo(pos,count_left_paranthesis,count_right_paranthesis):
if count_left_paranthesis > :
return false;
if (pos < 0)
return count_left_paranthesis == count_right_paranthesis;
if string[pos] == '(':
return foo(pos-1,count_left_paranthesis+1,count_right_paranthesis);
else if string[pos] == '):
return foo(pos-1,count_left_paranthesis,count_right_paranthesis+1);
else: // string[pos] = '*'
return foo(pos-1,count_left_paranthesis,count_right_paranthesis)
|| foo(pos-1,count_left_paranthesis,count_right_paranthesis+1)
|| foo(pos-1,count_left_paranthesis+1,count_right_paranthesis)
4. Memoize the results of the subproblems.
Хотя существуют более простые решения.
Я сам попробовал вышеизложенное, и вот рабочее решение. Удивительно, но это даже было принято.
class Solution {
public:
map<vector<int>,bool> dp;
bool foo(const string& s, int pos, int lc, int rc)
{
if (lc > rc) return false;
if (pos<0)
{
return lc == rc;
}
vector<int> v = {pos,lc,rc};
if (dp.find(v) != dp.end()) return dp[v];
if (s[pos] == '(')
{
return dp[v] = foo(s,pos-1,lc+1,rc);
}
else if (s[pos] == ')')
{
return dp[v] = foo(s,pos-1,lc,rc+1);
}
else
{
return dp[v] = (foo(s,pos-1,lc,rc) || foo(s,pos-1,lc+1,rc) || foo(s,pos-1,lc,rc+1));
}
}
bool checkValidString(string s) {
return foo(s,s.size()-1,0,0);
}
};
- Еще одна быстрая оптимизация может заключаться в использовании вектора для запоминания, но я ленивый.
- хорошо, вы даже можете начать с самого начала строки. Начать со спины было проще для меня.
Примечание: Это ни в коем случае не самый эффективный способ решения проблемы, это просто помочь оператору с рекурсивное решение, а затем придумать dp-решение со средствами запоминания (или « кэширование результатов подзадач »)