【问题标题】:Minimum number of jumps to reach end of the array with sequence using recursion使用递归的序列到达数组末尾的最小跳转次数
【发布时间】:2020-04-07 16:20:42
【问题描述】:

我有一个代码“使用递归到达数组末尾的最小跳转次数”。 但我无法打印序列。(向量 vec 中没有可打印的内容)
任何帮助将不胜感激。

说明:
我想从第一个元素(即 2)到达 最小跳跃中数组的最后一个元素(即 4)。
跳跃将如何:
第一个元素是 2。这意味着我最多可以在数组中进行 2 次跳转。如果我进行第一次跳跃,那么我可以达到第二个元素(即 3),或者如果我参加 第二次跳跃然后我可以到达第三个元素(即 1)
第二个元素是 3 ,所以我最多可以跳 3 次。第 1 跳我可以达到 1 ,第 2 跳我可以达到 0 ,第 3 跳我可以 达到 4
通过这种方式,我想以最少的跳跃次数从数组的第一个元素到达最后一个元素。
所以输出会像,从第一个元素 2,我会跳到 3。然后从 3 我会跳到 4(最后一个元素)。所以 2 跳。 ( 2 - 3 - 4 )

#include<iostream>
#include<vector>
#include<climits>
using namespace std;

int jump(int arr[], int n, int start, vector<int> &vec)
{
    if(start == n-1)  // if start is the last element in array
       return 0;

    if( arr[start] == 0)  // if array element is 0 
       return 0;

    vector<int> vec1 = vec;
    vector<int> vec2 = vec;

    int minimum = INT_MAX;
    for( int i = 1 ; i <= arr[start]; i++ )
    {
        vec1.push_back(start);

        int _jump = 1 + jump( arr, n, start+i, vec1); // considering every jump 

        vec = (_jump < minimum) ? vec1 : vec2;

        minimum = min(minimum, _jump);
    }
        return minimum;

}

int main()
{
    int arr[] = { 2, 3, 1, 0, 4 };
    int n = sizeof(arr) / sizeof(arr[0]);

    vector<int> vec;
    cout << "Number of jumps " << jump(arr, n, 0, vec) << endl;
    cout<<"Sequence is "<<endl;
    for( auto x : vec)
        cout << x <<" ";  
    return 0;
}          

输出

Number of jumps 2      
Sequence is      

预期输出

 Number of jumps 2       
 Sequence is 2 3 4

【问题讨论】:

  • 您能解释一下您要解决的算法问题吗?它可能对我们有帮助。还提供完整的代码,以便我们能够执行它。最后,您得到的输出是什么,您是否尝试过调试?
  • jump中,每次你选择不调整minimum,你仍然丢弃了累积的跳转列表,通过vec = vec2;
  • 我认为这个问题需要您进行更多的调试工作才能为 SO 做好准备。尝试简化情况。例如,当前示例使用 10 元素数组。你能用 9 个元素证明这个问题吗? 8?你能做到多短?缩短输入后,调试jump。在每次循环迭代结束时检查vecvec1vec2 的值(不要忘记考虑递归)。根据您的算法,这些值是您所期望的吗?你能缩小问题的范围吗?
  • @Yonlif 我试图解释这个问题。我尝试调试,发现我的向量 vec 大小为 0。我推入向量 vec,但大小仍然为 0。
  • @JaMiT 我已经缩小了问题的范围。我尝试调试,但向量 vec.size() 为 0。这就是为什么在输出中第二行没有显示任何内容。

标签: c++ algorithm c++11 c++14 dynamic-programming


【解决方案1】:

这是一个示例,它将设置一个向量,其中每个索引在访问该索引后存储序列中正确的下一步。我让您使用结果向量按照从第一个元素到最后的顺序进行编码。我还纠正了这个条件if( arr[start] == 0) 以返回“无穷大”,因为如果我们访问这个元素,我们就无法完成序列。

