【问题标题】:Find steps to find given value of index查找查找给定索引值的步骤
【发布时间】:2015-11-24 17:56:37
【问题描述】:

我是 SO 的新手 - 我有一个问题,我在面试中被问到,我一生都无法解决这个问题。我可以用 while/for 循环解决它,但面试官特别要求不要使用它们,我什至和我的几个朋友讨论过但无法解决。如果有人可以提供指点。

问题是: 对于给定的数组

s[] = {5,1,0,4,2,3}
  1. 未给出数组长度。
  2. 如果数组长度为 5 内容 保证在 0 到 5 之间。
  3. 没有重复 数字。

示例示例长度(s, 3) - a[3] = 4 , a[4] = 2, a[2] = 0, a[0] = 5, a[5] =3 返回长度 4 。

对于给定条件写子程序int length(s, 3) - 找出找到给定值所需的步数 -

附加条件

  1. 您不能使用任何循环语句,例如 for、while 等 -
  2. 您不能使用任何全局或静态变量。
  3. 您不能在该例程中调用其他例程
  4. 您不能修改给定的函数参数 - 它仅保持长度 (s, n)
  5. 您也不能更改原始数组

【问题讨论】:

  • 你考虑过递归吗?
  • 确实 - 但在增加价值方面陷入困境 - 我相信我需要在这里无法使用的全局价值
  • 3.你不能在这个例程中调用其他例程所以函数可以调用自己?
  • @this 是的 - 当我尝试他不反对这种方法时
  • 涉及此类谜题的编码面试与谜题本身无关。要么是关于你接近毫无意义的障碍的方式,要么是关于承认提出它的人脸上沾沾自喜的笑容。

标签: c arrays algorithm


【解决方案1】:

完全不修改数组,但在 x 的前 16 位内隐藏一个额外参数的替代解决方案:

int length(int *s, int x){
    int start = (x >> 16) - 1;
    if (start < 0)
        start = x;
    if (s[x] == start)
       return 0;
    return 1 + length(s, ((start + 1) << 16) + s[x]);   
}

如果数组中的元素太多,这将失败,但我怀疑任何其他递归解决方案在任何情况下都可能在那时遇到堆栈溢出。

【讨论】:

  • 这个方案修改了s
【解决方案2】:

我想我最终找到了答案,不,我没有破解它,但在网上找到了它:) .. 这是解决方案

int length(int * s, int x){
    if(s[x] < 0){
        return -1;
    }
    else{
        s[x] = -s[x];
        int len = length(s, -s[x]);
        s[x] = -s[x];
        return len + 1;
    }
}

【讨论】:

  • 那么约束 5 的实际意思是“数组的最终内容必须等于数组的初始内容”而不是“你不能写入原始数组”吗?
  • 给我的 API 是 --> int length(int * s, int x) - 它没有与之关联的常量,所以我认为我们可以修改数组,只要它完好无损- 再次,我不知道我无法在面试中解决 :) .. 只是我找到了一个解决方案,所以发布了解决方案。如果添加不写入原始数组的条件,b@PeterdeRivaz 解决方案会更正确 - 上述解决方案再次没有修改它.. 但彼得的解决方案再次会更优雅
  • 此解决方案违反了第 5 个约束。数组已更改或修改。约束的正确表述应该是:在函数调用之后,数组必须保留相同的值。
  • 似乎违反了关于修改s的约束。
【解决方案3】:

我认为这与您的任何条件都不矛盾。我只是没有使用数组作为参数(其实这不是问题,你可以自己修改)

int s[] = {5,1,0,4,2,3};
bool col[100]; ///to check cycle

int rec(int n)
{
    if(col[n])return 0;
    col[n]=true;
    int sum=0;
    sum = 1+rec(s[n]);
    return sum;
}

【讨论】:

  • 2.您不能使用任何全局或静态变量。
  • 您的意思是col 数组吗? @这个
  • 我说你不​​能使用全局或静态变量。您正在使用 col 和 s 作为全局变量。
【解决方案4】:

面试官正在探究你对算法和编程范式的理解,试图了解你的培训、背景和深度。面试官有一个具有挑战性的任务;用最少的证据识别有能力的开发人员。 因此,面试官提出了一个构造问题,(他们希望) 引出所需的知识(候选人 X 是否知道如何解决问题 Y,或者理解概念 Z) 可能是因为面试官认为期望的答案表明候选人知道预期的知识体系。

