简体   繁体   English

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

[英]how can i amend this code to have a time complexity of o(log n) or o(n) instead of o(n^2)

How can I solve this in o(n) or o(logn)? 如何在o(n)或o(logn)中解决这个问题?

After the lessons n groups of schoolchildren went outside and decided to visit Polycarpus to celebrate his birthday. 课后,n群学童走出校外,决定前往Polycarpus庆祝他的生日。 We know that the i-th group consists of si friends (1 ≤ si ≤ 4), and they want to go to Polycarpus together. 我们知道第i组由si朋友组成(1≤si≤4),他们想一起去Polycarpus。 They decided to get there by taxi. 他们决定乘坐出租车到达那里。 Each car can carry at most four passengers. 每辆车最多可搭载4名乘客。 What minimum number of cars will the children need if all members of each group should ride in the same taxi (but one taxi can take more than one group)? 如果每个小组的所有成员都应该乘坐同一辆出租车(但一辆出租车可以乘坐多个小组),孩子们需要的最小车辆数量是多少? Following is my approach but in o(n^2) 以下是我的方法,但在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;
    }
  }
}

You'll never achieve O(log N) since you have to examine every group. 你永远不会达到O(log N),因为你必须检查每个组。

You can do it in a single traversal of the set of groups and a cache: so O(N). 你可以在一组组和一个缓存的单次遍历中完成它:所以O(N)。

For each group, count the size. 对于每个组,计算大小。

  1. If it's 4, then add a taxi. 如果是4,那就加一辆出租车。
  2. If it's 3, then attempt to pair with a cached 1, if not, cache that group. 如果是3,则尝试与缓存的1配对,如果不是,则缓存该组。
  3. If it's 1, then attempt to pair with a cached 3, if not, cache that group. 如果它为1,则尝试与缓存的3配对,如果不是,则缓存该组。
  4. If it's 2, then attempt to pair with a cached 2, if not, cache that group. 如果是2,则尝试与缓存的2配对,如果没有,则缓存该组。

Examine your cache. 检查你的缓存。 Pair any group of 2 with one or more group of 1. Then pair any remaining groups of 1. 将任意一组2与一个或多个1组配对。然后将任何剩余的1组配对。

A similar solution to what Bathsheba suggested, but based on the number of groups of each size instead of caching : 类似于Bathsheba建议的解决方案,但基于每个大小的组数而不是缓存:

Iterate over the list of group once and count how many there are of each size. 迭代组列表一次并计算每个大小的数量。 This required O(n) time and gives you the following counters : 这需要O(n)时间,并为您提供以下计数器:

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

Now calculate the number of cars based on these counters (this calculation takes O(1) ) : 现在根据这些计数器计算汽车数量(此计算需要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
}

There are only 4 group sizes: 1, 2, 3 or 4. 只有4个组大小:1,2,3或4。

Initialize an array of counts for each size, pass through your array of group sizes, incrementing the appropriate array element for the group size. 初始化每个大小的计数数组,传递组大小数组,为组大小增加适当的数组元素。

// 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];
}

which is O(n) . 这是O(n)

Then, pass through like this: 然后,像这样通过:

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;

which is O(1) , meaning O(n) overall. 这是O(1) ,意味着总体上是O(n)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM