Я пишу алгоритм поиска с возвратом, я думаю, что я пишу правильно, но результат неправильный. Я пошел на отладку и обнаружил, что выполнение : Когда программа выполняет это предложение в цикле for, иногда она напрямую пропускает следующий оператор в цикле for.
Вопрос здесь: Последовательность перестановок
Я написал среду отладки, которую можно запускать напрямую.
Мой ответ здесь:
class Solution {
public:
int index = 0, N, K;
string ans;
string getPermutation(int n, int k) {
N = n;
K = k;
string str;
backtrace(str, 0);
return ans;
}
void backtrace(string &str, int start) {
if (start == N) {
index++;
if (index == K) {
ans = str;
}
return;
}
for (int i = start; i < N; i++) {
if (index == K) {
return;
}
string temp = str; //For loop to this sentence will not execute the following statement
str += to_string(i + 1);
backtrace(str, i + 1);
str = temp;
}
}
};
int nn(int n) {
if (n == 1) {
return 1;
}
return nn(n - 1) * n;
}
int main() {
Solution so;
for (int i = 1; i <= nn(3); i++) {
cout << so.getPermutation(3, i) << endl;
}
system("pause");
}
Я не уверен, проблема ли это C ++ или моя, или это может быть мой алгоритм , но я проверял это много раз.
1 ответ
Мое предыдущее мнение было неверным, @ Игорь Тандетник поправил меня. Эта задача требует немного математических навыков, иначе время откроется. Спасибо за помощь @john и @Igor Tandetnik. Мой окончательный код здесь:
class Solution {
private:
vector<int> hash;
vector<int> factorial;
bool flag = true;
void dfs(int cur, int n, int &k, string &ret, int &cnt, string path){
if(cur == n){
ret = path;
flag = false;
return;
}
int temp = factorial[n-cur-1];
for(int i=0; i<n; i++){
if(hash[i] && flag){
if(temp < k ){
k = k - temp;
continue;
}
path.push_back(i+1+'0');
hash[i] = 0;
dfs(cur+1,n,k,ret,cnt,path);
hash[i] = 1;
path.pop_back();
}
}
}
public:
string getPermutation(int n, int k) {
//calculate the factorial
if(n == 1) return "1";
factorial.resize(n);
factorial[0] = 1;
factorial[1] = 1;
if(n > 2){
for(int i=2; i<n; i++){
factorial[i] = i * factorial[i-1];
}
}
string ret;
string path;
hash.resize(n,1);
int cnt = 0;
dfs(0,n,k,ret,cnt,path);
return ret;
}
};
Предполагая, что n = 4, k = 17, мы можем знать, что 17-я перестановка равна [3,4,1,2]. Чтобы найти его, нам нужно обрезать ключевые узлы. Как судить? Как показано на рисунке, когда мы начинаем поиск, мы посещаем пурпурный узел «1» и замечаем, что если мы продолжаем посещать (глубокий поиск) в это время, это фактически бессмысленно, потому что есть не более 3 из этого узел! = 6 полных перестановок и комбинаций, и мы ищем 17-е, 6 <17, поэтому мы сокращаем напрямую; посетите пурпурный узел «2», видно то же самое, на этом узле нужно обрезать; посетите пурпурный узел "3" ", теперь, когда выполнены условия, 6> 5, вам нужно искать вниз. (Обратите внимание, что простой метод подсчета заключается в том, что, когда узел нужно обрезать, нам нужно обновить значение k, k = k - узел соответствует факториальному номеру).
Автор: edward_wang
Похожие вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.