C#使用递归查找数组中数字的索引

时间:2017-04-27 14:16:47

标签: c# arrays recursion

所以在编程课程中,我正在学习递归。我得到了一个编写递归函数的赋值,该函数获取排序数组和数字,如果存在则返回数组中该数字的索引。

我还不太了解递归的主题所以我需要一点帮助我的代码。我认为我正朝着正确的方向前进,但我再次对这个问题感到挣扎,所以我觉得我可以在这里找到指导和帮助。

这是我目前的代码:

private static int arrayIndexValue(int[] arr, int ind)
{
    if (ind > arr.Length/2)
    {
        return arrayIndexValue(arr.Length/2, ind)
    }
    else if (ind < arr.Length/2)
    {
        return arrayIndexValue(arr.Length/2)
    }
}

基本上我想在这里写的是这样的:

如果用户插入的数字小于数组的中间部分,则继续使用该函数,但将数组切成两半(二进制搜索)

相同如果数字更大(我建议使用我的函数与二进制搜索,但你可以看到我不知道如何将它应用于我的代码)

3 个答案:

答案 0 :(得分:2)

递归的工作原理是将整个问题分解为更小的部分。如果您处于最小的部分(意味着您的数组只有一个值),那么您将获得解决方案。这也是你必须处理的第一个案例。

if (arr.Length == 1) return arr[0];

现在你可以开始解决这个问题了。二进制左或右决定。正如您已经写过的那样,您想要检查天气,数字是从数组中间向左或向右的。因此,在您的情况下,您需要使用[ ]运算符访问数组中的元素:

if (ind > arr[arr.Length / 2]) // check if larger than the middle element

要提取阵列的一部分,您需要第二个阵列,您可以在其中复制所需的内容。由于您打算只将当前数组的一半传递给递归调用,因此您只需要一半的大小。

int [] temp = new int[arr.Length / 2];

现在您可以根据您的情况复制您想要的部分(第一个或第二个),并继续使用递归调用进行搜索。

要复制数组,您可以使用Arra.Copy方法。您可以将开始和长度传递给此方法,它会将左侧或右侧部分复制到int [] temp数组中。以下是如何复制正确部分的示例:

Array.Copy(arr, arr.Length / 2, temp, 0, arr.Length / 2);

最后,您需要触发递归调用。此调用将期望新数组和仍然相同的数字。因此,既然您复制了前一个数组的左半部分或右半部分,现在将新的短数组传递给递归调用:

return arrayIndexValue(temp, ind);

你有它吗

答案 1 :(得分:1)

  

我得到了一个编写递归函数的赋值,它获取了排序数组   和一个数字,并返回数组中该数字的索引if   存在。

在您的方法中,您检查索引而不是值 - 您应该比较元素的值,而不是索引。

要编写递归函数来查找元素,您应该传递数组,元素要查找,启动索引和结束索引。开始索引和结束索引将用于查找数组的一部分。

您的方法将是这样的:

private static int GetIndex(int[] arr, int element, int startIndex, int endIndex)
{
    if (startIndex > endIndex)
    {
        return -1; //not found
    }

    var middleIndex = (startIndex + endIndex) / 2;

    if (element == arr[middleIndex])
    {
        return middleIndex;
    }

    if (element < arr[middleIndex])
    {
        return GetIndex(arr, element, startIndex, middleIndex - 1);
    }
    else
    {
        return GetIndex(arr, element, middleIndex + 1, endIndex);
    }
}

并得到一些索引:

static void Main(String[] args)
{
    var arr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    var element = 5;
    var index = GetIndex(arr, element , 0, arr.Length - 1);
}

答案 2 :(得分:1)

所以你现在遇到的问题是你没有将问题分解为重复步骤。它实际上应该是非常类似于没有所有变量的循环流。我想先做一些简单的事情。

void int find(int[] values, int at, int value) {
    while (values.Length < at && at >= 0) {
        if (values[at] == value) {
            return at;
        }
        at = at + 1;
    }
    return -1;
}

这个函数每次只通过递归将一个索引向上移动一个,但我们也可以用循环做一些非常相似的事情。

void int find(int[] sortedValues, int start, int end, int value) {
    var midIndex = (start + end) / 2;
    var mid = sortedValues[midIndex];
    if (start == end) {
        return mid == value ? midIndex : -1;
    } else if (mid > value) {
        return find(sortedValues, mid, end, value);
    } else if (mid < value) {
        return find(sortedValues, start, mid, value);
    } else {
        return midIndex;
    }
}

我们通常谈论递归的全部原因是它通常被使用,因此你没有&#34;变异&#34;州。每个值的变量和值都相同。你可以打破这个,但通常被认为是有益的。快速查看您的问题会产生类似

的内容
GHCi, version 7.10.2: http://www.haskell.org/ghc/  :? for help
Prelude> :t "#"
"#" :: [Char]

但是,这并不完美。它已经知道像边缘情况会导致崩溃的问题。绝对应该清理一下。如果你真的想要将你的脚趾浸入递归中,试试一种纯粹的功能性语言,你不能改变它,比如Haskell,Elm,或者像F#,Clojure或Scala那样有些不纯洁的东西。无论如何都很有趣。