任何用于smoosh方法的O(n)算法?

时间:2012-10-01 03:49:36

标签: java algorithm

我正在尝试完成一个smoosh()方法,该方法需要一组int。完成后,数组仍应包含相同的数字,但无论数组有两个或多个连续的重复数字,它们都会被数字的一个副本替换。因此, 在smoosh()完成后,阵列中没有两个连续的数字是相同的。

数组末尾的任何未使用元素都设置为-1。

例如,如果输入数组是

[ 1 1 0 0 4 4 5 0 0 0 7 ]

它读取

[ 1 0 4 5 0 7 ] 

在smoosh()完成后。

方法签名是: public static void smoosh(int [] ints)

我能够这样做:

for (int i=0; i<ints.length-1; i++) {
    if (ints[i+1]==ints[i])
        ints[i]=-1;
}
for (int i=0; i<ints.length-1; i++) {
    if (ints[i]==-1) {
        for (int j=i+1; j<ints.length; j++) {
            if (ints[j]!=-1) {
                //swap ints[j] and ints[i] and then break;
            }
        }
    }
}

然而,这将是O(n2)时间(虽然几乎到位)。

我觉得应该有一些O(n)到位的方法来做到这一点,但我无法弄清楚如何。 谁能想到任何O(n)到位算法? (显然,如果你制作另一个相同大小的数组来帮助处理,那么你可以很容易地获得O(n),但这不是我想要的,因为它没有到位......)

谢谢!

3 个答案:

答案 0 :(得分:4)

基本上如下。这个O(n)-time,O(1)-space“算法”实际上是Python代码,因为只要你避开所有复杂的东西,比如lambdas,这就是教授基本算法的非常好的语言。

我实际上是用它来教我8岁的儿子,因为他表达了对我整天工作的兴趣。

array = [1, 1, 0, 0, 4, 4, 5, 0, 0, 0, 7]

print array

count = len (array)
last = array[0] - 1
toidx = 0
for fromidx in range (0, count):
    if array[fromidx] != last:
        array[toidx] = array[fromidx]
        toidx = toidx + 1
        last = array[fromidx]
while toidx < count:
    array[toidx] = -1
    toidx = toidx + 1

print array

这个输出是:

[1, 1, 0, 0, 4, 4, 5, 0, 0, 0, 7]
[1, 0, 4, 5, 0, 7, -1, -1, -1, -1, -1]

正如您的规范所要求的那样。

它基本上通过数组运行两个索引,fromix索引无论如何都会前进一个。 toidx索引仅在fromidx的值与传输的最后一个值不同时才会前进。传送的最后一个的初始值设置为与第一个元素不同的值,以确保传送第一个元素。

换句话说,在该条件为真的每次迭代中,from索引处的值被复制到toidx索引,toidx索引递增,{ {1}}值已更新。如果last的值与上次传输的值相同,则fromidx索引不会更新。

然后,最后,所有剩余的值都设置为-1。


由于您的规范要求使用-1填充数组的其余部分,这就是我在上面的代码中所做的。

但是,您的示例结果不包含负值,因此,如果您需要数组截断而不是填充toidx,则基本上替换{{1最后用数组截断循环,这样它的大小现在是-1

在Python中,您可以使用以下内容执行此操作:

while

答案 1 :(得分:3)

你的内循环没有必要。您只需跟踪您访问的最后一个值,然后开始跳过,直到找到“新”号码。例如在伪代码中

previous = null;
newarray = array();
newpos = 0;
for (i = 0; i < oldarray.length; i++) {
   if (oldarray[i] == previous) {
      continue; // got a duplicate value, so skip it.
   } else {
      newarray[newpos++] = oldarray[i];
      previous = oldarray[i];
   }
}
for (i = newpos; i < oldarray.length; i++) {
   newarray[i] = -1; // fill in any empty slots
}

现在你已经到了O(n)。

答案 2 :(得分:1)

如果您使用LinkedList,则可以使用ListIterator作为循环,将前一个值的值存储在列表中,如果它等于当前值,则调用ListIterator.remove