如何计算这些回溯算法的时间复杂度,并且它们具有相同的时间复杂度?如果不同怎么办?请详细解释,并感谢您的帮助。
1. Hamiltonian cycle: bool hamCycleUtil(bool graph[V][V], int path[], int pos) { /* base case: If all vertices are included in Hamiltonian Cycle */ if (pos == V) { // And if there is an edge from the last included vertex to the // first vertex if ( graph[ path[pos-1] ][ path[0] ] == 1 ) return true; else return false; } // Try different vertices as a next candidate in Hamiltonian Cycle. // We don't try for 0 as we included 0 as starting point in in hamCycle() for (int v = 1; v < V; v++) { /* Check if this vertex can be added to Hamiltonian Cycle */ if (isSafe(v, graph, path, pos)) { path[pos] = v; /* recur to construct rest of the path */ if (hamCycleUtil (graph, path, pos+1) == true) return true; /* If adding vertex v doesn't lead to a solution, then remove it */ path[pos] = -1; } } /* If no vertex can be added to Hamiltonian Cycle constructed so far, then return false */ return false; } 2. Word break: a. bool wordBreak(string str) { int size = str.size(); // Base case if (size == 0) return true; // Try all prefixes of lengths from 1 to size for (int i=1; i<=size; i++) { // The parameter for dictionaryContains is str.substr(0, i) // str.substr(0, i) which is prefix (of input string) of // length 'i'. We first check whether current prefix is in // dictionary. Then we recursively check for remaining string // str.substr(i, size-i) which is suffix of length size-i if (dictionaryContains( str.substr(0, i) ) && wordBreak( str.substr(i, size-i) )) return true; } // If we have tried all prefixes and none of them worked return false; } b. String SegmentString(String input, Set<String> dict) { if (dict.contains(input)) return input; int len = input.length(); for (int i = 1; i < len; i++) { String prefix = input.substring(0, i); if (dict.contains(prefix)) { String suffix = input.substring(i, len); String segSuffix = SegmentString(suffix, dict); if (segSuffix != null) { return prefix + " " + segSuffix; } } } return null; } 3. N Queens: bool solveNQUtil(int board[N][N], int col) { /* base case: If all queens are placed then return true */ if (col >= N) return true; /* Consider this column and try placing this queen in all rows one by one */ for (int i = 0; i < N; i++) { /* Check if queen can be placed on board[i][col] */ if ( isSafe(board, i, col) ) { /* Place this queen in board[i][col] */ board[i][col] = 1; /* recur to place rest of the queens */ if ( solveNQUtil(board, col + 1) == true ) return true; /* If placing queen in board[i][col] doesn't lead to a solution then remove queen from board[i][col] */ board[i][col] = 0; // BACKTRACK } } }
实际上,我有点困惑,因为Word Break(b)的复杂度为O(2 n),但对于汉密尔顿循环而言,其复杂度不同,因此对于打印相同字符串的不同排列,然后再次解决n Queens问题也是如此。
O(N!)
O(2^N)
注意:对于WordBreak,有一个O(N ^ 2)动态编程解决方案。
T(N) = N*(T(N-1) + O(1)) T(N) = N*(N-1)*(N-2).. = O(N!)
T(N) = N*(T(N-1) + O(1))
T(N) = N*(N-1)*(N-2).. = O(N!)
类似地,在NQueens中,每次分支因子减少1或更多,但不多,因此, O(N!)
对于WordBreak,它更为复杂,但我可以给您一个大概的想法。在WordBreak中,在最坏的情况下,字符串的每个字符都有两个选择,要么是上一个单词的最后一个字母,要么是新单词的第一个字母,因此分支因子为2。因此,对于WordBreak和SegmentString而言T(N) = O(2^N)
T(N) = O(2^N)