题目
思路
使用dfs进行搜索剪枝,时间复杂度是O(n),分析如下:结合代码:
- 首先,如果当前代码中的ok是true,则整个递归返回;接下来都是ok是false的情况
- 如果s[i]>7,则直接返回,一种选择
- 若4<s[i]<=7,则当前只能有一种选择-7,dfs回溯之后,不可能选择4,所以只有一种选择
- 如果s[i]<=4,则先选择4,后选择7,看似有两种选择:
a. 选择4,如果成功,直接返回
b. 如果不成功,选择7,这时候ok 一定是true,所以如果sum7>0,则之后就直接返回了;如果sum7==0,没法向下进行,直接返回false,回溯
所以每个位置最多向上回溯一次,之后就会结束递归,总的时间复杂度是O(N)
代码
class p95B {
public:
string ans, s;
bool dfs(int id, int sum4, int sum7, bool ok) {
//ok 代表可以随意填剩下的了
if (id >= s.size()) return 1;
if (ok) {
ans.append(sum4, '4');
ans.append(sum7, '7');
return 1;
}
if (s[id] <= '4' && sum4) {
ans.push_back('4');
if (dfs(id + 1, sum4 - 1, sum7, s[id] < '4')) return true;
ans.pop_back();
}
if (s[id] <= '7' && sum7) {
ans.push_back('7');
if (dfs(id + 1, sum4, sum7 - 1, s[id] < '7')) return 1;
ans.pop_back();
}
return 0;
}
void solve() {
cin >> s;
ans.clear();
int n = s.size();
if(n%2||!dfs(0,n/2,n/2,0)){
ans.append((n+2)/2,'4');
ans.append((n+2)/2,'7');
cout<<ans<<endl;
}
else cout<<ans<<endl;
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
p95B ans;
ans.solve();
return 0;
}