在各種解決問題的場景中操作字符串至關重要。發現給定字符串的排列可以優化大于相鄰字符的字符數,這是一個有趣的難題,需要重新排列字符串的字符以生成盡可能多的相鄰字符對,其中左側字符小于右側字符。 p>
方法
有多種方法可以解決字符串的排列,其中最大字符數大于與其直接相鄰的字符數。
方法 1 ? 回溯法與剪枝 ?
方法 2 – 動態規劃 –
方法3 – 堆算法-
方法 4 – 帶修剪的詞典順序 –
方法一:回溯法與剪枝
使用回溯算法生成字符串的所有排列。
在每一步中,檢查當前排列是否有比其相鄰字符更多的字符大于迄今為止找到的最大值。
如果沒有,請盡早修剪分支并回溯以避免不必要的計算。
語法
function backtrack_permutation(string): n = length(string) max_count = [0]
登錄后復制
存儲大于相鄰字符的最大字符數
result = [None] * n
登錄后復制
存儲最終排列
function backtrack(curr_permutation, used_chars): nonlocal max_count if length(cu permutation) == n:
登錄后復制
計算大于相鄰字符的字符數量
count = 0 for i in range(1, n - 1): if cu permutation [i - 1] < cu permutation[i] > cu permutation [i + 1]: count += 1 if count > max count [0]: max count [0] = count result [:] = cu permutation
登錄后復制
更新結果
return for i in range(n): if not used_chars[i]:
登錄后復制
選擇下一個字符
used_chars[i] = true curr_permutation.append(string[i])
登錄后復制
回溯到下一個位置
backtrack(curr_permutation, used_chars)
登錄后復制
撤銷選擇
used_chars[i] = false curr_permutation.pop()
登錄后復制
開始回溯過程
used_chars = [false] * n
登錄后復制
跟蹤已使用的字符
curr_permutation = [] backtrack(curr_permutation, used_chars) return result.
登錄后復制
算法
步驟 1 – 用一個空字符串開始 max_permutation。
應定義輔助函數回溯(current_permutation、remaining_characters)。
步驟2 – 如果字符串remaining_characters為空 –
如果當前排列的長度比最大排列的長度長,將max_permutation設置為current_permutation。
返回。
步驟 3 – 在迭代中,遍歷剩余字符中的每個字符 c –
將 c 添加到 current_permutation 中以創建 new_permutation。
如果new_permutation的長度大于1且其最后一個字符不再長于其前面的字符,則跳過此迭代。
從remaining_characters中取出c,生成新的new_remaining。
迭代調用回溯(new_permutation、new_remaining)。
第四步 – 調用回溯函數,將輸入文本作為remaining_characters,將空字符串作為current_permutation。
第 5 步 – 提供輸出 max_permutation。
示例 1
此程序通過首先將輸入字符串“abcd”按升序排列來操作。隨后,使用回溯函數生成每個可能的排列,該函數僅考慮大于前一個字符的字符,從而避免了不符合條件的重復排列。此外,isValidPermutation函數根據每個字符與其前一個字符進行評估,對于任何等于或小于后者的情況返回false。
結果是,這個有目的的過程會創建所有有效的排列,其中每個字符的最大數量都高于其相鄰字符。我們可以自由地進一步定制給定的輸入字符串、代碼和邏輯,以滿足個人的要求。
#include <iostream> #include <string> #include <algorithm> using namespace std; int maxCount = 0; bool isValidPermutation(const string& str) { for (int i = 1; i < str.length(); i++) { if (str[i] <= str[i - 1]) { return false; } } return true; } void backtrack(string& str, int pos) { if (pos == str.length()) { if (isValidPermutation(str)) { cout << str << endl; } return; } for (int i = pos; i < str.length(); i++) { swap(str[pos], str[i]); if (str[pos] > str[pos - 1]) { backtrack(str, pos + 1); } swap(str[pos], str[i]); } } int main() { string input = "abcd"; sort(input.begin(), input.end()); // Sort the input string initially backtrack(input, 1); return 0; }
登錄后復制
輸出
abcd
登錄后復制
方法二:動態規劃
使用動態規劃逐步生成字符串的排列。
從空前綴開始,考慮所有可能的位置,迭代地向其中添加字符。
維護當前前綴中大于其相鄰字符的字符數。
修剪計數已經低于目前發現的最大值的分支。
語法
def find_max_permutation(string): n = len(string) dp = [0] * n dp[0] = 1
登錄后復制
動態編程循環
for i in range (1, n):
登錄后復制
檢查當前字符是否大于其相鄰字符
if string[i] > string[i-1]:
登錄后復制
如果是,則將計數增加1
dp[i] = dp[i-1] + 1 else:
登錄后復制
如果不是,計數是相同的
dp[i] = dp[i-1]
登錄后復制
查找 dp 數組中的最大計數
max_count = max(dp) return max_count
登錄后復制
算法
步驟 1 – 創建一個名為 maxPerm(str) 的函數,接受字符串作為輸入,并返回滿足指定條件的最長字符串的排列。
步驟 2 – 首先初始化長度為 n 的數組(稱為 dp),其中 n 等于輸入字符串 str 的長度。以位置 i 結束的最大排列串存儲在每個元素 dp[i] 中。
第三步 – 將 dp [0] 初始化為字符串 str 的第一個字符。
第四步 – 從索引1到n-1迭代遍歷str的字符 –
初始化一個空字符串curr來存儲當前最大排列字符串。
對于索引 i 處的每個字符,將其與索引 i-1 處的前一個字符進行比較。
如果 str[i] 大于 str[i-1],將 str[i] 添加到 curr 中。
否則,將 str[i-1] 追加到 curr 中。
使用 dp[i-1] 和 curr 之間的最大值更新 dp[i]。
第5步 – 循環完成后,最大排列字符串將存儲在dp[n-1]中。
第 6 步 – 返回 dp[n-1] 作為結果。
Example 2
的中文翻譯為:
示例2
在此示例中,輸入字符串被硬編碼為“abcbdb”。 findMaxPermutation 函數使用動態編程來計算每個索引處大于其相鄰字符的最大字符數。然后,它通過回溯表來重建具有最大計數的字符串。生成的最大排列在 main 函數中打印。
#include <iostream> #include <string> #include <vector> std::string findMaxPermutation(const std::string& str) { int n = str.length(); // make a table to store the maximum count of characters // larger than their adjacent characters std::vector<std::vector<int>> dp(n, std::vector<int>(2, 0)); // Initialize the table for the base case dp[0][0] = 0; // Count when str[0] is not included dp[0][1] = 1; // Count when str[0] is included // Calculate the maximum count for each index for (int i = 1; i < n; i++) { // When str[i] is not involved, the count is the maximum // when str[i-1] is included or not dp[i][0] = std::max(dp[i-1][0], dp[i-1][1]); // When str[i] is involved, the count is the count when // str[i-1] is not included plus 1 dp[i][1] = dp[i-1][0] + 1; } // The more count will be the largest of the last two values int maxCount = std::max(dp[n-1][0], dp[n-1][1]); // Reconstruct the string with the maximum count std::string maxPerm; int i = n - 1; int count = maxCount; // Start from the end and check which character to include while (i >= 0) { if ((dp[i][0] == count - 1 && dp[i][1] == count) || (dp[i][0] == count && dp[i][1] == count)) { maxPerm = str[i] + maxPerm; count--; } i--; } return maxPerm; } int main() { std::string str = "abcbdb"; std::string maxPerm = findMaxPermutation(str); std::cout << "String: " << str << std::endl; std::cout << "Max Permutation: " << maxPerm << std::endl; return 0; }
登錄后復制
輸出
String: abcbdb Max Permutation: bbb
登錄后復制
方法三:堆算法
實現Heap算法,高效地生成字符串的所有排列。
生成每個排列后,計算大于其相鄰字符的字符數量。
保持追蹤到目前為止找到的最大計數,并根據需要進行更新。
語法
function generatePermutations(string): n = length(string) characters = array of n elements initialized with string's characters generatePermutationsHelper(n, characters) function generatePermutationsHelper(n, characters): if n = 1: checkAndPrintPermutation(characters) else: for i = 0 to n-1: generatePermutationsHelper(n-1, characters) if n is even: swap characters[i] and characters[n-1] else: swap characters [0] and characters[n-1]
登錄后復制
算法
第一步 – 已經初始化了一個數組,用于存儲輸入字符串的字符。
第 2 步 – 繼續創建一個函數,并將其命名為“generatePermutations”,帶有兩個參數 – 一個最終變量“size”,用于確定數組的大小,以及一個名為“arr”的數組,其中包含字符串字符。
步驟 3 – 如果大小為 1,則通過將數組中的字符組合在一起,直到最大字符數超過連續字符數,打印當前排列。
步驟 4 – 如果不是,則函數返回。為了從索引 0 到 ‘size – 1’ 迭代數組,我們使用一個名為 ‘i’ 的變量。
第 5 步 – 在此迭代中,我們進一步迭代參數大小 – 1 和錯誤的generatePermutations 函數。
第 6 步 – 如果 size 恰好是奇數,則我們將數組中索引 0 處的元素替換為索引“size – 1”處的元素。
第 7 步 – 類似地,如果 size 結果是偶數,我們將數組中索引“i”處的元素替換為索引“size – 1”。
步驟8 – 最后,我們使用初始數組大小和數組本身作為參數調用”generatePermutations”函數。
示例 1
以下的C++示例使用Heap’s算法創建字符串的排列,并識別出在其相鄰字符上具有最大字符數的排列 ?
為了說明問題,在這個例子中使用”abcd”作為輸入字符串。可以修改變量來使用不同的輸入字符串。如果排列滿足具有比其鄰居更多字符的要求,則找到isValidPermutation函數是否有效。generatePermutations函數使用堆棧方法來跟蹤具有最多字符的排列,以便它可以生成輸入字符串的每個可能的排列。主函數將最大數量和排列本身作為輸出打印。
#include <iostream> #include <algorithm> using namespace std; // Function to check if the permutation satisfies the condition bool isValidPermutation(const string& perm) { int n = perm.length(); for (int i = 0; i < n - 1; i++) { if (abs(perm[i] - perm[i + 1]) <= 1) return false; } return true; } // Function to swap two characters in a string void swapChar(char& a, char& b) { char temp = a; a = b; b = temp; } // Heap's Algorithm for generating permutations void generatePermutations(string& str, int n, int& maxCount, string& maxPerm, int idx = 0) { if (idx == n - 1) { if (isValidPermutation(str)) { int count = count_if(str.begin(), str.end(), [](char c) { return isalpha(c) && c >= 'A' && c <= 'Z'; }); if (count > maxCount) { maxCount = count; maxPerm = str; } } return; } for (int i = idx; i < n; i++) { swapChar(str[idx], str[i]); generatePermutations(str, n, maxCount, maxPerm, idx + 1); swapChar(str[idx], str[i]); } } int main() { string str = "abcd"; int n = str.length(); int maxCount = 0; string maxPerm; generatePermutations(str, n, maxCount, maxPerm); if (maxCount == 0) { cout << "No valid permutation found." << endl; } else { cout << "Maximum number of characters greater than adjacent characters: " << maxCount << endl; cout << "Permutation with the maximum count: " << maxPerm << endl; } return 0; }
登錄后復制
輸出
No valid permutation found.
登錄后復制
方法4:字典序排序與剪枝
按字典順序對字符串的字符進行排序。
生成排序字符串的排列。
在每一步中,檢查當前排列是否滿足最大字符數大于其相鄰字符的條件。
如果不是這樣,請跳過具有相似前綴的剩余排列,以避免不必要的計算。
語法
生成字符串所有排列的函數
function generatePermutations(string):
登錄后復制
TODO:排列生成的實現
檢查字符是否大于其相鄰字符的函數
function isGreaterAdjacent(char1, char2):
登錄后復制
TODO:比較邏輯的實現
找到具有大于相鄰字符的最大數量的排列的函數
function findMaxAdjacentPermutation(string):
登錄后復制
生成字符串的所有排列
permutations = generatePermutations(string)
登錄后復制
初始化變量
max_permutation = "" max_count = 0
登錄后復制
遍歷每個排列
for permutation in permutations: count = 0
登錄后復制
迭代排列中的每個字符(不包括最后一個字符)
for i from 0 to length(permutation) - 2: char1 = permutation[i] char2 = permutation[i + 1]
登錄后復制
檢查當前字符是否大于其相鄰字符
if isGreaterAdjacent(char1, char2): count = count + 1
登錄后復制
檢查當前排列的計數是否大于先前的最大值
if count > max_count: max_permutation = permutation max_count = count
登錄后復制
返回具有最大計數的排列
return max_permutation
登錄后復制
算法
第一步 – 從輸入字符串開始。
第 2 步 – 按字典順序對字符串進行排序以獲得初始排列。
第 3 步 – 將變量 maxCount 初始化為 0,以跟蹤大于相鄰字符的最大字符數。
第 4 步 – 初始化變量 maxPermutation 以存儲最大計數的排列。
第 5 步 – 當有下一個排列時 –
將變量 count 初始化為 0,以跟蹤當前大于相鄰字符的字符數。
對于當前排列中的每個字符 –
檢查當前字符是否大于其前一個字符和后一個字符(如果存在)。
如果滿足條件,則將計數增加 1。
如果計數大于最大計數(maxCount)-
將maxCount更新為當前計數。
將 maxPermutation 更新為當前排列。
步驟 6 – 將 maxPermutation 作為結果返回。
示例 1
對于此示例,為簡單起見,讓我們考慮固定字符串“abcde”。
在這個例子中,countAdjacentGreater函數統計字符串中相鄰字符大于其前一個字符的數量。findMaxPermutation函數生成輸入字符串的所有排列,并檢查每個排列,找出具有最大數量相鄰字符大于的那個。
主要函數初始化輸入字符串”abcde”和跟蹤最大計數和最大排列的變量。它調用findMaxPermutation函數來找到最大排列。
#include <iostream> #include <algorithm> #include <string> using namespace std; int countAdjacentGreater(const string& str) { int count = 0; for (int i = 0; i < str.length() - 1; i++) { if (str[i] < str[i + 1]) { count++; } } return count; } void findMaxPermutation(string& str, int& maxCount, string& maxPerm) { sort(str.begin(), str.end()); do { int count = countAdjacentGreater(str); if (count > maxCount) { maxCount = count; maxPerm = str; } } while (next_permutation(str.begin(), str.end())); } int main() { string str = "abcde"; int maxCount = 0; string maxPerm; findMaxPermutation(str, maxCount, maxPerm); cout << "String with the maximum number of characters greater than its adjacent characters: " << maxPerm << endl; cout << "Count of adjacent characters greater in the maximum permutation: " << maxCount << endl; return 0; }
登錄后復制
輸出
String with the maximum number of characters greater than its adjacent characters: abcde Count of adjacent characters greater in the maximum permutation: 4
登錄后復制
結論
總之,找到最大字符數大于相鄰字符的字符串的排列問題是字符串操作中的一個有趣的挑戰。通過分析給定的字符串并有策略地重新排列其字符,可以實現所需的排列。這個問題凸顯了在使用字符串和排列時仔細檢查和創造性思維的重要性。
以上就是字符串的排列,使得其中字符的數量大于其相鄰字符的數量的最大化的詳細內容,更多請關注www.xfxf.net其它相關文章!