如何修改此代码以使时间复杂度为o(log n)或o(n)而不是o(n ^ 2)

时间:2017-01-18 12:48:25

标签: java optimization time brute-force greedy

如何在o(n)或o(logn)中解决这个问题?

课程结束后,各组学童走出校外,决定前往Polycarpus庆祝他的生日。我们知道第i组由si朋友组成(1≤si≤4),他们想一起去Polycarpus。他们决定乘坐出租车到达那里。每辆车最多可搭载4名乘客。如果每个小组的所有成员都应该乘坐同一辆出租车(但一辆出租车可以乘坐多个小组),孩子们需要的最小车辆数量是多少? 以下是我的方法,但在o(n ^ 2)

import java.util.*;

public class taxi {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    while (sc.hasNext()) {
      int cars = 0;
      int groups = sc.nextInt();
      int[] a = new int[groups];
      for (int i = 0; i < a.length; i++) {
        a[i] = sc.nextInt();
      }
      Arrays.sort(a);
      for (int i = a.length - 1; i > 0; i--) {

        if (a[i] == 4) {
          cars = cars + 1;
        } else {
          if (a[i] == 0) {
            break;
          } else {
            int y = 4 - a[i];
            for (int j = i - 1; j >= 0; j--) {
              if (y - a[j] == 0) {
                a[j] = 0;
                break;
              }
              if (y - a[j] > 0) {
                y = y - a[j];
                a[j] = 0;
              }
            }
            cars = cars + 1;
            Arrays.sort(a);
          }
        }
      }
      if (a[0] != 0) {
        cars++;
      }
      System.out.println(cars);
      cars = 0;
    }
  }
}

3 个答案:

答案 0 :(得分:2)

你永远不会达到O(log N),因为你必须检查每个组。

你可以在一组组和一个缓存中进行一次遍历:所以O(N)。

对于每个组,计算大小。

  1. 如果是4,那就加一辆出租车。
  2. 如果是3,则尝试与缓存的1配对,如果没有,则缓存该组。
  3. 如果是1,则尝试与缓存的3配对,如果没有,则缓存该组。
  4. 如果是2,则尝试与缓存的2配对,如果没有,则缓存该组。
  5. 检查您的缓存。将任意一组2与一组或多组1配对。然后将任何剩余的1组配对。

答案 1 :(得分:1)

与Bathsheba建议的类似解决方案,但基于每个大小的组数而不是缓存:

迭代组列表并计算每个大小的数量。这需要O(n)时间,并为您提供以下计数器:

int size1 = ...
int size2 = ...
int size3 = ...
int size4 = ...

现在根据这些计数器计算汽车数量(此计算需要O(1)):

int carsCount = size4; // add full cars (groups of 4)
carsCount += size3; // each group of 3 requires a separate car
carsCount += size2/2; // pairs of groups of 2
size1 -= size3; // group as many groups of 1 with groups of 3 as possible
boolean odd2s = (size2 % 2) == 1;
if (odd2s) {
    carsCount++; // add a car for the odd group of 2
}
if (size1 > 0) {
    if (odd2s) {
        size1 -= 2; // two groups of 1 can be paired with the odd group of 2
    }
}
if (size1 > 0) {
    carsCount += (size1 + 3) / 4; // any remaining groups of 1 are grouped in groups of 4
}

答案 2 :(得分:0)

只有4个组大小:1,2,3或4。

初始化每个大小的计数数组,传递组大小数组,为组大小增加适当的数组元素。

char ch;
std::cin >> ch;
if (ch == 'A')
...

// Count the number of groups of each size. int[] counts = new int[5]; // 1 more, just to use 1-based indexing. for (int e : a) { ++counts[e]; }

然后,像这样通过:

O(n)

int numTaxis = counts[4]; // 1 taxi for each 4-sized group. + counts[3]; // 1 taxi for each 3-sized group. + counts[2] / 2; // 1 taxi for each pair of 2-sized groups. // But you can put a 1-sized group in each 3-sized group's taxi. int unmatched1s = Math.max(0, counts[1] - counts[3]); // You require ceil(unmatched1s / 4) taxis for the 1-sized groups - // - but increase by 1 to handle the possibility of unpaired 2-sized group. numTaxis += (unmatched1s + counts[2] % 2 + 3) / 4; ,意思是O(1)整体。