我一直在我的业余时间工作面试街挑战改变比赛一个多星期,现在只是旋转我的车轮,所以我希望有人可以给我一个指针或提示正确的方向。
挑战的基础是采取两个字符串A& B并运行一些操作两位字符串的查询。
设A和B为两个N位数。您将获得A和B的初始值,您应该编写一个处理三种查询的程序:
其中位数的长度为1到100,000,并且程序可以包含set_a,set_b或get_c的任意组合的1到500,000个查询。
为了最小化循环,我使用C作为运行总计。当A或B中的位改变时,也从C加上或减去改变的位。当存在进位时,进一步最小化加法和减法时的循环从改变的位到左手完成。
private static void add(final boolean[] the_array, final int the_index)
{
for(int iter = the_array.length - the_index - 1; iter >= 0; iter--)
{
if(the_array[iter])
{
the_array[iter] = false;
}
else if(!the_array[iter])
{
the_array[iter] = true;
return ;
}
}
}
private static void subtract(final boolean[] the_array, final int the_index)
{
for(int iter = the_array.length - the_index - 1; iter >= 0; iter--)
{
if(the_array[iter])
{
the_array[iter] = false;
return ;
}
else if(!the_array[iter])
{
the_array[iter] = true;
}
}
}
整体而言,该程序运行良好,完成了最大边缘长度为100,000的情况,500,000个查询在大约120ms内运行但是仍然不够快,无法应对挑战。由于比特长度的大小快速超过Java中的原始整数(长)值,因此大多数API不适用于此。由于我没有取得多大进展,因此整体运行时间的大小开始表明可能存在一种算法或数据结构,而不仅仅是一个数组。有什么想法吗?
答案 0 :(得分:3)
A: 001101001010111
B: 010110100010110
^ asked for C there
1000111^ only need to add bits from here
^ until you get your answer.
答案 1 :(得分:2)
我会使用long []而不是boolean []。每个long都有64位,您可以执行组合操作,如
if (the_array[iter] == -1L) // all 1s
the_array[iter] = 0L; // all zeros.
您可以在与布尔操作大致相同的时间内执行64位操作,从而使循环速度提高64倍。
BTW:使用boolean[]
将使用8倍于long[]
的内存,因为每个boolean
在大多数JVM中使用一个字节的内存。
使用较长类型存储数据的示例。
long[]
来存储其位。 http://fuseyism.com/classpath/doc/java/util/BitSet-source.html int[]
存储其位。 http://developer.classpath.org/doc/java/math/BigInteger-source.html 根据您的效果,使用int
可以更轻松地进行操作,例如x = (long) a * b
会溢出long
但不会int
。
如果您正在扫描大量位(如BitSet可以做的那样),那么使用long[]
会更快。
添加一个基准,显示它可以做出的时间差异。
public static final int RUNS = 100;
public static void main(String... args) throws InterruptedException {
boolean[] bools = new boolean[1024 * 1024];
long[] longs = new long[bools.length / 64];
for (int i = 0; i < 5; i++) {
testBools(bools);
testLongs(longs);
}
}
private static void testBools(boolean[] bools) {
long start = System.nanoTime();
for (int t = 0; t < RUNS; t++) {
// set all to true
for (int i = 0; i < bools.length; i++)
bools[i] = true;
// search for a false;
for (boolean b : bools)
if (!b) throw new AssertionError();
// set all to false
for (int i = 0; i < bools.length; i++)
bools[i] = false;
// search for a true;
for (boolean b : bools)
if (b) throw new AssertionError();
}
long time = System.nanoTime() - start;
System.out.printf("To set and scan a boolean[] with %,d bits took %,d us%n",
bools.length, time / 2/ RUNS / 1000);
}
private static void testLongs(long[] longs) {
long start = System.nanoTime();
for (int t = 0; t < RUNS; t++) {
// set all to true
for (int i = 0; i < longs.length; i++)
longs[i] = ~0; // all 1s
// search for a false;
for (long l : longs)
if (l != ~0) throw new AssertionError();
// set all to false
for (int i = 0; i < longs.length; i++)
longs[i] = 0; // all 0s
// search for a true;
for (long l : longs)
if (l != 0) throw new AssertionError();
}
long time = System.nanoTime() - start;
System.out.printf("To set and scan a long[] with %,d bits took %,d us%n",
longs.length * Long.SIZE, time / 2/ RUNS / 1000);
}
打印
To set and scan a boolean[] with 1,048,576 bits took 777 us
To set and scan a long[] with 1,048,576 bits took 104 us
To set and scan a boolean[] with 1,048,576 bits took 666 us
To set and scan a long[] with 1,048,576 bits took 20 us
To set and scan a boolean[] with 1,048,576 bits took 537 us
To set and scan a long[] with 1,048,576 bits took 18 us
To set and scan a boolean[] with 1,048,576 bits took 567 us
To set and scan a long[] with 1,048,576 bits took 28 us
To set and scan a boolean[] with 1,048,576 bits took 776 us
To set and scan a long[] with 1,048,576 bits took 27 us
在此示例中,与boolean[]
long[]
的速度要慢30倍