#include<iostream>
#include<vector>
#include<climits>
using namespace std;

int jump(int arr[], int n, int start, vector<int> &vec)
{
    if(start == n-1)  // if start is the last element in array
       return 0;

    if( arr[start] == 0)  // if array element is 0 
       return INT_MAX - n;

    int minimum = INT_MAX;
    int step;
    for( int i = 1 ; i <= arr[start]; i++ )
    {
        int _jump = 1 + jump( arr, n, start+i, vec); // considering every jump 

        if (_jump < minimum){
          minimum = _jump;
          step = start + i;
        }
    }

    vec.at(start) = step;

    return minimum;
}

int main()
{
    int arr[] = { 2, 3, 1, 0, 4 };
    int n = sizeof(arr) / sizeof(arr[0]);

    vector<int> vec(n, -1);
    cout << "Number of jumps " << jump(arr, n, 0, vec) << endl;
    cout<<"Vector: "<<endl;
    for( auto x : vec)
        cout << x <<" ";  
    return 0;
}

【讨论】:

  • 虽然您发现了一些问题,但您的代码输出为1 4 3 -1 -1。可能性。索引应该是0, 1, 4,因此一开始就漏掉了一个,最后漏掉了一个。此外,似乎应该在索引中显示值。顺便说一句,step 并未在所有路径上初始化。
  • @Phil1970 不,1 4 3 -1 -1 是正确的。正如我在回答中所描述的,向量中的每个值都代表我们从存储值的索引跳转到的下一个索引。在这种情况下,我们从向量的索引 0 开始,这告诉我们下一个索引是 1,我们找到 4,这是序列的结尾。
  • @Phil1970 正如您所建议的那样,可能存在一些未处理的边缘场景,我将留给读者修复。
  • (1)看问题中的预期输出(2) 3 在你的序列中代表什么?
  • @Phil1970 你的批评是不恰当的。我提出了一种让 OP 存储序列的方法。我还建议 OP 由他们决定使用此方法来输出此序列在完整解决方案中需要采用的任何形式。
【解决方案2】:

本质上,这是使示例数据正常工作的最小修复。我没有检查所有边缘情况。例如,您可能想要打印除 INT_MAX 的值之外的其他内容,即 end is not reachable。

问题 1

您想要输出值(即示例中的 2、3、4)而不是索引(0、1、4)。因此,您必须推送值而不是索引。

vec1.push_back(arr[start]);

问题 2

if(start == n-1)  // if start is the last element in array
   return 0;

这不会在到达末尾时添加最终值。您必须添加最后一个值:

vec.push_back(arr[start]);

问题 3

if( arr[start] == 0)  // if array element is 0 
   return 0;

一个没有到达终点的序列,将被认为是非常好的。您应该返回一个很大的值。由于 _jump 是 1 + jump 的返回值,因此返回值应该是 INT_MAX - 1 并且出于同样的原因,最小值也应该初始化为该值。

或者,您也可以返回其他值,例如 n

问题 4

最后,以下条件不正确:

vec = (_jump < minimum) ? vec1 : vec2;

条件不成立时,由于循环使用vect1,所以需要将vect2复制到vec1中。

【讨论】:

  • 我了解您提到的第 3 个问题。我犯了一个错误。但我无法理解最后一个。我试过你说的,但输出没有改变。你能帮我理解吗?我应该执行哪些更改?
  • 循环使用vec1,它应该是每次迭代时的原始值。因此,当条件未验证(未找到最小值)时,需要将 vec1 重置为其原始状态(即复制到 vec2 中。因此,您需要类似 if (_jump &lt; minimum) vec = vec1; else vec1 = vec2; 的内容。这将获得预期输出。
猜你喜欢
  • 1970-01-01
  • 2021-10-13
  • 2015-03-07
  • 2020-07-29
  • 2020-11-25
  • 1970-01-01
  • 1970-01-01
  • 2019-01-08
  • 2011-08-01
相关资源
最近更新 更多