二進位制字串中最長非遞減子序列


在這個問題中,我們需要找到給定字串中最長的非遞減子序列。

非遞減的意思是字元應該相同或按降序排列。由於二進位制字串只包含“0”和“1”,因此結果字串應該以“1”開頭,以“0”結尾,或者以“0”或“1”開頭和結尾。

為了解決這個問題,我們將計算字串每個位置的字首“1”和字尾“0”,並找到字首“1”和字尾“0”的最大和。

問題陳述 - 我們給定一個二進位制字串str。我們需要找到給定字串中最長的非遞減子序列。

示例

Input –  str = "010100"
Output – 4

解釋

最長的非遞減子序列是“1100”。

Input –  str = "010110010"
Output – 6

解釋

最長的非遞減子序列是“111000”。

Input –  str = ‘00000000’
Output – 8

解釋

最長的非遞減子序列是“00000000”,它等於給定的字串。

方法一

在這種方法中,我們將為每個索引儲存字首“1”和字尾“0”的計數。之後,我們從兩個陣列的相同索引獲取值,將它們相加,並找到最大和。

演算法

  • 步驟1 - 定義pre1s和suffix0s陣列來儲存字首1和字尾0。並將所有陣列元素初始化為0。

  • 步驟2 - 使用for迴圈遍歷字串並計算每個索引的字首1。如果i > 0,則將前一個元素的值新增到當前元素。

  • 步驟3 - 如果當前字元是“1”,則將pre1s[i]的當前值加1。

  • 步驟4 - 現在,計算給定字串中的字尾0。從末尾開始遍歷字串。

  • 步驟5 - 如果“i”的值不等於“n – 1”,則獲取“i + 1”元素的值並將其新增到當前元素。

  • 步驟6 - 如果當前元素是“0”,則將當前元素加1。

  • 步驟7 - 現在,將“res”變數初始化為0。

  • 步驟8 - 使用迴圈遍歷“pre1s”和“suffix0s”。

  • 步驟9 - 從“pre1s”和“suffix0s”陣列的第i個索引獲取值,並將它們相加。如果“sum”大於“res”變數的當前值,則將“res”變數的值更改為“sum”值。

  • 步驟10 - 返回“res”變數的值。

示例

對於輸入“010100”,字首陣列將為[0, 1, 1, 2, 2, 2],字尾0陣列將為[4, 3, 3, 2, 2, 1]。和陣列將為[4, 4, 4, 4, 4, 3],和陣列中的最大值為4。所以答案將是4。

#include <bits/stdc++.h>
using namespace std;
int getMaxLength(string str, int n){
   // To store the prefix count of '1's and suffix count of '0's
   int pre1s[n] = {0},
      suffix0s[n] = {0};
   for (int i = 0; i < n; i++){
   
      // get the prefix count of '1's
      if (i > 0){
         pre1s[i] += pre1s[i - 1];
      }
      
      // If the current character is '1', then update the pre1s array by adding 1; else, keep it as it is.
      if (str[i] == '1'){
         pre1s[i] += 1;
      }
   }
   
   // get suffix count of '0's
   for (int i = n - 1; i >= 0; i--) {
   
      // add the suffix count of '0's
      if (i != n - 1)
         suffix0s[i] += suffix0s[i + 1];
         
      // If the current character is '0', then update the suffix0s array by adding 1; else, keep it as it is.
      if (str[i] == '0')
         suffix0s[i] += 1;
   }
   
   // to store the final result value
   int res = 0;
   
   // iterate over the pre1s[] and suffix0s[] array and find the maximum value of pre1s[i] + suffix0s[i]
   for (int i = 0; i < n; i++){
      res = max(res, pre1s[i] + suffix0s[i]);
   }
   
   // Return the result
   return res;
}

// Driver Code
int main(){
   string str = "010100";
   int N = str.length();
   cout << "The length of the longest non-increasing subsequence in the given binary string is - " << getMaxLength(str, N);
   return 0;
}

輸出

The length of the longest non-increasing subsequence in the given binary string is - 4

時間複雜度 - O(N),因為我們需要初始化字首1和字尾0陣列。

空間複雜度 - O(N),因為我們將字首1和字尾0儲存在陣列中。

方法二

在這種方法中,我們將首先計算零的總數。之後,我們開始遍歷字串並繼續計數“1”並在找到0時減少“0”。此外,我們在每次迭代中對零和一的計數求和,並找到最大的結果值。

演算法

  • 步驟1 - 定義“count1”、“count0”和“res”變數並將它們初始化為0,分別儲存1、0和最終結果的計數。

  • 步驟2 - 透過遍歷字串並將結果儲存在“count0”變數中來計算零的總數。

  • 步驟3 - 現在,使用迴圈迭代字串。

  • 步驟4 - 在迴圈中,如果當前字元是“1”,則將“count1”的值增加1,否則將“count0”的值減少1。

  • 步驟5 - 此外,將“res”和“count0 + count1”中的最大值儲存到“res”變數中。

  • 步驟6 - 當迴圈終止時,返回“res”變數的值。

示例

#include <bits/stdc++.h>
using namespace std;
int getMaxLength(string str, int n){
   int count1 = 0, count0 = 0;
   int res = 0;
   // counting total zeros in the string
   for (int i = 0; i < n; i++){
      if (str[i] == '0')
         count0++;
   }
   
   // counting 1s from left, subtracting zeros from total zeros and adding both counts.
   for (int i = 0; i < n; i++){
      if (str[i] == '1')
         count1++;
      else
         count0--;
      res = max(res, count1 + count0);
   }
   return res;
}
int main(){
   string str = "010110010";
   int N = str.length();
   cout << "The length of the longest non-increasing subsequence in the given binary string is - " << getMaxLength(str, N);
   return 0;
}

輸出

The length of the longest non-increasing subsequence in the given binary string is - 6

時間複雜度 - O(N),因為我們計算字串中零的總數並遍歷字串以找到最長的子序列。

空間複雜度 - O(1)

結論

在這裡,兩種方法的時間複雜度相同,但空間複雜度不同。第二種方法使用常量空間,因為我們優化了程式碼,但第一種方法使用動態空間來儲存字首1和字尾0的總數。

更新於:2023年7月28日

211 次瀏覽

開啟你的職業生涯

完成課程獲得認證

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