现代语言提供了几种重复结构(命令、语句),一些是预测试的(在进入语句块之前检查条件),还有一些是后测试的(在执行语句块至少一次后检查条件)。以下是示例,

预测试

while(condition) statement-block
for(initializer;condition;step) statement-block

后测

do statement-block while(condition)
repeat statement-block until(condition)
do statement-block until(condition)

这些都可以写成带有分支(goto)的条件(选择)结构,

预测试

label:
if(condition)
    statement-block;
    goto label;
else
    nil;
endif

后测

label:
statement-block;
if(condition)
    goto label;
endif

您还可以使用递归,只要条件成立(或直到满足条件,取决于正逻辑或负逻辑),您就调用相同的函数,

预测试

function recurse(args)
    if(condition)
        statement-block
        recurse(revised args);
    endif
    return
end #function

后测

function recurse(args)
    statement-block
    if(condition)
        recurse(revised args);
    endif
    return;
end

您将在算法或可计算性课程中学习递归。您将了解编译器、高性能计算或系统类中的条件分支。您的编译器课程可能会检查检测“尾递归”的技术,以及如何将函数调用重写为循环。

这就是问题所在,重申一下,

given array, s[] = {5,1,0,4,2,3}
array length unknown
content between [0 .. length], not repeated, no duplicates
write subroutine which provides the number of steps to find given value

也就是说,

int length( array s, int member ) --> position

检查问题的条件(约束),

  • 数组长度未知 - 解决方案必须适用于可变范围的输入
  • 不能使用循环语句(for、while 等) - 这表明面试官想要条件分支或递归。
  • 不能使用全局或静态变量 - 这是否表明面试官需要递归/函数式编程解决方案?条件分支也提供了这个。
  • 不能在该例程中调用其他例程 - 面试官是指同一函数以外的函数,还是调用任何函数(面试官所说的“其他”是什么意思)。
  • 无法修改函数参数,保持长度(s,n) - 允许声明本地(堆栈)变量。这可能意味着按值传递、制作本地副本等。但不是破坏性修改。
  • 无法更改原始数组 - 绝对没有破坏性修改。可能的“提示”(可以制作本地副本吗?),或者进一步表明您应该使用条件分支?

这里有两个解决方案和一个测试驱动程序(注意,我将它们命名为 longi,iterative 和 lengthr,recursive)。

#include <stdio.h>

/* conditional branch */
int lengthi( int s[], int member )
{
    int position=0;
    AGAIN:
    if( s[position] == member ) return(position);
    ++position;
    goto AGAIN;
    return(-1);
}

/* recursive */
int lengthr( int s[], int member )
{
    if( s[0] == member ) return(0);
    return( 1+length(s+1,member) );
}

int
main(int argc,char* argv[])
{
    int s1[] = {0,1,2,3,4,5,6,7,8,9};
    int s2[] = {1,2,3,4,9,8,7,6,0,5};
    int s3[] = {2,4,6,8,0,1,3,5,7,9};

    printf("%d at %d\n",3,lengthr(s1,3));
    printf("%d at %d\n",3,lengthr(s2,3));
    printf("%d at %d\n",3,lengthr(s3,3));
    printf("%d at %d\n",3,lengthi(s1,3));
    printf("%d at %d\n",3,lengthi(s2,3));
    printf("%d at %d\n",3,lengthi(s3,3));
}

由于我们应该找到步骤数(迭代、函数调用),因此要求的是列表中的序数位置,而不是 C 索引(从零开始)的位置。

这是一个面试问题,而不是编程问题(本身),因此可能更适合Programmers.stackexchange 网站。 我可能会给面试官一个有趣的答案,或者他们想要的答案。

【讨论】:

  • 请注意,这里回答了一个非常相似的问题:programmers.stackexchange.com/questions/303242/…
  • 哦,我拼错了 AGAIN(goto 目标),但是,嘿,我从不使用 goto。请运行我添加的测试,您会看到这些函数确实返回了正确的步数。
  • @ChuckCottrill - 感谢您的详细回答 - 我会牢记这些要点 - 感激不尽!!!
  • 你完全误解了这个问题。我建议尝试查看其他答案和提供的示例 OP。
猜你喜欢
  • 2021-05-31
  • 2012-12-10
  • 2014-09-20
  • 2011-07-04
  • 2019-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多