- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在寻找一种更快的算法来解决以下问题:
A
和 B
在 [0, N)
范围内, 都是固定长度 d
,假设按排序顺序给出,没有重复元素。A
之间是否存在最大可能的交集(即共同元素的数量)和 B
的循环移位大于某个指定阈值 t
.通过 B
的循环移位,我的意思是数组 [(b + s) % N for b in B]
对于某个整数 s
.如果重要的话,我会在 Rust 中实现它(虽然我对一般算法改进比特定语言优化更感兴趣),并且在实践中,t
将小于 10,d
通常在 15 到 150 的范围内,N
将大致在 2*d*d
的顺序上.
我目前的算法基本上如下(注意,d
和 N
是在编译时定义的常量):
fn max_shifted_overlap_geq(A: [u32; d], B: [u32; d], threshold: u32) -> bool {
for i in 0..d {
for j in 0..d {
let s = N + A[i] - B[j];
let mut B_s = [0; d];
for k in 0..d {
B_s[k] = (B[k] + s) % N;
}
B_s.sort();
// Actually, I do an insertion-sort in place as I construct B_s,
// but I'm writing it this way here for simplicity.
if sorted_intersection_count(&A, &B_s) >= threshold {
return true;
}
}
}
false
}
所以我只从 A[i] - B[j]
的可能值中选择偏移(因为不是这种形式的移位给出零交集),然后我只构造 B
的循环移位并以相当简单的方式计算共有元素的数量。
考虑到数组的尺寸相当小,是否有更有效的算法?特别是,是否有更好的方法来找到更有可能产生大量重叠的转变?
编辑:为了提供额外的上下文(按照下面的要求),这出现在 QC-MDPC 代码的研究中:数组表示生成奇偶校验矩阵的循环 block 的二进制向量的支持,并且这个条件与循环移位的交集定义了一类具有某些密码含义的“弱 key ”。 (我最初没有提到这一点,因为这个问题单独看来很有趣,并且不需要任何编码理论或密码学知识。)
编辑 2:修正了代码中的一些拼写错误,并改用更好的方法来计算排序列表的交集。 (奇怪的是,我实际上在早期版本中使用了该改进的算法并且代码运行速度较慢,但这可能是由于代码中其他地方的实现错误或现在已修复的问题。)
编辑 3:为了将来遇到类似问题的任何人引用,这是我当前的实现,使用下面 virchau13 的回答中的关键思想加上一些小的额外优化。这在实践中似乎非常有效。 (为清楚起见,我重命名了一些变量——arr1
和 arr2
用于输入数组,LEN
而不是 d
用于数组长度。)
fn relative_shifts(arr1: &[u32; LEN], arr2: &[u32; LEN]) -> [[u32; LEN]; LEN] {
let n = N as u32;
let mut shifts = [[0; LEN]; LEN];
for i in 0..LEN {
for j in 0..LEN {
shifts[i][j] = if arr1[i] < arr2[j] {
n + arr1[i] - arr2[j]
} else {
arr1[i] - arr2[j]
}; // this equals (arr1[i] - arr2[j]) % n
}
}
shifts
}
fn max_shifted_overlap_geq(arr1: &[u32; LEN], arr2: &[u32; LEN], threshold: u8) -> bool {
let shifts = relative_shifts(arr1, arr2);
let mut shift_counts = [0; N];
for i in 0..LEN {
for j in 0..LEN {
let count = &mut shift_counts[shifts[i][j] as usize];
*count += 1;
if *count >= threshold {
return true;
}
}
}
false
}
几个实现说明:
(i, j)
附加到与每个类次关联的列表 s
计算)。最佳答案
我认为可以将算法降低到 O(d^2)。这只是(未经测试的)推测。
对于两个元素 A[i]
和 B[j]
循环相等,(B[j] + s) % N
必须等于 A[i]
.如果s = s_orig
满足这个方程,那么s = s_orig % n
也满足这个等式,意味着我们可以限制s
至 0 <= s < N
.使用此限制,我们可以证明两个元素循环相等当且仅当 B[j] + s
等于 A[i]
或 A[i] + N
(自 0 <= A[i],B[i] < N
开始),这等同于说 s
必须等于 A[i] - B[j]
或 N + A[i] - B[j]
.然而,由于 0 <= s < N
,第一项仅在差为正或零时才有意义,而第二项仅在差为负时才有意义;即我们可以说 s
必须等于表达式 if A[i] - B[j] < 0 { N + A[i] - B[j] } else { A[i] - B[j] }
.另一种写法是 s = (N + A[i] - B[j]) % N
.
请注意,由于 s
只有一个值对于每个 (i,j)
一对,两个 (i1,j1)
和 (i2,j2)
当且仅当 s
的值时,对都重叠对于它们中的每一个都是相同的。
所以这是最终的算法:
首先枚举所有可能的 s
A
之间的循环差异和 B
并将它们放入二维数组中:possible_values: [[usize; d]; d]
possible_values[i][j] = (N + A[i] - B[j]) % N
.这是 O(d^2)。
接下来,找到所有唯一的 s
值(即 possible_values[i][j]
的唯一值)并存储每个索引列表 s
HashMap 中的值 unique_possible_values: HashMap<usize, Vec<(usize, usize)>>
.这句话不是很清楚,所以这就是我的意思:
let unique_possible_values: HashMap<usize, Vec<(usize, usize)>> = HashMap::new();
for i in 0..d {
for j in 0..d {
let indexes_with_same_value =
unique_possible_values
.entry(possible_values[i][j])
.or_insert(Vec::new());
indexes_with_same_value.push((i, j));
}
}
换句话说,hashmap的每个条目都存储了二维索引列表(i,j)
共享相同的 possible_values[i][j]
值(value)。这是 O(d^2)。
然后,对于每个唯一的 s
value ( for (s, indexes) in &unique_possible_values
),计算它具有的循环相等元素的数量。这等于独特的数量 i
-值和独特的数量j
-values,可以在 O(indexes.len())
中计算时间。我不打算为此编写代码,但这应该不难,而且它是 O(d^2)(因为您迭代的每个 2D 索引恰好出现一次)。
取第 3 步中所有计数的最大值。这是最坏情况下的 O(d^2),平均情况下要低得多。这个最终值对应于 A 和 B 循环交集的最大可能大小。
检查该值是否超过 threshold
.如果是,则返回 true;否则,返回 false。
这个算法基本上枚举了所有可能的s
- 以高效的方式计算最大交叉点长度。
关于arrays - 计算排序数组与循环移位交集的快速算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74168192/
我正在尝试创建一个包含 int[][] 项的数组 即 int version0Indexes[][4] = { {1,2,3,4}, {5,6,7,8} }; int version1Indexes[
我有一个整数数组: private int array[]; 如果我还有一个名为 add 的方法,那么以下有什么区别: public void add(int value) { array[va
当您尝试在 JavaScript 中将一个数组添加到另一个数组时,它会将其转换为一个字符串。通常,当以另一种语言执行此操作时,列表会合并。 JavaScript [1, 2] + [3, 4] = "
根据我正在阅读的教程,如果您想创建一个包含 5 列和 3 行的表格来表示这样的数据... 45 4 34 99 56 3 23 99 43 2 1 1 0 43 67 ...它说你可以使用下
我通常使用 python 编写脚本/程序,但最近开始使用 JavaScript 进行编程,并且在使用数组时遇到了一些问题。 在 python 中,当我创建一个数组并使用 for x in y 时,我得
我有一个这样的数组: temp = [ 'data1', ['data1_a','data1_b'], ['data2_a','data2_b','data2_c'] ]; // 我想使用 toStr
rent_property (table name) id fullName propertyName 1 A House Name1 2 B
这个问题在这里已经有了答案: 关闭13年前。 Possible Duplicate: In C arrays why is this true? a[5] == 5[a] array[index] 和
使用 Excel 2013。经过多年的寻找和适应,我的第一篇文章。 我正在尝试将当前 App 用户(即“John Smith”)与他的电子邮件地址“jsmith@work.com”进行匹配。 使用两个
当仅在一个边距上操作时,apply 似乎不会重新组装 3D 数组。考虑: arr 1),但对我来说仍然很奇怪,如果一个函数返回一个具有尺寸的对象,那么它们基本上会被忽略。 最佳答案 这是一个不太理
我有一个包含 GPS 坐标的 MySQL 数据库。这是我检索坐标的部分 PHP 代码; $sql = "SELECT lat, lon FROM gps_data"; $stmt=$db->query
我需要找到一种方法来执行这个操作,我有一个形状数组 [批量大小, 150, 1] 代表 batch_size 整数序列,每个序列有 150 个元素长,但在每个序列中都有很多添加的零,以使所有序列具有相
我必须通过 url 中的 json 获取文本。 层次结构如下: 对象>数组>对象>数组>对象。 我想用这段代码获取文本。但是我收到错误 :org.json.JSONException: No valu
enter code here- (void)viewDidLoad { NSMutableArray *imageViewArray= [[NSMutableArray alloc] init];
知道如何对二维字符串数组执行修剪操作,例如使用 Java 流 API 进行 3x3 并将其收集回相同维度的 3x3 数组? 重点是避免使用显式的 for 循环。 当前的解决方案只是简单地执行一个 fo
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我有来自 ASP.NET Web 服务的以下 XML 输出: 1710 1711 1712 1713
如果我有一个对象todo作为您状态的一部分,并且该对象包含数组列表,则列表内部有对象,在这些对象内部还有另一个数组listItems。如何更新数组 listItems 中 id 为“poi098”的对
我想将最大长度为 8 的 bool 数组打包成一个字节,通过网络发送它,然后将其解压回 bool 数组。已经在这里尝试了一些解决方案,但没有用。我正在使用单声道。 我制作了 BitArray,然后尝试
我们的数据库中有这个字段指示一周中的每一天的真/假标志,如下所示:'1111110' 我需要将此值转换为 boolean 数组。 为此,我编写了以下代码: char[] freqs = weekday
我是一名优秀的程序员,十分优秀!