给定二进制数,找到只能翻转一位(1或0)可以获得的最大连续1或0
给出的代码是
public int getMacCon(string[] A)
{
int n = A.Length;
int result = 0;
for (int i = 0; i < n - 1; i++)
{
if (A[i] == A[i + 1])
result = result + 1;
}
int r = -2;
for (int i = 0; i < n; i++)
{
int count = 0;
if (i > 0)
{
if (A[i - 1] != A[i])
count = count + 1;
else
count = count - 1;
}
if (i < n - 1)
{
if (A[i + 1] != A[i])
count = count + 1;
else
count = count - 1;
}
r = Math.Max(r, count);
}
return result + r;
}
我很难弄清楚这里的逻辑。特别是下面给出的部分
for (int i = 0; i < n - 1; i++)
{
if (A[i] == A[i + 1])
result = result + 1;
}
如果任何人能够解释这个解决方案中的逻辑,我会非常高兴。 感谢
答案 0 :(得分:2)
您突出显示的位只计算当前相邻相等值的数量,即一个值(A[i]
)等于下一个值(A[i+1]
)。然后,它依次询问(第二个循环),对于每个值,是否翻转它会增加vs减少而不改变相邻相等值的数量;因此,如果一个值当前与之前的值不同(A[i-1] != A[i]
),则翻转将增加 - 否则减少;同样是它之后的那个。最终结果是预先存在的相邻相等值(result
)的数量,加上扫描中找到的最佳增量(r
)。
public int getMacCon(string[] A)
{
int n = A.Length;
int result = 0;
// find how many adjacent values are currently in the string
for (int i = 0; i < n - 1; i++)
{
// if same as the next value, that's a hit
if (A[i] == A[i + 1])
result = result + 1;
}
// worst case delta from flipping one value is that me make it
// worse on both sides, so -2
int r = -2;
// now consider each value in turn
for (int i = 0; i < n; i++)
{
int count = 0;
if (i > 0) // test value before, if not the first value
{
if (A[i - 1] != A[i])
count = count + 1; // before is different; flip is incr
else
count = count - 1; // before is same; flip is decr
}
if (i < n - 1) // test value after, if not the last value
{
if (A[i + 1] != A[i])
count = count + 1; // after is different; flip is incr
else
count = count - 1; // after is same; flip is decr
}
// compare that to the tracking counter, and keep the best value
r = Math.Max(r, count);
}
// final result is sum of pre-existing count plus the delta
return result + r;
}
顺便提一下,优化可能是将第二个循环测试从i < n
更改为i < n && r != 2
- 即在找到最佳可能的delta后立即停止(使其在两侧都更好,+ 2)
答案 1 :(得分:1)
不是你问题的直接答案(正如Marc Gravell的答案所涵盖的那样)但我只想补充一下如何解决这个问题:
使用RLE(行程长度编码)对字符串进行编码
因此您需要b,v,n
个值的数组。如果b>=0
是起始位置,v={0,1}
是位值,n
是后续发生的计数。例如:
const int _max=100; // max number of bits
int b[_max],v[_max],n[_max],bvns=0;
bvns
是数组中使用的b,v,n
的数量。您也可以使用任何动态列表/模板。
重置您的实际解决方案
您需要位位置来更改ix
以及在其翻转sz
之后产生的后续位数。将展位设置为零。
扫描RLE以查找n=1
如果发现这意味着在RLE之前和之后的项目是相同的,那么翻转将加入它们。因此,计算结果大小,如果更大,则存储为实际解决方案,如:
for (int i=1;i<bvns-1;i++) // scann RLE except first and last item
if (n[i]==1) // single bit found
{
l=n[i-1]+1+n[i+1]; // resulting size
if (l>=sz) { sz=l; ix=b; } // update solution
}
测试放大单个序列是否不大
简单地:
for (int i=0;i<bvns;i++) // scann RLE
if (n[i]>=sz) // result is bigger?
{
sz=l; ix=b-1; // update solution
if (ix<0) ix=b+n[i];
}