在数组中查找元素,但该元素可以跳转

时间:2016-03-22 08:23:39

标签: arrays algorithm

有一个数组,其中除了一个单元格之外的所有单元格都是0,我们想要找到该单个非零单元格的索引。问题是,每次检查此数组中的单元格时,该非零元素都将执行以下操作之一:

  1. 向前推进1
  2. 向后移动1
  3. 留在原地。
  4. 例如,如果该元素当前位于第10位,并且我检查arr[5]中的内容,那么在我选中arr[5]后该元素可能位于第9,10或11位。

    我们只需要找到元素当前所处的位置,而不是它开始的位置(这是不可能的)。

    困难的部分是,如果我们写一个for循环,真的无法知道元素当前是在你面前还是在你身后。

    如果它有帮助,可以提供更多上下文:

    1. 面试官确实给出了一个提示,也许我应该在检查x个细胞后将指针移回。问题是,我应该何时返回,以及插入多少个插槽?
    2. 在“大声思考”的同时,我开始说一些常见的方法,希望有什么东西会受到影响。当我说递归时,面试官确实说“递归是一个好的开始”。我不知道递归真的是正确的方法,因为我没有看到我如何能够同时进行递归和#1。
    3. 采访者说这个问题在O(n ^ 2)中无法解决。所以我们至少看O(n ^ 3),或者甚至指数。

5 个答案:

答案 0 :(得分:0)

不要忘记关于循环的一切。 将此数组复制到另一个数组,然后检查哪些单元格现在为非零。例如,如果你的主数组是mainArray [],你可以使用:

int temp[sizeOfMainArray]
int counter = 0;
while(counter < sizeOfArray)
{
    temp[counter] == mainArray[counter];
}
//then check what is non-zero in copied array
counter = 0;

while(counter < sizeOfArray)
{
    if(temp[counter] != 0)
{
    std::cout<<"I Found It!!!";
}
}//end of while

答案 1 :(得分:0)

或许可以采用一种方法:

i - 有四个索引变量f,f1,l,l1。 f指向0,f1指向1,l指向n-1(数组的末尾),l1指向n-2(倒数第二个元素)

ii - 检查f1和l1处的元素 - 它们中的任何一个都不为零吗?如果是这样的话。如果没有,检查f和l处的元素(以查看元素是否已跳回1)。

iii - 如果f和l仍然为零,则递增索引并重复步骤ii。当f1&gt;停止L1

答案 2 :(得分:0)

Iff 对数组索引进行等式检查会使非零元素跳转。

为什么不考虑一种我们不需要使用数组索引进行相等性检查的方法?

int check = 0;
for(int i = 0 ; i < arr.length ; i++) {
    check |= arr[i];
    if(check != 0)
        break;
}

Orrr。也许你可以继续阅读arr[mid]。非零元素将在那里结束。有一天。推理:帕特里克·特伦廷似乎把它放在了他的答案中(有点,不是那么,但你会得到一个想法)。

如果您有关于阵列的一些信息,也许我们可以提出一种更为狡猾的方法。

答案 3 :(得分:0)

忽略1在数组的第一个单元格中的简单情况如果迭代遍历数组依次测试每个元素,则必须最终到达1在单元格i + 2中的位置i。因此,当你阅读单元格i + 1时,将会发生三件事之一。

  1. 1保持原样,下次看时你会发现它
  2. 1离开你,你回到起始位置,下一次是i + 2,
  3. 1移动到您刚检查的单元格,它躲过了您的扫描
  4. 重新读取i + 1单元格会在案例3中找到1,但只是给它另一个机会在案例1和2中移动,因此基于重读的策略不会起作用。

    因此,我的选择是采用蛮力方法,如果我继续扫描阵列,那么我将在某个时刻点击案例1并找到难以捉摸的1。

答案 4 :(得分:0)

假设:

  1. 数组不是真正的数组。鉴于这个问题,这很明显。我们得到了一些类似于数组的类。

  2. 数组主要是隐藏的。唯一的公共操作是[]和size()。

  3. 数组被混淆了。我们无法通过检索它的地址来获取任何信息,然后分析该位置的内存。即使我们遍历系统的整个内存,由于一些先进的加密手段,我们也无法做到。

  4. 数组的每个字段都可能成为承载该字段的第一个字段。

  5. 我们知道触发后如何改变位置的可能性。

  6. 概率控制算法:

    1. 引入另一个大小相同的数组,即概率数组(超过两倍)。 初始化此数组,所有字段均为1 / size。
    2. 每当我们在基础数组上使用[]时,概率数组就会以这种方式改变:
      1. 访问的位置设置为零(不包含一个)
      2. 条目变为其邻居的总和乘以该邻居跳转到条目位置的概率。 (prob_array_next_it [i] = prob_array_last_it [i-1] * prob_jump_to_right + prob_array_last_it [i + 1] * prob_jump_to_left + prob_array_last_it [i] * prob_dont_jump,i = 0且i = size = 1当然不同)
      3. 概率数组被归一化(将一个条目设置为零,将概率之和设置为低于1)
    3. 算法以最高概率访问该字段(在具有最佳概率的字段中选择)
    4. 它可能能够通过控制概率流来优化这一点,但这需要基于游荡事件,可能需要一些研究。

      尝试解决此问题的算法不会在一段时间后终止。对于复杂性,我们将分析平均情况。

      实施例: 跳跃概率为1/3,如果试图跳出界限则没有任何反应

      初​​始化:

      • 隐藏数组:0 0 1 0 0 0 0 0
      • 概率阵列:1/8 1/8 1/8 1/8 1/8 1/8 1/8 1/8

      第一次迭代:尝试[0] - &gt;失败

      • 隐藏数组:0 0 1 0 0 0 0 0(无跳转)
      • 概率数组步骤1:0 1/8 1/8 1/8 1/8 1/8 1/8 1/8
      • 概率数组步骤2:1/24 2/24 1/8 1/8 1/8 1/8 1/8 1/8
      • 概率数组步骤2:相同的标准化(整数组* 8/7):
      • 1/21 2/21 1/7 1/7 1/7 1/7 1/7 1/7

      第二次迭代:尝试[2],因为1/7是最大值,这是第一个具有1/7 - >的字段。成功(示例现​​在应该很清楚,当然这可能不会在另一个例子上如此快速地工作,没有兴趣在很多迭代中这样做,因为手动计算的概率很麻烦,需要实现它。如果那个跳到左边,我们就不会这么快检查它,即使它在那里停留了一段时间)