【问题标题】:How to reduce time complexity of the code?如何降低代码的时间复杂度?
【发布时间】:2019-09-05 05:04:41
【问题描述】:

我已经给队列初始位置增加了 1,从行前的 1 到后面的 n。

队列中的任何人都可以贿赂直接排在他们前面的人以交换位置。如果两个人交换位置,他们仍然会佩戴相同的标签,表示他们原来的位置。一个人最多可以贿赂另外两个人。例如,如果 n = 8 和 Person 5 贿赂 Person 4,则队列将如下所示:1,2,3 ,5,4,6,7,8.

minimumbribes 必须打印一个整数,表示创建原始队列所需的最低贿赂数量,如果行配置不可行,则Too chaotic。如果一个人的贿赂数量不超过 2,则线路配置是不可能的。

minimumBribes 具有以下参数:

  • q:整数数组。
  • 1

示例输入

2
5
2 1 5 3 4
5
2 5 1 3 4

输出

3
Too chaotic

使用排序逻辑,我刚刚计算了来得早的人,并且大于跟随人。如果线路配置可能,它还会打印贿赂总数,否则它会打印 Too chaotic 消息。

static void minimumBribes(int[] q) {
    int count = 0; // Counts the no of bribes by an individual.
    int j;
    int total = 0; // Total no of bribes.

   loop1 : for(int i = 0; i < q.length; i++) {
      loop2 :  for(j = i; j < q.length; j++) {
            if(q[i] > q[j]) {
                count++;
                if(count > 2) {
                    System.out.println("Too chaotic");
                    break loop1;
                }

            }
            else if (q[i] <= q[j]) {
                total += count;
                count = 0;

            }
        }
    }
    if(count <= 2)    
    System.out.println(total);
}

上面提到的代码对于一个小队列运行完美,但是如果一个数组的大小很大,它就会超过固定的处理时间限制。

【问题讨论】:

    标签: java performance time-complexity


    【解决方案1】:

    我刚刚在 python 中解决了这个问题,以便更好地理解这个问题。

    我决定从队列中的最后一个人开始,因为我们可以立即对这个人说很多话:

    1. 他们只能向前行贿(即他们背后没有人行贿)
    2. 他们不能贿赂距离“EOQ”超过两个位置 [,其中 EOQ 表示队列结束或此人的初始位置]。

    我们可以将此规则应用于从N 到1 的所有人。

    伪代码:

    FOR PERSON in [N to 1]:
      P = PERSON
      IF (P MORE THAN 2 POSITIONS FROM INITIAL POS; OR P IS FURTHER BACK IN QUEUE):
        PRINT 'Too chaotic'
        RETURN
    
      FOR POS in [CURR_POS[P] to INIT_POS[P]]:     
         SWAP POSITION OF P AND PERSON_TO_THE_RIGHT_OF_P
         INCREMENT COUNT OF BRIBES BY 1
    
    PRINT COUNT_OF_BRIBES
    

    注意事项

    • INIT_POS[P]是指贿赂发生前的初始位置,所以INIT_POS[PERSON_5] = 5

    • CURR_POS[P] 指的是P 在算法开始或任何交换之后的当前位置。

    • 在这个算法的最后,(假设贿赂不是混乱的)以下不变量应该成立:CURR_POS[i] == i。原因是因为我们所做的只是在贿赂发生之前让所有人回到原来的位置。

    【讨论】:

    • 正如我之前已经提到的,我的问题中发布的代码将运行得非常好,但问题是效率不高。如果您仔细注意到您的代码将花费更多时间进行处理,因为它必须进行交换然后计数。这可以在不交换的情况下完成。请记住,队列大小可以是 100000 个元素。
    • @apoorvasharma 有趣的是,您说这需要更多时间,因为我实际上是用 Python 编写并提交(在hackerrank 上),它很好地完成了所有 11 个问题。这个也是O(N),而你的更接近O(N ^ 2)。执行交换的内部循环最多只运行两次(每次迭代),因此交换是恒定的
    • " 进行交换的内部循环最多只运行两次(每次迭代),所以交换是恒定的“如何??我已经尝试了所有方法,但它没有在 java 中运行,只有 7/11 测试用例运行与之前相同。
    • @apoorvasharma 这与我们对队列中最后一个人的看法有关。正如我上面所说,这个人不能超过队列末尾的两个位置。此外,此人不能贿赂除他们前面的人之外的任何其他人。但这也适用于队列中最后一个人前面的那个人——他们不能贿赂后面的任何人,而且他们不能比他们的起源领先两个以上的位置。所以我们需要做的就是从最后一个人开始检查每个人的位置,并在验证他们的贿赂时将他们移动到原来的位置。
    【解决方案2】:
    static void minimumBribes(int[] q) {
        int count = 0; // Counts the no of bribes by an individual.
    
        int total = 0; // Total no of bribes.
    
       loop1 : for(int i = 0; i < q.length; i++) {
                  if((q[i]-(i+1))>2){//original position i should be person i+1 
                    System.out.println("Too chaotic");
                    break loop1;
                  }  
                  else if((q[i]-(i+1))>0){
                      count=q[i]-(i+1);
                      total += count;
                      count = 0;
                  }
                }
    
    
    
        if(count <= 2)    //not sure what dose this sentence do?
        System.out.println(total);
    }
    

    这是你问的吗?不确定我是否理解正确

    【讨论】:

    • 我想你还没有理解这个问题。您必须打印最后发生的贿赂总数。也就是说,您必须计算所有可能的贿赂并加起来。
    • 你的意思是根据输入队列打印发生了多少贿赂?
    • 是的。你的代码关于“太混乱”的部分是正确的。
    • 那么,另一部分有什么问题?我计算每人的计数,并将计数加到总数中。
    • 它将始终打印 0,因为您没有增加计数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-28
    • 2011-06-15
    • 1970-01-01
    相关资源
    最近更新 更多