字符串中的 Rs 数

Posted

技术标签:

【中文标题】字符串中的 Rs 数【英文标题】:Number of Rs in a string 【发布时间】:2015-04-02 18:41:22 【问题描述】:

我有一个作业,我得到一个包含字母“R”和“K”的字符串 S,例如“RRRRKKKKRK”。

我需要通过将字符 i 到 j 翻转到相反的位置来获得该字符串可能包含的最大 'R' 数。所以:

for(int x = i; x < j; x++)

  if S[x] = 'R'
  
    S[X] = 'S';
  
  else
  
    S[X] = 'R';
  

但是,我只能进行上述调用一次

所以对于上面的例子:“RRRRKKKKRK”。

您将有 i = 4 和 j = 8,这将导致:“RRRRRRRRKR”,然后您将在结果字符串中输出 R 的数量:9。

我的代码部分有效,但在某些情况下无效。谁能弄清楚缺少什么?

示例输入

2
RKKRK
RKKR

样本输出

4
4

我的解决方案

我的解决方案仅适用于第一种情况,我不知道我缺少什么来完成算法:

int max_R = INT_MIN;
for (int i = 0; i < s.size(); i++)

    for (int j = i + 1; j < s.size(); j++)
    
        int cnt = 0;
        string t = s;

        if (t[j] == 'R')
        
            t[j] = 'K';
        
        else
        
            t[j] = 'R';
        

        for (int b = 0; b < s.size(); b++)
        
            if (t[b] == 'R')
            
                cnt++;

                if (cnt  > max_R)
                
                    max_R = cnt;
                
            

        
    




cout << max_R << endl;

【问题讨论】:

这里有问题吗? @BillLynch 是的......但这是家庭作业。他希望我们解决上述问题。他已经为样本工作了,但需要提供更多详细信息,以便我们了解他的期望和得到的。我会努力清理的。 这不是家庭作业,我正在练习解决问题并提高我的技能。用其他测试用例解决不了,算法需要细化 我并没有说这是一个坏问题(如果是,我会标记它)。它只是写成一个家庭作业问题。它实际上是一种打包算法。 拜托,伙计们,这与背包无关。背包是NP完全的,这个问题有一个脑死的n^3解。 【参考方案1】:

将其转换为具有 O(n) 解决方案的 Maximum subarray problem 怎么样?

遍历字符串一次,给“K”一个值,给“R”一个值-1。

例如,对于'RKRRKKKKRKK',您生成一个数组 -> [-1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1] -> [-1, 1, -2, 4, -1, 2](为了更清楚,我将连续的 -1 和 1 分组)

对生成的数组应用 Kadane 算法。这样做你得到的是你可以从翻转'K'中获得的最大'R'数量。

继续这个例子,你发现最大的子数组是[4, -1, 2],和为5。

现在将这个子数组之外的负值的绝对值与你的最大子数组的总和相加得到你的答案。

在我们的例子中,只有 -1 和 -2 是负数并且在子数组之外。我们得到 |-1| + |-2| + 5 = 8

【讨论】:

@kirelagin 一个角落的箱子可以处理这个 你是如何想出这个解决方案的?我想学习 !!这很棘手,它确实以快速的方式回答了问题 我不明白您是如何获得13+11 以及您如何获得 34 作为正确解决方案的?抱歉,如果我不清楚最后一步,我编辑了我的答案。最后一步是将要翻转的范围之外的“R”的数量添加到从翻转中获得的“R”的数量中。 @Jarod 我分配了 'K' 的值 1 和 'R' 的值 -1!因此,最大子数组是 5, -1, 8 和 12。然后将这个子数组之外的负值的绝对值与这个和相加:|-10| + |-6| + 12 = 28。不知道为什么要翻转代表 10 个“R”的 -10(我们正在最大化“R”,而不是“K”) @j449li:抱歉,错过了阅读您的解决方案,您使用最大子数组来查找要反转的数组。【参考方案2】:

尝试仔细考虑您的解决方案。你明白它的作用吗?

首先,让我们忘记输入文件可能包含多个测试,所以让我们摆脱@​​987654321@ 循环。现在,我们只有两个 for 循环。第二个显然只是计算处理字符串中的R。但是第一个是做什么的呢?

答案是第一个循环将第二个循环中的所有字母(即索引1)翻转到字符串的末尾。我们可以在第一个测试用例中看到:

RKKRK

确实是最优解。字符串变成RRRKR,我们得到四个R。但在第二种情况下:

RKKR

字符串变成RRRK,我们得到三个 R。如果我们只将字母从 2 翻转到 3(即索引 12),我们可以得到 RRRR,其中有 四个 R

因此,您的算法总是将索引 1 中的字母翻转到末尾,但这并不总是最优的。我们能做些什么?我们怎么知道要翻转哪些字母?好吧,有一些聪明的解决方案,但最简单的是尝试所有可能的组合!

你可以把0的所有字母翻到1,数一下R的个数,记住。回到原始字符串,将字母从0 翻转到2,计数R,记住它等等,直到你从0 翻转到n-1。然后你把字母从1翻到2,从1翻到3等等。答案就是你记得的最大值。

这是非常低效的,但这是可行的。在你获得更多解决算法问题的练习之后,回到这个任务并尝试找出更有效的解决方案。 (提示:如果您考虑逐步构建最佳答案,即逐个字符地遍历字符串并将子字符串 s[0..i] 的最佳解决方案转换为 s[0..i+1] 的最佳解决方案,您可以得出一个非常简单的 O( n^2) 算法。这可以增强到 O(n),但是这一步稍微复杂一些。)


这是这个解决方案的草图:

def solve(s):
  answer = 0
  for i in 0..(n-1)
    for j in i..(n-1)
      t = copy(s)  # we will need the original string later
      flip(t, i, j)  # flip letters from i to j in t
      c = count_R(t)  # count R's in t
      answer = max(answer, c)
  return answer

【讨论】:

非常感谢。 O(N^3) 解决方案是三个嵌套循环正确吗?你能显示伪代码吗? 你能检查一下我修改后的算法吗? @andre 我在答案中添加了伪代码。请注意,有两个循环(即 n^2),我们还需要翻转字母(这将我们带到 n^3)。同样,这完全是脑死亡,例如你不需要实际上翻转字母来计算R,你可以只计算R0i-1,然后计算Kij 并再次计算 Rj+1n-1 @andre 检查了您修改后的代码。您仍然没有尝试 right 界限的所有可能值,因此您在第二次测试中仍然得到错误的答案。 @andre 我认为实际上没有任何改变。您仍然总是将 all 字母翻转到字符串的末尾。只需拿起笔和纸,自己在第二个测试用例上执行您的算法,您会发现您从未考虑过只翻转中间的两个 R 的可能性。

以上是关于字符串中的 Rs 数的主要内容,如果未能解决你的问题,请参考以下文章

s-s-rS 将字符串格式化为 if 语句中的百分比

获取1-10000之前所有的对称数(回文数)

获取1-10000之前所有的对称数(回文数)

将由 TFS 区域路径组成的多值字符串传递给 s-s-rS 中的子报表

如何使用 s-s-rS 中的 URL 访问传递带有特殊字符的多个参数

特别是在 s-s-rS tablix 中的非换行连字符