[英]O(log n) Programming
I am trying to prepare for a contest but my program speed is always dreadfully slow as I use O(n). 我正在努力为比赛做准备,但是当我使用O(n)时,我的程序速度总是非常慢。 First of all, I don't even know how to make it O(log n), or I've never heard about this paradigm.
首先,我甚至不知道如何制作O(log n),或者我从未听说过这种范式。 Where can I learn about this?
我在哪里可以了解到这一点?
For example, 例如,
If you had an integer array with zeroes and ones, such as [ 0, 0, 0, 1, 0, 1 ], and now you wanted to replace every 0 with 1 only if one of it's neighbors has the value of 1, what is the most efficient way to go about doing if this must occur t number of times? 如果你有一个带有0和1的整数数组,例如[0,0,0,1,0,1],现在你想要将每个0替换为1, 只要其中一个邻居的值为1,如果必须发生这种情况,这是最有效的方法吗? (The program must do this for a number of t times)
(该程序必须执行此操作数t次)
EDIT: Here's my inefficient solution: 编辑:这是我的低效解决方案:
import java.util.Scanner;
public class Main {
static Scanner input = new Scanner(System.in);
public static void main(String[] args) {
int n;
long t;
n = input.nextInt();
t = input.nextLong();
input.nextLine();
int[] units = new int[n + 2];
String inputted = input.nextLine();
input.close();
for(int i = 1; i <= n; i++) {
units[i] = Integer.parseInt((""+inputted.charAt(i - 1)));
}
int[] original;
for(int j = 0; j <= t -1; j++) {
units[0] = units[n];
units[n + 1] = units[1];
original = units.clone();
for(int i = 1; i <= n; i++) {
if(((original[i - 1] == 0) && (original[i + 1] == 1)) || ((original[i - 1] == 1) && (original[i + 1] == 0))) {
units[i] = 1;
} else {
units[i] = 0;
}
}
}
for(int i = 1; i <= n; i++) {
System.out.print(units[i]);
}
}
} }
This is an elementary cellular automaton. 这是一个基本的细胞自动机。 Such a dynamical system has properties that you can use for your advantages.
这种动态系统具有可用于您的优势的属性。 In your case, for example, you can set to value 1 every cell at distance at most t from any initial value 1 (cone of light property).
例如,在您的情况下,您可以将距离任何初始值1(光锥属性)的距离最多为t的每个单元格设置为值1。 Then you may do something like:
然后你可以这样做:
You may then take as your advantage in the next step that you've already set position pt to p+t... This can let you compute the final step t without computing intermediary steps (good factor of acceleration isn't it?). 然后你可以在下一步中把你的位置pt设置为p + t ...这可以让你计算最后一步t而无需计算中间步骤(加速的好因素不是吗?) 。
You can also use some tricks as HashLife, see 1 . 你也可以使用一些技巧作为HashLife,见1 。
As I was saying in the comments, I'm fairly sure you can keep out the array and clone
operations. 正如我在评论中所说,我相当确定你可以阻止阵列和
clone
操作。
You can modify a StringBuilder
in-place, so no need to convert back and forth between int[]
and String
. 您可以就地修改
StringBuilder
,因此无需在int[]
和String
之间来回转换。
For example, (note: This is on the order of an O(n)
operation for all T <= N
) 例如,(注意:对于所有
T <= N
,这是O(n)
操作的顺序)
public static void main(String[] args) {
System.out.println(conway1d("0000001", 7, 1));
System.out.println(conway1d("01011", 5, 3));
}
private static String conway1d(CharSequence input, int N, long T) {
System.out.println("Generation 0: " + input);
StringBuilder sb = new StringBuilder(input); // Will update this for all generations
StringBuilder copy = new StringBuilder(); // store a copy to reference current generation
for (int gen = 1; gen <= T; gen++) {
// Copy over next generation string
copy.setLength(0);
copy.append(input);
for (int i = 0; i < N; i++) {
conwayUpdate(sb, copy, i, N);
}
input = sb.toString(); // next generation string
System.out.printf("Generation %d: %s\n", gen, input);
}
return input.toString();
}
private static void conwayUpdate(StringBuilder nextGen, final StringBuilder currentGen, int charPos, int N) {
int prev = (N + (charPos - 1)) % N;
int next = (charPos + 1) % N;
// **Exactly one** adjacent '1'
boolean adjacent = currentGen.charAt(prev) == '1' ^ currentGen.charAt(next) == '1';
nextGen.setCharAt(charPos, adjacent ? '1' : '0'); // set cell as alive or dead
}
For the two samples in the problem you posted in the comments, this code generates this output. 对于您在注释中发布的问题中的两个示例,此代码生成此输出。
Generation 0: 0000001
Generation 1: 1000010
1000010
Generation 0: 01011
Generation 1: 00011
Generation 2: 10111
Generation 3: 10100
10100
The BigO notation is a simplification to understand the complexity of the Algorithm. BigO表示法是一种简化算法的复杂性。 Basically, two algorithms O(n) can have very different execution times.
基本上,两个算法O(n)可以具有非常不同的执行时间。 Why?
为什么? Let's unroll your example:
让我们展开你的例子:
So, in essence your algorithm is O(k * t * n) . 所以,实质上你的算法是O(k * t * n) 。 If t is in the same order of magnitude of n , then you can consider the complexity as O(k * n^2) .
如果t与n的数量级相同,则可以将复杂度视为O(k * n ^ 2) 。
There is two approaches to optimize this algorithm: 优化此算法有两种方法:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.