int n, k;
int count = 0, diff;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] input;
input = br.readLine().split(" ");
n = Integer.parseInt(input[0]);
int[] a = new int[n];
k = Integer.parseInt(input[1]);
input = br.readLine().split(" ");
for (int i = 0; i < n; i++) {
a[i] = Integer.parseInt(input[i]);
for (int j = 0; j < i; j++) {
diff = a[j] - a[i];
if (diff == k || -diff == k) {
count++;
}
}
}
System.out.print(count);
这是我打印特定差异计数的示例程序,其中n范围<= 100000 现在的问题是减少这个程序的执行。如何才能更好地减少运行时间。
提前感谢您的建议
答案 0 :(得分:4)
从文件中读取数字并将它们放在Map中(数字作为键,其频率作为值)。迭代它们一次,并为每个数字检查地图是否包含添加了k
的数字。如果是这样,请增加您的柜台。如果您使用HashMap,那就是O(n)
,而不是算法的O(n^2)
。
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int k = Integer.parseInt(br.readLine().split(" ")[1]);
Map<Integer, Integer> readNumbers = new HashMap<Integer, Integer>();
for (String aNumber : br.readLine().split(" ")) {
Integer num = Integer.parseInt(aNumber);
Integer freq = readNumbers.get(num);
readNumbers.put(num, freq == null ? 1 : freq + 1);
}
int count = 0;
for (Integer aNumber : readNumbers.keySet()) {
int freq = readNumbers.get(aNumber);
if (k == 0) {
count += freq * (freq - 1) / 2;
} else if (readNumbers.containsKey(aNumber + k)) {
count += freq * readNumbers.get(aNumber + k);
}
}
System.out.print(count);
编辑已修复重复且k = 0
答案 1 :(得分:3)
以下是使用HashSet,TIntIntHashSet和原始解决方案的@ Socha23解决方案的比较。
对于100,000个数字,我得到以下内容(没有阅读和解析)
对于100个唯一值,k = 10
Set: 89,699,743 took 0.036 ms
Trove Set: 89,699,743 took 0.017 ms
Loops: 89,699,743 took 3623.2 ms
对于1000个唯一值,k = 10
Set: 9,896,049 took 0.187 ms
Trove Set: 9,896,049 took 0.193 ms
Loops: 9,896,049 took 2855.7 ms
代码
import gnu.trove.TIntIntHashMap;
import gnu.trove.TIntIntProcedure;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
class Main {
public static void main(String... args) throws Exception {
Random random = new Random(1);
int[] a = new int[100 * 1000];
int k = 10;
for (int i = 0; i < a.length; i++)
a[i] = random.nextInt(100);
for (int i = 0; i < 5; i++) {
testSet(a, k);
testTroveSet(a, k);
testLoops(a, k);
}
}
private static void testSet(int[] a, int k) {
Map<Integer, Integer> readNumbers = new HashMap<Integer, Integer>();
for (int num : a) {
Integer freq = readNumbers.get(num);
readNumbers.put(num, freq == null ? 1 : freq + 1);
}
long start = System.nanoTime();
int count = 0;
for (Integer aNumber : readNumbers.keySet()) {
if (readNumbers.containsKey(aNumber + k)) {
count += (readNumbers.get(aNumber) * readNumbers.get(aNumber + k));
}
}
long time = System.nanoTime() - start;
System.out.printf("Set: %,d took %.3f ms%n", count, time / 1e6);
}
private static void testTroveSet(int[] a, final int k) {
final TIntIntHashMap readNumbers = new TIntIntHashMap();
for (int num : a)
readNumbers.adjustOrPutValue(num, 1,1);
long start = System.nanoTime();
final int[] count = { 0 };
readNumbers.forEachEntry(new TIntIntProcedure() {
@Override
public boolean execute(int key, int keyCount) {
count[0] += readNumbers.get(key + k) * keyCount;
return true;
}
});
long time = System.nanoTime() - start;
System.out.printf("Trove Set: %,d took %.3f ms%n", count[0], time / 1e6);
}
private static void testLoops(int[] a, int k) {
long start = System.nanoTime();
int count = 0;
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < i; j++) {
int diff = a[j] - a[i];
if (diff == k || -diff == k) {
count++;
}
}
}
long time = System.nanoTime() - start;
System.out.printf("Loops: %,d took %.1f ms%n", count, time / 1e6);
}
private static long free() {
return Runtime.getRuntime().freeMemory();
}
}
答案 2 :(得分:1)
由于split()
使用正则表达式来分割字符串,因此您应该测量StringTokenizer是否会加快速度。
答案 3 :(得分:1)
您正在尝试查找具有差异k
的元素。试试这个:
k
来调整其中一个答案 4 :(得分:1)
值的稀疏映射及其出现频率。
SortedMap<Integer, Integer> a = new TreeMap<Integer, Integer>();
for (int i = 0; i < n; ++i) {
int value = input[i];
Integer old = a.put(value, 1);
if (old != null) {
a.put(value, old.intValue() + 1);
}
}
for (Map.Entry<Integer, Integer> entry : a.entrySet()) {
Integer freq = a.get(entry.getKey() + k);
count += entry.getValue() * freq; // N values x M values further on.
}
这个O(n)。
如果成本过高,您可以对输入数组进行排序并执行类似操作。
答案 5 :(得分:0)
我不明白你为什么在另一个圈内有一个循环。这样O(n^2)
。
你也可以将这个数组中的读数与得到这个计数混合起来。我将两者分开 - 读完整个内容然后扫过并获得差异计数。
也许我误解了你正在做的事情,但感觉你在内循环中重新做了很多工作。
答案 6 :(得分:0)
为什么不使用java.util.Scanner类而不是BufferReader。
例如: -
Scanner sc = new Scanner(System.in);
int number = sc.nextInt();
这可能会更快,因为他们的包装更少...... See this link
答案 7 :(得分:0)
使用集合和地图,正如其他用户已经解释的那样,所以我不会再重申他们的建议。
我会建议别的。
停止使用String.split
。它编译并使用正则表达式。
String.split
中有一行:Pattern.compile(expr).split(this)
。
如果你想沿着单个字符分割,你可以编写自己的函数,它会快得多。我相信Guava(ex-Google collections API)具有String split功能,可以在不使用正则表达式的情况下拆分字符。