透過交替新增字符合並兩個字串,得到字典序最大的字串


字典序是指一種演算法,可以用來按字母順序排列給定的單詞,這與字典中使用的概念相同。透過一次取一個字符合並兩個字串,可以得到最大的字串,方法是按降序排列字母,同時記住元素的順序。

問題陳述

在本問題中,我們需要找到透過合併兩個給定字串得到的字典序最大的字串。要理解這個問題,我們應該瞭解用於按字典序排列字串的基本概念。

讓我們透過一些例子來理解這個問題。

輸入

string1 = "cabaa", string2 = "bcaaa"

輸出

"cbcabaaaaa"

解釋

獲得字典序最大的合併字串的一種方法是:

  • 從字串1中取“c”並將其新增到初始空字串中,這使得字串1變為“abaa”,字串2變為“bcaaa”。

  • 現在,從字串2中取“b”,使合併字串變為“cb”,字串1變為“abaa”,字串2變為“caaa”。

  • 再次從字串2中取“c”,使合併字串變為“cbc”,字串1變為“abaa”,字串2變為“aaa”。

  • 從字串1中取“a”,使合併字串變為“cbca”,字串1變為“baa”,字串2變為“aaa”。

  • 再次從字串1中取“b”,使合併字串變為“cbcab”,字串1變為“aa”,字串2變為“aaa”。

  • 現在,將字串1和字串2中剩餘的“a”全部新增到合併字串中,得到最終結果。

輸入

string1 = "baa", string2 = "bcaac"

輸出

"bcbaacaa"

解釋

這裡,為了得到字典序最大的合併字串,我們將從字串2中取“b”,然後再次從字串2中取“c”,使其變為“bc”。現在,我們將從字串1中取“b”,使合併字串變為“bcb”,其餘我們將從字串2中取“aac”,從字串1中取“aa”,使合併字串變為“bcbaacaa”,作為預期輸出。

問題解釋

讓我們嘗試理解這個問題並找到解決方案。我們可以透過兩種方法解決這個問題:一種是使用遞迴,另一種是使用迭代,其中我們將使用貪婪指標的概念。貪婪指標是在我們為獲得整體最優解而採取小步最優選擇時使用的指標。

方法1 - 暴力遞迴解法

這裡,我們將使用遞迴函式的概念,其中基準條件定義為當兩個字串中的任何一個的大小變為零時。然後,我們將比較剩餘字串的第一個字元,返回較大的字元及其子字串的函式呼叫。

示例

現在,讓我們在不同的程式語言中實現上述方法:C、C++、Java 和 Python:

#include<bits/stdc++.h>
using namespace std;
// Make a function to get the Lexicographically largest possible string
string helper(string word1, string word2) {
   // base condition for recursion
   if (word1.empty() || word2.empty()){
      return word1 + word2;
   }
   // Check the character from which string would be chosen first among both strings
   if (word1 > word2) {
      return word1[0] + helper(word1.substr(1), word2);
   }
   // return the final answer which would provide optimal result
   return word2[0] + helper(word1, word2.substr(1));
}
int main() {
   // Give two strings by the user
   string string1 = "cabaa";
   string string2 = "bcaaa";
   // Call the helper function 
   cout << "The lexicographically largest possible string is: " << helper(string1, string2);
   return 0;
}	  

輸出

The lexicographically largest possible string is: cbcabaaaaa
public class Main {
   // Function to get the lexicographically largest possible string
   public static String helper(String word1, String word2) {
      // Base condition for recursion
      if (word1.isEmpty() || word2.isEmpty()) {
         return word1 + word2;
      }

      // Check the character from which string would be chosen first among both strings
      if (word1.compareTo(word2) > 0) {
         return word1.charAt(0) + helper(word1.substring(1), word2);
      }

      // Return the final answer which would provide the optimal result
      return word2.charAt(0) + helper(word1, word2.substring(1));
   }
   public static void main(String[] args) {
      // Provide two strings
      String string1 = "cabaa";
      String string2 = "bcaaa";

      // Call the helper function
      String result = helper(string1, string2);

      // Print the lexicographically largest possible string
      System.out.println("The lexicographically largest possible string is: " + result);
   }
}

