【问题标题】:Optimizing matrix operation to complexity less than O(n^2)将矩阵运算优化为复杂度小于 O(n^2)
【发布时间】:2016-10-25 21:26:30
【问题描述】:

给定一个 2D 正方形 (n*n) 矩阵,我试图找出是否有一种方法可以在小于 O(n^2) 的时间内对矩阵的上三角形执行操作[最好线性时间]。请注意,矩阵元素是连续的,如示例所示。即:每行和每列中的所有值都已排序。我已经使用 O(n^2) 复杂度解决了这个问题。下面的例子:

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45

现在,如果我想对上三角形执行 XOR 操作,这意味着 XOR -ing 以下元素: 21^22^23^24^25^26^27^28^29^31^32^33^36^37^41 = 35,就是想要的结果。

换句话说,我基本上是异或:

21 22 23 24 25 26 27 28 29 31 32 33 36 37 41

我尝试通过生成二进制等效项来查找模式来使用 DP 来解决问题,但找不到任何一致的模式。

【问题讨论】:

  • 这个问题有点含糊。所以假设你想要的只是计算上三角形的异或。 那么 O(n^2 / 2)=O(n^2) 是下限,因为您需要查看三角形中的每个元素(=n^2/2 个元素)。这可能会因某些计算而改变,但 xor 函数非常敏感(不可能进行太多修剪;要查看的最后一个值可能会改变所有位)。
  • @sascha 另一方面,如果矩阵包含 n*n 个元素,那将被视为输入的大小 -> O(n/2)。
  • 是否有任何模式可以在二维矩阵中生成给定的数字?
  • 该矩阵中有哪些可能的值?
  • 当你说“连续”时,你的意思是元素m[i+1] = m[i] + 1吗?

标签: algorithm optimization bit-manipulation big-o dynamic-programming


【解决方案1】:

评论后编辑:

使用来自this post的方法

long long f(long long a) {
     long long res[] = {a,1,a+1,0};
     return res[a%4];
}

long long getXor(long long a, long long b) {
     return f(b)^f(a-1);
}

创建一个这样的循环:

long FinalXor = 0;
for(int i = 0 ; i< n; i++){
    FinalXor =FinalXor^getXor(m(i,0),m(i,0)+ n-i)
}

你只需要遍历每一行的第一个值,生成一个复杂度为 O(n) 的算法

【讨论】:

  • 感谢您的回复。我做了类似的事情。但是,我想知道是否有一种方法可以玩位操作,可以直接给出答案,而不必实际对所有连续数字进行异或。问题中有一个编辑。我忘了提到矩阵中的元素是连续的,如示例所示。换句话说,row 和 col 元素是排序的。无论如何,该编辑现在已被合并。
  • 好吧,考虑到这一点,我认为有更好的解决方案,使用this 解决方案来计算每行元素的异或,而不是对所有结果进行异或。由于这些值是连续的,您可以在 O(N) 中一次对每一行应用 getXor 方法来计算它
  • 这个范围是FinalXor =FinalXor^getXor(m(i,0),m(i,0)+ n-(i+1))有一个小的修改。但是,我无法清楚地理解它们是如何在引用的帖子中形成查找表的。如果您能解释一下 {a,1,a+1,0} 的模式是如何确定的,将会有很大帮助。
  • @user5566364 正如在提到的link 中给出的答案中所解释的那样,xor 操作将每四个术语“循环”一次:对于从 a 开始的元素,您将拥有(a, 1, a+1,0),所以你只需要知道选择的词是第一个,第二个,第三个还是第四个res[a%4]
【解决方案2】:

考虑到网格中数字模式的约束,有一种方法可以在 O(n) 时间内完成。 您首先需要编写一个函数,该函数能够在 O(1) 时间内为您提供 [1,n] 中所有数字的异或总和结果。

//iteratate in every row of the grid to find out xor sum of that row
//and xor add that sum with the final_xorsum
int final_xorsum=0;
for(i=0;i<n;i++) {
    final_xorsum^=xor_sum(biggest_num_in_row_i)^xor_sum(smallest_num_in_row_i-1);
}
cout<<final_xorsum<<endl;

//this function will retrun xor sum value of all the numbers [1...n]
//example: xor_sum(5) = 1^2^3^4^5
int xor_sum(int n) {
    int vals[4] = {a,1,a+1,0};
    return vals[a%4];
}

在此处阅读有关 xor_sum 函数的更多信息: Find XOR of all numbers in a given range

【讨论】:

  • 谢谢艾永。你能解释一下int vals[4] = {a,1,a+1,0}; return vals[a%4];背后的理由吗
  • @user5566364,这可以从你会注意到的连续异或序列中的模式来解释 (0,1,2,3,4,5,6,7) => (0,1, 3,0,5,1,7,0..)。更多解释见链接
猜你喜欢
  • 2022-08-13
  • 1970-01-01
  • 2022-03-04
  • 1970-01-01
  • 2023-03-16
  • 2019-12-09
  • 2019-12-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多