📌  相关文章
📜  通过翻转给定二进制字符串中最多 K 位来最大化分配权重的总和

📅  最后修改于: 2021-10-26 05:55:36             🧑  作者: Mango

给定一个长度为N的二进制字符串str和一个整数K ,任务是找到通过翻转给定二进制字符串中最多 K位可以获得的分配权重的最大可能总和。分配给该字符串的字符的权重如下:

  • 如果字符为‘0’ ,则权重为0
  • 如果一个字符是‘1’并且它前面的字符也是‘1’ ,那么权重是2
  • 如果一个字符是‘1’并且它前面没有字符或者它前面的字符是‘0’ ,那么权重是1

例子:

做法:字符“1”“1”之后出现的重量是所有字符中最伟大的,所以最大限度的总和,尽量创造尽可能多这样的1秒。要翻转为10段可以按如下优先级排序:

  • 第一优先级:翻转包含在两个1之间的所有0 ,这将使表格10…01的段的权重增加(2*(包含的0数)+ 1)。如果 x 大于或等于所包含的0数,否则为 2*(所包含的 0 数)。
  • 第二优先度”1秒的第一次出现之前的字符串中的字符串的开头翻转为0,这将增加形式0的链段的重由2 *(翻转数的0的)01。
  • 第三优先级:在字符串中最后一次出现1之后的字符串末尾翻转0 ,这将使10…0形式的段的权重增加 2*(翻转 0 的数量)。

按照上述优先级翻转给定字符串的字符以最大化权重,然后在最多K次翻转后找到结果字符串的权重。

下面是这个方法的实现:

C++
// C++ program of the above approach
#include 
using namespace std;
 
// Function to find maximum sum of
// weights of binary string after
// at most K flips
int findMax(string s, int n, int k)
{
    int ans = 0;
 
    // Stores lengths of substrings
    // of the form 1..00..1s
    int l = 0;
 
    // Stores the index of last 1
    // encountered in the string
    int ind = -1;
 
    // Stores the index of first 1
    // encountered
    int indf = -1;
 
    // Stores lengths of all substrings
    // having of 0s enclosed by 1s
    // at both ends
    multiset ls;
 
    // Traverse the string
    for (int i = 0; i < n; i++) {
        // If character is 0
        if (s[i] == '0')
            l++;
 
        // If character is 1
        // First Priority
        else if (s[i] == '1'
                 && l > 0 && ans != 0) {
            ls.insert(l);
            l = 0;
        }
 
        // Second Priority
        if (s[i] == '1') {
            ind = i;
            l = 0;
            if (indf == -1)
                indf = i;
 
            // Add according to the
            // first priority
            if (i > 0 && s[i - 1] == '1')
                ans += 2;
            else
                ans += 1;
        }
    }
 
    // Stores length of the shortest
    // substring of 0s
    int curr;
 
    // Convert shortest substrings
    // of 0s to 1s
    while (k > 0 && !ls.empty()) {
        curr = *ls.begin();
 
        // Add according to the
        // first priority
        if (k >= curr) {
            ans += (2 * curr + 1);
            k -= curr;
        }
 
        // Add according to the
        // third priority
        else {
            ans += (2 * k);
            k = 0;
        }
        ls.erase(ls.begin());
    }
 
    // If more 0s can be made into 1,
    // then check for 0s at ends
    if (k > 0) {
        // Update the ans
        ans += (2 * min(k,
                        n - (ind + 1))
                - 1);
        k -= min(k, n - (ind + 1));
 
        if (ind > -1)
            ans++;
    }
 
    // If K is non-zero, then flip 0s
    // at the beginning
    if (k > 0) {
        ans += (min(indf, k) * 2 - 1);
 
        if (indf > -1)
            ans++;
    }
 
    // Return the final weights
    return ans;
}
 
// Driver Code
int main()
{
    // Given string str
    string str = "1110000101";
 
    int N = str.length();
 
    // Given K flips
    int K = 3;
 
    // Function Call
    cout << findMax(str, N, K);
 
    return 0;
}


Python3
# Python 3 program of the above approach
 
# Function to find maximum sum of
# weights of binary string after
# at most K flips
def findMax( s, n, k):
 
    ans = 0;
 
    # Stores lengths of substrings
    # of the form 1..00..1s
    l = 0;
 
    # Stores the index of last 1
    # encountered in the string
    ind = -1;
 
    # Stores the index of first 1
    # encountered
    indf = -1;
 
    # Stores lengths of all substrings
    # having of 0s enclosed by 1s
    # at both ends
    ls = set([])
 
    # Traverse the string
    for i in range(n):
        # If character is 0
        if (s[i] == '0'):
            l+=1
 
        # If character is 1
        # First Priority
        elif (s[i] == '1'
                 and l > 0 and ans != 0):
            ls.add(l);
            l = 0;
 
        # Second Priority
        if (s[i] == '1') :
            ind = i;
            l = 0;
            if (indf == -1):
                indf = i;
 
            # Add according to the
            # first priority
            if (i > 0 and s[i - 1] == '1'):
                ans += 2;
            else:
                ans += 1;
 
    # Stores length of the shortest
    # substring of 0s
    curr = 0
 
    # Convert shortest substrings
    # of 0s to 1s
    while (k > 0 and len(ls)!=0):
        for i in ls:
          curr = i
          break
 
        # Add according to the
        # first priority
        if (k >= curr):
            ans += (2 * curr + 1);
            k -= curr;
 
        # Add according to the
        # third priority
        else :
            ans += (2 * k);
            k = 0;
        
        ls.remove(curr);
     
    # If more 0s can be made into 1,
    # then check for 0s at ends
    if (k > 0) :
        # Update the ans
        ans += (2 * min(k,
                        n - (ind + 1))
                - 1);
        k -= min(k, n - (ind + 1));
 
        if (ind > -1):
            ans+=1
 
    # If K is non-zero, then flip 0s
    # at the beginning
    if (k > 0):
        ans += (min(indf, k) * 2 - 1);
 
        if (indf > -1):
            ans+=1
    
    # Return the final weights
    return ans
 
# Driver Code
if __name__ == "__main__":
   
    # Given string str
    s = "1110000101";
 
    N = len(s)
 
    # Given K flips
    K = 3;
 
    # Function Call
    print(findMax(s, N, K));
 
    # This code is contributed by chitranayal


输出:
14

时间复杂度: O(N)
辅助空间: O(N)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程