輸出

The lexicographically largest possible string is: cbcabaaaaa
# Function to get the lexicographically largest possible string
def helper(word1, word2):
   # Base condition for recursion
   if not word1 or not word2:
      return word1 + word2
    
   # Check the character from which string would be chosen first among both strings
   if word1 > word2:
      return word1[0] + helper(word1[1:], word2)
    
   # Return the final answer which would provide the optimal result
   return word2[0] + helper(word1, word2[1:])

# Main function
def main():
   # Provide two strings
   string1 = "cabaa"
   string2 = "bcaaa"

   # Call the helper function
   result = helper(string1, string2)

   # Print the lexicographically largest possible string
   print("The lexicographically largest possible string is:", result)

if __name__ == "__main__":
   main()

輸出

The lexicographically largest possible string is: cbcabaaaaa

上述程式碼的複雜度

  • 時間複雜度 - O(m*n);其中“m”和“n”是使用者提供的兩個字串的初始輸入大小。這裡有一個內建的遞迴堆疊,將用於遍歷兩個字串中所有給定的元素。

  • 空間複雜度 - O(1);雖然這裡使用了內建的遞迴堆疊,但它仍然不會佔用空間,因為它用作執行時記憶體。

方法2 - 使用貪婪指標技術的最佳解法

演算法

  • 執行一個迴圈,直到我們到達第一個字串的大小(對於變數“i”)或者第二個字串的大小(對於變數“j”)。

  • 檢查哪個字元根據ASCII碼排在後面,我們將把該字元新增到合併字串中。

  • 到達迴圈的停止條件後,我們將檢查“i”或“j”中哪個到達了其限制。

  • 我們將執行一個單獨的迴圈以使另一個迴圈到達其停止點,以便我們可以將兩個字串的字元新增到合併字串中。

示例

現在,讓我們在不同的程式語言中實現上述方法:C、C++、Java 和 Python:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// Function to get the lexicographically largest possible string
char* helper(const char* word1, const char* word2) {
   int n = strlen(word1);
   int m = strlen(word2);
   char* ans = (char*)malloc(n + m + 1); // Allocate memory for the result string

   int i = 0, j = 0, k = 0;
   
   while (i < n && j < m) {
      // Check which character is maximum
      if (strcmp(&word1[i], &word2[j]) > 0) {
         ans[k++] = word1[i++];
      } else {
         ans[k++] = word2[j++];
      }
   }
   
   // If the condition for 'i' was not satisfied, append the rest of the first string to the final answer
   while (i < n) {
      ans[k++] = word1[i++];
   }
   
   // If the condition for 'j' was not satisfied, append the rest of the second string to the final answer
   while (j < m) {
      ans[k++] = word2[j++];
   }    
   ans[k] = '\0'; // Null-terminate the result string    
   return ans;
}
int main() {
   // Given two strings by the user
   const char* string1 = "cabaa";
   const char* string2 = "bcaaa";
   
   // Call the helper function
   char* result = helper(string1, string2);
   
   // Print the lexicographically largest possible string
   printf("The lexicographically largest possible string is: %s\n", result);
   
   // Free the allocated memory
   free(result);
   
   return 0;
}

輸出

The lexicographically largest possible string is: cbcabaaaaa
#include<bits/stdc++.h>
using namespace std;
// Make a function to get the Lexicographically largest possible string
string helper(string word1, string word2) {
   // Define size of string1 and string2
   int i = 0, j = 0, n = word1.size(), m = word2.size();
   string ans;
   // Using the pointer technique
   while(i < n && j < m) {
      // Check which character is maximum
      if(word1.substr(i) > word2.substr(j)){ 
         ans += word1[i];
         i++;
      } else { 
         ans += word2[j];
         j++;
      }
   }
   // If the condition for 'i' was not satisfied append the rest first string to the final answer
   while(i < n){ 
      ans += word1[i];
      i++;
   }
   // If the condition for 'i' was not satisfied append the rest first string to the final answer
   while(j < m){ 
      ans += word2[j];
      j++;
   }
   // return the final answer which would provide the optimal result
   return ans;
}
int main() {
   // Given two strings by the user
   string string1 = "cabaa";
   string string2 = "bcaaa";
   // Call the helper function 
   cout << "The lexicographically largest possible string is: " << helper(string1, string2);
   return 0;
}	  

