【问题标题】:given an array for each element count how many divisibility给定一个数组,每个元素计数多少分
【发布时间】:2021-04-19 04:35:41
【问题描述】:

我有一个数字列表,现在我想从列表中取出一个数字并检查有多少元素可以将该数字除以余数为 0。

这是我的代码:

public static void countDivibilies(List<Integer> list) {
    for (int i = 0; i < list.size(); i++) {
        int e = list.get(i);
        int count = 0;
        for (int j = 0; j < list.size(); j++) {
            int k = list.get(j);
            if (e % k == 0) {
                count++;
            }
        }
        System.out.println(e + " : " + count);
    }
}

对于样本输入:

2, 4, 8, 2

输出是:

2 : 2
4 : 3
8 : 4
2 : 2

但是这段代码以O(n<sup>2</sup>) 的时间复杂度运行。但我的输入列表大小范围最大为 105,每个元素也在 1 到 105 之间。那么如何才能提高这个程序的时间复杂度呢?

【问题讨论】:

  • 好吧,通常如果2 有两个潜在的除数,而24 的一个除数,我倾向于说它比2 多了一个除数。提示:首先对列表进行排序
  • 每个元素的最大值是多少?
  • @iota,每个元素也是 10 次方 5,我现在用它来更新我的问题
  • 所以这个任务不在线,是你自己编的? (这也可以解释名称countDivibilies :-)

标签: java algorithm


【解决方案1】:
  1. O(N) 时间从List 创建频率Map
  2. 计算List 的每个元素在O(sqrt(N)) 时间的除数。使用频率Map 找出元素在List 中有多少个除数。总时间复杂度为O(Nsqrt(N))
public static void countDivibilies(List<Integer> list) {
    Map<Integer, Integer> freq = list.stream()
       .collect(Collectors.toMap(x -> x, x -> 1, Integer::sum));
    for(int x : list){
        int count = 0;
        for(int i = 1; i * i <= x; i++){
            if(x % i == 0) {
                count += freq.getOrDefault(i, 0);
                if(x / i != i) //don't overcount square root
                   count += freq.getOrDefault(x / i, 0);
            }
        }
        System.out.println(x + " : " + count);
    }
}

【讨论】:

  • 您能解释一下为什么我们从 i =1 运行内部循环吗?还有 if 条件 if(x % i == 0) {if(x / i != i) 以及我们递增计数的方式
  • @learner 我们正在寻找数字的除数。每次我们找到一个,我们将计数增加除数出现在列表中的次数。
  • 你的 N 是多少?
  • @Manuel 列表的最大尺寸和最大元素。
猜你喜欢
  • 1970-01-01
  • 2012-03-18
  • 2019-09-19
  • 1970-01-01
  • 2017-09-12
  • 1970-01-01
  • 2018-12-30
  • 2015-08-15
  • 1970-01-01
相关资源
最近更新 更多