基於給定條件從陣列構造一個長度為 K 的二進位制字串


在本教程中,我們需要構造一個長度為 K 的二進位制字串,如果使用陣列元素可以得到等於 I 的子集和,則它應該在第 i 個索引處包含“1”。我們將學習兩種解決問題的方法。在第一種方法中,我們將使用動態規劃方法來檢查是否可以得到等於索引“I”的子集和。在第二種方法中,我們將使用位集查詢使用陣列元素的所有可能的和。

問題陳述 - 我們給定一個包含 N 個整數的陣列。此外,我們還給定一個整數 M 表示二進位制字串的長度。我們需要建立一個長度為 M 的二進位制字串,使其滿足以下條件。

  • 如果我們可以在陣列中找到一個和等於索引“I”的子集,則索引“I”處的字元為 1;否則為 0。

  • 索引 I 從 1 開始。

示例

Input –  arr = [1, 2] M = 4
Output – 1110

解釋

  • 和等於 1 的子集是 {1}。

  • 和等於 2 的子集是 {2}。

  • 和等於 3 的子集是 {1, 2}。

  • 我們找不到和等於 4 的子集,因此我們在第 4 個索引處放置了 0。

Input –  arr = [1, 3, 1] M = 9
Output – 111110000

解釋

我們可以建立所有可能的組合以獲得 1 到 5 之間的和。因此,前 5 個字元是 1,最後 4 個字元是 0。

Input –  arr = [2, 6, 3] M = 6
Output – 011011

解釋

使用陣列元素無法得到等於 1 和 4 的和,因此我們在第一個和第四個索引處放置了 0。

方法 1

在這種方法中,我們將使用動態規劃來檢查是否可以使用陣列元素構造等於索引“I”的和。我們將對每個索引進行檢查,並將 1 或 0 附加到二進位制字串。

演算法

  • 步驟 1 - 建立一個大小為 N 的向量,並將其初始化為整數值。此外,定義字串型別的“bin”變數,並將其初始化為空字串。

  • 步驟 2 - 使用 for 迴圈進行總共 M 次迭代,等於字串長度。

  • 步驟 3 - 在 for 迴圈中,透過傳遞陣列、N 和索引值作為引數來呼叫 isSubsetSum() 函式。

  • 步驟 4 - 如果 isSubsetSum() 函式返回 true,則將“1”附加到“bin”。否則,將“0”附加到“bin”。

  • 步驟 5 - 定義 isSubsetSum() 函式以檢查是否可以使用陣列元素得到和。

  • 步驟 5.1 - 定義一個名為 dpTable 的二維向量。

  • 步驟 5.2 - 將“dpTable[i][0]”初始化為 true,因為和為零總是可能的。這裡,“I”是索引值。

  • 步驟 5.3 - 將“dpTable[0][j]”初始化為 false,因為對於空陣列來說和是不可能的。

  • 步驟 5.4 - 現在,使用兩個巢狀迴圈。第一個迴圈從 1 到 N 進行迭代,另一個從 1 到和進行迭代。

  • 步驟 5.5 - 在 for 迴圈中,如果當前元素的值大於和,則忽略它。

  • 步驟 5.6 - 否則,包含或排除元素以得到和。

  • 步驟 5.7 - 返回包含結果的“dpTable[N][sum]”。

示例

#include <iostream>
#include <vector>
using namespace std;
// Function to check if subset-sum is possible
bool isSubsetSum(vector<int> &arr, int N, int sum){
   vector<vector<bool>> dpTable(N + 1, vector<bool>(sum + 1, false));
   
   // Base cases
   for (int i = 0; i <= N; i++)
   
      // If the sum is zero, then the answer is true
      dpTable[i][0] = true;
      
   // for an empty array, the sum is not possible
   for (int j = 1; j <= sum; j++)
      dpTable[0][j] = false;
      
   // Fill the dp table
   for (int i = 1; i <= N; i++){
      for (int j = 1; j <= sum; j++){
      
         // if the current element is greater than the sum, then we can't include it
         if (arr[i - 1] > j)
            dpTable[i][j] = dpTable[i - 1][j];
            
         // else we can either include it or exclude it to get the sum
         else
            dpTable[i][j] = dpTable[i - 1][j] || dpTable[i - 1][j - arr[i - 1]];
      }
   }
   
   // The last cell of the dp table contains the result
   return dpTable[N][sum];
}
int main(){

   // Given M
   int M = 9;
   
   // Creating the vector
   vector<int> arr = {1, 3, 1};
   
   // getting the size of the vector
   int N = arr.size();
   
   // Initializing the string
   string bin = "";
   
   // Making k iteration to construct the string of length k
   for (int i = 1; i <= M; i++){
   
      // if the subset sum is possible, then add 1 to the string, else add 0
      if (isSubsetSum(arr, N, i)){
         bin += "1";
      }
      else{
         bin += "0";
      }
   }
   
   // print the result.
   cout << "The constructed binary string of length " << M << " according to the given conditions is ";
   cout << bin;
   return 0;
}

輸出

The constructed binary string of length 9 according to the given conditions is 111110000

時間複雜度 - O(N^3),因為 isSubsetSum() 的時間複雜度為 O(N^2),並且我們從驅動程式程式碼中呼叫了 N 次。

空間複雜度 - O(N^2),因為我們在 isSubsetSum() 函式中使用了一個二維向量。

方法 2:使用位集

在這種方法中,我們將使用位集查詢透過組合陣列的不同元素的所有可能的和值。這裡,位集表示它建立一個二進位制字串。在結果位集中,它的每個位都表示是否可以得到等於特定索引的和,這正是我們需要在這裡找到的。

演算法

  • 步驟 1 - 定義陣列和 M。此外,定義 createBinaryString() 函式。

  • 步驟 2 - 接下來,定義所需長度的位集,它建立一個二進位制字串。

  • 步驟 3 - 將 bit[0] 初始化為 1,因為和為 0 總是可能的。

  • 步驟 4 - 使用 for 迴圈遍歷陣列元素

  • .
  • 步驟 5 - 首先,對“bit”執行左移運算,並使用陣列元素作為移位位數。之後,執行結果值和“bit”值的“或”運算。

  • 步驟 6 - 列印從索引 1 到 M 開始的位集值。

示例

#include <bits/stdc++.h>
using namespace std;
// function to construct the binary string
void createBinaryString(int array[], int N, int M){
   bitset<100003> bit;
   
   // Initialize with 1
   bit[0] = 1;
   
   // iterate over all the integers
   for (int i = 0; i < N; i++){
      // perform left shift by array[i], and OR with the previous value.
      bit = bit | bit << array[i];
   }
   
   // Print the binary string
   cout << "The constructed binary string of length " << M << " according to the given conditions is ";
   for (int i = 1; i <= M; i++){
      cout << bit[i];
   }
}
int main(){

   // array of integers
   int array[] = {1, 4, 2};
   int N = sizeof(array) / sizeof(array[0]);
   
   // value of M, size of the string
   int M = 8;
   createBinaryString(array, N, M);
}

輸出

The constructed binary string of length 8 according to the given conditions is 11111110

時間複雜度 - O(N),因為我們使用單個 for 迴圈。

空間複雜度 - O(N),因為我們儲存位集值。

結論

在這裡,我們優化了第二種方法,它在空間和時間複雜度方面都優於第一種方法。但是,如果您不瞭解位集,則第二種方法對於初學者來說可能難以理解。

更新於: 2023-07-28

104 次檢視

開啟您的 職業生涯

透過完成課程獲得認證

開始
廣告