輸出

The lexicographically largest possible string is: cbcabaaaaa
public class Main {
   // Make a function to get the lexicographically largest possible string
   public static String helper(String word1, String word2) {
      int i = 0, j = 0;
      int n = word1.length();
      int m = word2.length();
      StringBuilder ans = new StringBuilder(); // Use StringBuilder to efficiently build the string

      // Using a pointer technique
      while (i < n && j < m) {
         // Check which character is maximum
         if (word1.substring(i).compareTo(word2.substring(j)) > 0) {
            ans.append(word1.charAt(i));
            i++;
         } else {
            ans.append(word2.charAt(j));
            j++;
         }
      }

      // If the condition for 'i' was not satisfied, append the rest of the first string to the final answer
      while (i < n) {
         ans.append(word1.charAt(i));
         i++;
      }

      // If the condition for 'j' was not satisfied, append the rest of the second string to the final answer
      while (j < m) {
         ans.append(word2.charAt(j));
         j++;
      }

      // Return the final answer which provides the optimal result
      return ans.toString();
   }
   public static void main(String[] args) {
      // Given two strings by the user
      String string1 = "cabaa";
      String string2 = "bcaaa";
      // Call the helper function
      System.out.println("The lexicographically largest possible string is: " + helper(string1, string2));
   }
}

輸出

The lexicographically largest possible string is: cbcabaaaaa
# Function to get the lexicographically largest possible string
def helper(word1, word2):
   i, j = 0, 0
   n, m = len(word1), len(word2)
   ans = []
   # Using a pointer technique
   while i < n and j < m:
      # Check which character is maximum
      if word1[i:] > word2[j:]:
         ans.append(word1[i])
         i += 1
      else:
         ans.append(word2[j])
         j += 1
   # If the condition for 'i' was not satisfied, append the rest of the first string to the final answer
   while i < n:
      ans.append(word1[i])
      i += 1
   # If the condition for 'j' was not satisfied, append the rest of the second string to the final answer
   while j < m:
      ans.append(word2[j])
      j += 1

   # Join the characters to form the final answer
   return ''.join(ans)

# Main function
def main():
   # Given two strings by the user
   string1 = "cabaa"
   string2 = "bcaaa"
   # Call the helper function
   result = helper(string1, string2)
   print("The lexicographically largest possible string is:", result)

if __name__ == "__main__":
   main()

輸出

The lexicographically largest possible string is: cbcabaaaaa

上述程式碼的複雜度

  • 時間複雜度 - O(m+n);其中“m”和“n”是使用者提供的兩個字串的初始輸入大小。這裡一個迴圈將被使用 (n + m) 次以獲得最終解決方案。

  • 空間複雜度 - O(n+m);這裡使用一個字串“ans”來儲存我們的輸出,這將在記憶體中佔用 (n+m) 的大小。

結論

在本文中,為了找到透過一次新增一個字元來合併使用者提供的兩個字串而得到的字典序最大的字串,首先,我們將使用遞迴過程來應用樸素的方法以獲得輸出。我們將仔細考慮合併字串的所有可用選項,遞迴將為我們提供最合適的輸出,以滿足字典序條件,同時記住兩個字串的順序。但是這種方法需要更多的時間來執行程式碼。因此,我們將使用另一種方法,即使用貪婪指標的迭代方法來提高時間複雜度,透過此過程,我們將能夠僅透過一次迭代即可達到最終輸出。

更新於:2024年1月22日

296 次瀏覽

啟動你的職業生涯

完成課程獲得認證

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