Как рассчитать временную сложность алгоритма возврата?

Как рассчитать временную сложность для этих алгоритмов поиска с возвратом и имеют ли они одинаковую временную сложность? Если отличается как? Пожалуйста, объясните подробно и спасибо за помощь.

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 (2n), но для гамильтонового цикла она отличается, как и для печати разных перестановок одной и той же строки, а затем снова для решение проблемы с n ферзями.


person da3m0n    schedule 18.11.2013    source источник
comment
Если вы сосредоточитесь на фактическом возврате (или, скорее, возможностях ветвления на каждом шаге), вы увидите только экспоненциальную сложность. Однако, если есть только так много возможных состояний для исследования с возвратом, это все, что он может исследовать. Если вы гарантируете, что ваш алгоритм посещает каждое возможное состояние только один раз (и с постоянной границей времени для каждого состояния), то количество возможных состояний для исследования теперь является верхней границей временной сложности — независимо от того, использует ли ваш алгоритм поиск с возвратом.   -  person Steve314    schedule 18.11.2013


Ответы (2)


Короче говоря:

  1. Гамильтонов цикл: O(N!) в худшем случае
  2. WordBreak и StringSegment: O(2^N)
  3. NQueens : O(N!)

Примечание. Для WordBreak существует решение для динамического программирования O(N^2).


Подробнее:

  1. В гамильтоновом цикле при каждом рекурсивном вызове в худшем случае выбирается одна из оставшихся вершин. В каждом рекурсивном вызове коэффициент ветвления уменьшается на 1. Рекурсию в этом случае можно рассматривать как n вложенных циклов, где в каждом цикле количество итераций уменьшается на единицу. Следовательно, временная сложность определяется как:

    T(N) = N*(T(N-1) + O(1))
    T(N) = N*(N-1)*(N-2).. = O(N!)

  2. Точно так же в NQueens каждый раз, когда коэффициент ветвления уменьшается на 1 или более, но не намного, отсюда и верхняя граница O(N!)

  3. Для WordBreak это сложнее, но я могу дать вам примерное представление. В WordBreak у каждого символа строки в худшем случае есть два варианта: либо быть последней буквой в предыдущем слове, либо первой буквой нового слова, следовательно, коэффициент ветвления равен 2. Следовательно, как для WordBreak, так и для SegmentString T(N) = O(2^N)

person Vikram Bhat    schedule 18.11.2013
comment
Пожалуйста, объясните, а также различайте временную сложность для части b Word Break с частью a. - person da3m0n; 18.11.2013
comment
Извините за первый ответ, я недооценил временную сложность WordBreak - person Vikram Bhat; 18.11.2013

Алгоритм поиска с возвратом:

задача с n-ферзями:O(n!)

задача раскраски графа:O(nm^n)//где n=no. вершины, m=нет. используемого цвета

цикл Гамильтона:O(N!)

WordBreak и StringSegment:O(2^N)

проблема суммы подмножества:O(nW)

person Shyam Bhimani    schedule 16.12.2017
comment
Не должна ли сложность проблемы суммы подмножества с использованием поиска с возвратом быть O(2^(N/2) )? - person Kewal Shah; 11.11.2018