字典序第 K 小的字串,其中包含 'a' X 次和 'b' Y 次


字典序第 K 小的字串,其中包含 'a' X 次和 'b' Y 次,是一個我們需要找到包含 X 個 'a' 和 Y 個 'b' 的第 K 小的字串的問題。這些字串按字典序排列,這意味著當我們對所有可能的字串進行排序時,最小的字串排在最前面。

在本教程中,我們將討論如何使用 C++ 解決此問題。我們將首先詳細瞭解問題陳述,然後介紹演算法方法。然後,我們將繼續使用動態規劃在 C++ 中實現解決方案。程式碼將進行詳細解釋,並逐步介紹解決問題的步驟。在本教程結束時,您將清楚地瞭解如何解決此問題以及在 C++ 中的實現細節。所以讓我們開始吧!

問題陳述

目標是識別按字典序排列的第 K 小的字串,該字串由 X 個字元 'a' 和 Y 個字元 'b' 組成。此問題的輸入是三個非負整數 X、Y 和 K。

示例 1

輸入

X=2, Y=3, K=3

輸出

abbab

解釋:包含 2 個 'a' 和 3 個 'b' 的字典序前三個最小的字串是 "aabbb"、"ababb" 和 "abbab"。因此,第三個字典序最小的字串是 "abbab"。

示例 2

輸入

X=4, Y=3, K=4

輸出

aaabbba

解釋:包含 4 個 'a' 和 3 個 'b' 的字典序第四個最小的字串是 "aaabbba"。

演算法

步驟 1. 建立一個名為 ‘fillDpArray’ 的函式,該函式接收引數 ‘X’、‘Y’、‘dp[][MAX]’、‘rows’ 和 ‘cols’

  • 使用 ‘memset’ 將整個 ‘dp’ 陣列填充為 0。

  • 將 ‘dp[0][0]’ 設定為 1。

  • 使用巢狀迴圈遍歷 ‘dp’ 陣列

    • 對於每個元素 ‘dp[i][j]’,透過新增 ‘dp[i - 1][j]’ 和 ‘dp[i][j - 1]’ 的值來更新其值。

步驟 2. 建立一個名為 ‘findKthString’ 的遞迴函式,該函式接收引數 ‘X’、‘Y’、‘K’ 和 ‘dp[][MAX]’

  • 處理基本情況

    • 如果 ‘X’ 為 0,則返回一個長度為 ‘Y’ 的 'b' 字串。

    • 如果 ‘Y’ 為 0,則返回一個長度為 ‘X’ 的 'a' 字串。

  • 檢查 ‘K’ 是否小於或等於 ‘dp[X - 1][Y]’

    • 如果為真,則返回字元 'a' 與呼叫 ‘findKthString’ 並傳入引數 ‘X - 1’、‘Y’、‘K’ 和 ‘dp’ 的結果的串聯。

  • 否則

    • 返回字元 'b' 與呼叫 ‘findKthString’ 並傳入引數 ‘X’、‘Y - 1’、‘K - dp[X - 1][Y]’ 和 ‘dp’ 的結果的串聯。

步驟 3. 在 ‘main’ 函式中

  • 宣告變數 ‘X’、‘Y’ 和 ‘K’ 以儲存使用者輸入。

  • 從使用者處讀取 ‘X’、‘Y’ 和 ‘K’ 的輸入值。

  • 驗證輸入值以確保它們滿足所需條件 ‘(X >= 0, Y >= 0, and K > 0)’。

  • 建立一個二維陣列 ‘dp[MAX][MAX]’。

  • 如果輸入值有效,則呼叫 ‘fillDpArray’ 函式並傳入引數 ‘X’、‘Y’、‘dp’、‘MAX’ 和 ‘MAX’ 以計算 ‘dp’ 陣列。

  • 檢查輸入值是否有效以及 ‘K’ 是否小於或等於 ‘dp[X][Y]’

    • 如果為真,則呼叫 ‘findKthString’ 函式並傳入引數 ‘X’、‘Y’、‘K’ 和 ‘dp’ 以獲取字典序第 K 小的字串。

    • 透過列印從 ‘findKthString’ 獲得的字串來顯示結果。

  • 否則,顯示錯誤訊息,指示輸入值無效。

現在,讓我們藉助示例檢視使用 C++ 實現上述演算法。

示例

使用 C++ 實現上述演算法

下面的 C++ 程式計算由 'a' 和 'b' 組成的字典序第 K 小的字串。它使用動態規劃來填充一個二維陣列 ‘dp’,其中包含每個 'a' 和 'b' 組合的有效字串計數。‘fillDpArray’ 函式初始化陣列並根據先前值更新其值。‘findKthString’ 函式透過遞迴檢查 ‘dp’ 中以 'a' 開頭的字串的計數,並使用更新的值遞迴呼叫自身來構造第 K 個字串。‘main’ 函式讀取輸入值,驗證它們,如果輸入有效則使用 ‘fillDpArray’ 計算結果,並顯示結果或錯誤訊息。

#include <iostream>
#include <cstring>

const int MAX = 30;
// Function to fill a 2D dp array with 0s
void fillDpArray(int X, int Y, int dp[][MAX], int rows, int cols) {
   memset(dp, 0, rows * cols * sizeof(int));
   dp[0][0] = 1;
   // Traverse the dp array and update its values
   for (int i = 0; i <= X; ++i) {
      for (int j = 0; j <= Y; ++j) {
         // Update the value of dp[i][j] based on previous values
         if (i > 0) {
            dp[i][j] += dp[i - 1][j];
         }
         if (j > 0) {
            dp[i][j] += dp[i][j - 1];
         }
      }
   }
}
// Recursive function to find the Kth lexicographically smallest string
std::string findKthString(int X, int Y, int K, int dp[][MAX]) {
   // Handle base cases where the string has only one character
   if (X == 0) {
      return std::string(Y, 'b');
   }
   if (Y == 0) {
      return std::string(X, 'a');
   }
   // If there are more than or equal to K strings which start with 'a',
   //Then the first character is 'a'
   if (K <= dp[X - 1][Y]) {
      return std::string("a") + findKthString(X - 1, Y, K, dp);
   }
   // Otherwise, the first character of the resultant string is 'b'
   else {
      return std::string("b") + findKthString(X, Y - 1, K - dp[X - 1][Y], dp);
   }
}
int main() {
   // Input variables
   int X=4, Y=3, K=4;
   // Validate the input values to ensure they meet the required criteria
   bool isValid = X >= 0 && Y >= 0 && K > 0;
   // Calculate the result
   int dp[MAX][MAX];
   if (isValid) {
      fillDpArray(X, Y, dp, MAX, MAX);
   }
   // Display the outcome or an error message
   if (isValid && K <= dp[X][Y]) {
      std::string kthString = findKthString(X, Y, K, dp);
      std::cout << "The " << K << "th lexicographically smallest string with " << X << " 'a's and " << Y << " 'b's is: " << kthString << std::endl;
   } else {
      std::cout << "Invalid input values. Please enter non-negative integers for 'a's and 'b's, and a positive integer for K." << std::endl;
   }
   return 0;
}

輸出

The 4th lexicographically smallest string with 4 'a's and 3 'b's is: aaabbba

結論

總而言之,查詢具有給定 'a' 和 'b' 數量的字典序第 K 小的字串需要使用動態規劃。透過填充二維 DP 陣列並使用遞迴函式,我們可以找到字典序第 K 小的字串。此演算法的時間複雜度為 O(X * Y),其中 X 和 Y 分別是 'a' 和 'b' 的數量。此演算法可以應用於需要查詢字典序第 K 小的字串的各種問題。

更新於: 2023年9月8日

102 次檢視

開啟你的 職業生涯

透過完成課程獲得認證

開始學習
廣告

© . All rights reserved.