【问题标题】:Algorithm - Police and thief in Grid(N*N)算法 - 网格中的警察和小偷(N*N)
【发布时间】:2017-09-25 03:12:28
【问题描述】:

问题陈述:
给定 N*N 矩阵,矩阵中的每个单元格都包含警察或小偷。 找出被警方逮捕的小偷人数。

  1. 警察只能逮捕一个小偷。
  2. 警察可以在同一排逮捕小偷。
  3. 警察可以在K范围内抓小偷。(例如:如果K为1,那么3号牢房的警察只能抓2号和4号牢房的小偷)

输入:
3 1 -> 这里 3 是 N, 1 是 K
呸呸呸
T T P
呸呸呸

输出:
3

我的解决方案因某些输入而超时:

1. Iterate each row and have two Treeset<Integer> to store position of police and thief
2. If current item is Police, then check if thief Treeset is Not empty, 
   a.if so then iterate the treeset to find the position from thief set which 
   can be removed(satisfying above criteria), remove thief from treeset and 
   increment counter.
     a.1. If such item not available then add current position to police set
   b. if not then add position to police treeset

3. If current item is Thief, then do the same

在对一行完成迭代后,对下一行进行迭代,最后打印计数器。

取一行的时间复杂度:
1. 迭代行中的每个元素 O(n)
2. 从树集中添加或删除元素 O(log(n))
肯定需要超过 O(n*log(n))

请告诉我这是什么类型的问题以及我应该如何有效地解决。

【问题讨论】:

  • 对 N(矩阵大小)有什么限制?
  • 提示:解决方案应该是O(N^2)。有 N^2 个单元格,每个单元格必须至少检查一次。但我认为您不需要检查单元格超过恒定次数。 (基于我脑海中的算法:-))这意味着O(N^2)
  • 现在如果给你警察的职位,O(P) 的解决方案可能是可能的......其中P 是警察的人数。 (这也是基于矩阵的问题的一点提示。)
  • 好吧,现在我注意到外面,有完全相同的问题(确切的措辞)......很有可能是那些在线比赛的一些问题,是吗?stackoverflow.com/questions/46397308/…跨度>
  • 是的,同一个,在线测试中

标签: java algorithm matrix


【解决方案1】:

这似乎可以通过贪婪策略来解决。您可以使用队列来存储警察和小偷的索引,或者指针(一个指针用于警察,一个指针用于小偷)。

使用指针(或存储索引的变量),您可以执行以下操作:

  1. 声明两个变量,例如policeIndexthiefIndex。对于每一行:

  2. policeIndex 走到该行中下一个警察的索引处,并将thiefIndex 走到该行中下一个小偷的索引处。

  3. 比较policeIndexthiefIndex

    3.1。如果它们之间的绝对差小于或等于k,则将逮捕人数增加一。返回第 2 步。

    3.2。否则,根据更改的索引,将最低索引(policeIndexthiefIndex)带到下一个警察或小偷。返回第 3 步。

  4. 重复直到policeIndexthiefIndex 到达行尾,然后转到下一行。

对于队列,您将执行基本相同的策略:使用该类型的所有索引填充每个队列(警察和小偷);然后得到每个队列的第一个元素之间的差异,然后:如果它们的差异小于或等于k,则删除两个元素并增加逮捕数;否则,从两个队列之一中删除最低索引并再次比较。重复此操作,直到任何队列为空。

【讨论】:

  • 谢谢乔治,我的方法很相似,但使用的是 TreeSet 而不是队列或指针,所以我认为这是一个问题。我不需要 Treeset 以任何方式按顺序存储
  • @乔治。我使用了队列,但方法有点不同。我维护了 2 个队列。一种用于存储警察索引的警察,另一种用于存储小偷索引的盗贼。对于每一排,如果我遇到警察,我会查看小偷队列。我不断弹出小偷,直到找到第一个在k范围内的小偷。如果毕竟弹出。队列中没有任何元素。我在警察队列中加入警察。如果范围内存在小偷,我会弹出小偷并增加计数。
  • 反之亦然,如果我遇到小偷,我会查看警察队列并遵循类似的步骤。使用这些步骤,我无法清除所有测试用例。
  • @Manya,我看到您正在使用 ArrayDeque,但尝试使用没有任何移除成本的 Linkedlist。我现在正在尝试,我的实现和你的一样,但是我使用了树集,所以对于一些测试用例它超时了。
【解决方案2】:

使用 C++:

可以使用向量而不是再次迭代来查找索引。

int solution (vector<vector<char> > A, int K) {
    int res=0;
   for(int i=0;i<A.size();i++)
   {
       vector<int> pol;
       vector<int> thi;
       for(int j=0;j<A[0].size();j++)
       {
           if (A[i][j] == 'P') 
            pol.push_back(j); 
        else if (A[i][j] == 'T') 
            thi.push_back(j);
       }

       // track lowest current indices of 
    // thief: thi[l], police: pol[r] 

       int l = 0, r = 0; 
    while (l < thi.size() && r < pol.size()) {
        if (abs(thi[l] - pol[r]) <= K) { 
            res++; 
            l++; 
            r++; 
        } 
        // increment the minimum index 
        else if (thi[l] < pol[r]) 
            l++;
        else
            r++; 
    }
    pol.clear();
    thi.clear();
   }
   return res;
}

它通过了所有测试用例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-22
    • 2023-03-25
    相关资源
    最近更新 更多