生成在給定關係下從 1 到 N 的字典序最小的排列


在本主題中,我們尋求從 1 到 N 的受關係約束的字典序最小排列。該關係描述了排列的某些元件的相對順序。我們透過根據此關係仔細組織數字來確保生成的排列在字典序比較時儘可能小。為了實現數字的最小可能排列,必須找到既滿足關係約束又實現最小字典序的最佳序列。為了有效地產生預期結果,該過程需要徹底的分析和元素選擇。

使用的方法

  • 貪心演算法

  • 回溯法

貪心演算法

在使用貪心演算法生成給定關係下從 1 到 N 的字典序最小排列時,我們採用一種系統的方法。在每個步驟中,我們重複選擇剩餘候選者中滿足指定關係的最小元素。將此最小有效元素新增到排列中,然後將其丟棄。此過程與後續的最小元素重複進行,確保它們與先前新增的元素保持所需的關係。透過這種方式,我們始終選擇最小的有效元素,並在保持給定關係的同時生成最小的字典序排列。重複此過程,直到所有元素都包含在最終排列中,從而確保達到滿足字典序和指定關係的預期結果。

演算法

  • 初始化一個空列表來儲存生成的排列。

  • 根據給定的關係按升序排列元素。

  • 迭代遍歷已排序的元素。

  • 對於每個元素,確定將其包含在排列中是否會滿足與已新增元素的關係。

  • 如果滿足關係,則將元素新增到排列列表中並將其丟棄。

  • 重複步驟 4-5,直到排列包含所有元素。

  • 生成的列表表示從 1 到 N 的字典序最小的排列。

示例

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

bool checkRelation(const vector<int>& permutation, int num) {
    
    return true; 
}

vector<int> generateLexicographicallySmallestPermutation(int N) {
    vector<int> permutation;
    for (int i = 1; i <= N; ++i) {
        permutation.push_back(i);
    }

    sort(permutation.begin(), permutation.end(), [](int a, int b) {
        return checkRelation({a}, b);
    });

    return permutation;
}

int main() {
    int N = 5; 

    vector<int> result = generateLexicographicallySmallestPermutation(N);

    cout << "Lexicographically Smallest Permutation: ";
    for (int num : result) {
        cout << num << " ";
    }
    cout << endl;

    return 0;
}

輸出

Lexicographically Smallest Permutation: 5 4 3 2 1 

回溯法

回溯法是一種有效的演算法策略,用於在保持特定關係的同時查詢從 1 到 N 的字典序最小排列。它採用一種系統的方法,為排列中的每個位置做出決策,並考慮所有可能性。如果選擇的元素導致無效解,則該方法回溯到前一個位置並考慮其他選項。透過徹底探索所有排列並不斷改進排列,它最終確定滿足所需關係的最佳配置。回溯法確保了徹底的搜尋,以便找到具有最小字典序的最佳排列。這種方法在可能結果很多的情況下特別有用,因為它能夠有效地找到所需的結果,同時修剪無效的選項。

演算法

  • 識別並確定給定的關係,該關係指定排列中元件的相對順序。

  • 建立必要的變數和資料結構來跟蹤當前排列和其他約束。

  • 選擇排列的第一個元素以啟動回溯過程。

  • 對於排列中的每個位置,嘗試所有滿足指定關係的元素。

  • 確保選擇的元素不會違反任何規則或破壞關係。

  • 如果元素有效,則透過新增選擇的元素來更新排列,並移動到下一個位置。

  • 遞迴地移動到排列中的下一個位置,並重復步驟 4 到 6 以繼續回溯過程。

  • 當所有位置都填滿時,當前排列是字典序最小排列的候選者。

  • 如果找到更小的排列,則將當前排列與到目前為止找到的最佳排列進行比較,並更新結果。

  • 刪除新增到當前排列中的最後一個元素,並返回到前一個位置以考慮其他選項。

  • 探索所有組合,直到所有選項都已考慮。

  • 回溯過程完成後,返回字典序最小排列作為最終輸出。

示例

#include <iostream>
#include <vector>
using namespace std;

vector<int> permutation;
vector<bool> used;

bool isRelationSatisfied(int a, int b) {
    return a > b;
}

void generatePermutation(int N) {
    if (permutation.size() == N) {
        for (int num : permutation) {
            cout << num << " ";
        }
        cout << endl;
        return;
    }

    for (int i = 1; i <= N; i++) {
        if (!used[i] && (permutation.empty() || isRelationSatisfied(permutation.back(), i))) {
            permutation.push_back(i);
            used[i] = true;
            generatePermutation(N);
            permutation.pop_back();
            used[i] = false;
        }
    }
}

int main() {
    int N = 4;
    used.resize(N + 1, false);
    generatePermutation(N);
    return 0;
}

輸出

4 3 2 1

結論

為了生成滿足特定關係的從 1 到 N 的字典序最小排列,可以使用貪心演算法或回溯法。貪心演算法透過在每一步選擇最小的有效元素來有效地生成最小排列。另一方面,回溯法仔細探索所有可能性以找到最佳的、字典序最小的排列。這兩種方法都有各自的優點,具體取決於關係的複雜性和有效排列的數量。透過仔細分析問題並選擇正確的策略,我們可以輕鬆生成滿足指定關係的所需字典序最小排列。

更新於:2023年8月2日

408 次瀏覽

開啟你的職業生涯

完成課程獲得認證

開始學習
廣告
© . All rights reserved.