c - 如果只允许一个操作,即按 K 位右移,则二进制字符串将产生的最大二进制数,其中 K = [0,字符串长度]
问题描述
假设您有一个二进制字符串S
,并且您只能执行一项操作,即Right-Rotate by K-bits
where K = [0, Length of the string]
。编写一个算法,该算法将打印您可以通过定义的过程创建的最大二进制数。
例如:
S = [00101]
那么我可以从这个过程中得到的最大值是10100
ie20
。S = [011010]
那么我可以从这个过程中得到的最大值是110100
ie52
。S = [1100]
那么我可以从这个过程中得到的最大值是1100
ie12
。
字符串的长度S
有一个上限,即5*(10^5)
。
我想到的想法有点天真,那就是:正如我们所知,当您将任何二进制数右旋转 时1-bit
,您在旋转后得到相同的二进制数m
where m = number of bits required to represent that number
。
所以,我向右旋转1
直到我得到我开始的数字,在这个过程中,我跟踪我遇到的最大值,最后我打印最大值。
有没有解决问题的有效方法?
UPD1:这是问题的根源One-Zero,这一切都归结为我上面描述的陈述。
UPD2:由于答案可能很大,程序将打印答案模10^9 + 7.
解决方案
您想找到用环绕的二进制编码字符串表示的最大数字。
以下是解决方案的步骤:
- 设为
len
字符串的长度 - 分配一个大小数组
2 * len
并将字符串复制到它。 - 使用线性搜索,找到该数组
pos
中长度最大的子串的位置len
(可以使用字典顺序)。 - 计算
res
,转换后的数模 10 9 +7,读取len
从 开始的位pos
。 - 释放数组并返回
res
。
这是一个简单的函数实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long max_bin(const char *S) {
size_t i, pos, len;
char *a;
// long has at least 31 value bits, enough for numbers upto 2 * 1000000007
long res;
if ((len = strlen(S)) == 0)
return 0;
if ((a = malloc(len + len)) == NULL)
return -1;
memcpy(a, S, len);
memcpy(a + len, S, len);
// find the smallest right rotation for the greatest substring
for (pos = i = len; --i > 0;) {
if (memcmp(a + i, a + pos, len) > 0)
pos = i;
}
res = 0;
for (i = 0; i < len; i++) {
res = res + res + a[pos + i] - '0';
if (res >= 1000000007)
res -= 1000000007;
}
free(a);
return res;
}
int main(int argc, char *argv[]) {
for (int i = 1; i < argc; i++) {
printf("[%s] -> %ld\n", argv[i], max_bin(argv[i]));
}
return 0;
}
如果需要,避免内存分配是可行的。
推荐阅读
- html - 使用 ngModelChange 改变样式
- sql - 防止存储过程 SQL Server 2008 中的参数嗅探?
- css - 如何在特色图像上获得背景色低不透明度叠加?
- java - 如何将`hamcrest-core-1.3.jar`添加到Windows中的类路径变量?
- java - Java 文本未正确更新
- jquery - 尝试使用 jQuery 或 CSS 删除 Squarespace 中的悬停覆盖
- angular - Angular ngModel 格式输出
- google-apps-script - 复制电子表格也会复制所有链接的文件
- php - 从 PHP Docker 运行 Python 脚本
- angular - Angular 6 防止 [hidden] 在页面加载时闪烁