【问题标题】:Java recursively print array in reverseJava反向递归打印数组
【发布时间】:2011-09-28 05:14:09
【问题描述】:

数组是一个字符串数组。数组为{"hello", "how", "are", "you", "?"}

它有点工作,但输出混合了最后两个元素,当我运行我的程序时,输出为you ? are how hello,它应该是? you are how hello

我输入了一个打印语句来查看我的左右是什么以及它们是否切换,但这并没有帮助,因为它们只打印了起始值而没有其他任何内容。

为什么打印错误?不是在做递归吗?

这是我的方法。必须分而治之。

public void outrev() {
    outrev(0, a.length - 1);
}

private void outrev(int left, int right) {
    System.out.println("left a[" + left + "] is " + a[left]);
    System.out.println("right a[" + right + "] is " + a[right]);
    int mid;
    if (left > right) {
        //do nothing
    }
    else if (left == right) {
        System.out.print(a[left]);
    }
    else {
        mid = (left + right) / 2;
        outm(mid + 1, right);
        System.out.print(a[mid] + " ");
        outm(left, mid - 1);
    }
}

【问题讨论】:

  • 首先,递归在哪里?还有,outm的定义是什么?
  • recusion 是两个 outm( ) 的,对吧? outm 的定义是什么意思?
  • 按定义,我的意思是outm的函数/方法定义是什么?不应该是outrev吗?
  • 正如@Sandeep 所说,递归伙伴在哪里。outm() 是什么
  • @alexthefourth 如果将outm 替换为outrev,那么我认为这段代码是正确的。请在获取输出时remark前两个 println 语句。否则程序会给出正确的输出。

标签: java arrays string recursion


【解决方案1】:
public void outrev()
{ 
    List<String> arr = Arrays.asList(a);
    outrev(arr);
} 

private void outrev(List<String> arr)
{

    System.out.println(arr.get(arr.size() - 1));
    if(arr.size() != 1){
        outrev(arr.subList(0, arr.size() - 1));
    }
}

你必须导入

导入 java.util.Arrays; 导入 java.util.List;

不知道这是否违反了你的家庭作业规则。注意 outrev 调用自己,但一旦列表长度为一项就停止调用自己?那是递归的主要租户,即一个调用自身并具有终止条件的函数。在您的原始代码中, outrev 并没有真正调用自己;但是,在一种情况下,您正在重载 outrev,但这与递归不同——除非您未定义的 outm 旨在调用 outrev。

您还应该让此程序检查以确保列表不为空,因为您的老师可能会将其扔给您,并且在这种情况下代码会失败。

请记住,对于递归,最好从以下方面考虑: 1)当我有零项时该怎么办。 2)当我有一件物品时该怎么办。 3)如何处理我的列表包含多个项目的所有其他情况。

【讨论】:

  • @Bringer128,有时最好的学习方式就是通过例子。非常感谢 -1。
  • 我并没有恶意,如果您更改答案,我很乐意删除反对票,这样他就不能只是将其复制粘贴到他的作业/课堂作业中。看看the tag wiki for the homework tag
  • 我明白,但我认为我们在这里只是存在哲学差异。 OP正在努力解决问题,但遇到了很多麻烦。我觉得向他展示如何解决问题是最好的教学方式。即使他逐字复制答案,当材料出现在考试中时,他也有责任理解事物。检查元堆栈;与您向我展示的那个wiki页面相反,有很多关于硬件问题的讨论。如果你真的想用你的代表来拖累我,因为我试图提供合法的帮助,那是你的特权
  • 很公平。不幸的是,除非编辑答案(StackOverflow 不允许我),否则我无法删除反对票。
【解决方案2】:

您对递归“分而治之”算法有正确的想法。基本思想是以下动作:

  1. 将数组一分为二:
  2. 递归打印右半部分
  3. 递归打印左半边

打印“中间”会让自己变得困难。相反,您应该仅在达到终止条件时才进行打印,也就是说,当您只有 1 个元素而无法将数组分成两半时。

此外,您的代码包含方法 outrev()outrev(int left, int right) 的定义,但没有定义 outm(int left, int right),因此您发布的代码无法编译。

【讨论】:

  • outm 是另一种方法,感谢您指出我没有注意到我调用了错误的方法。当你说打印右半边和左半边时,这就像一个 [left] 的打印语句和一个 [right] 的打印语句吗?
  • @alex 我的意思是你应该调用你的递归打印函数outrev 与左右两半的边界。我会更新我的答案以更清楚。
  • afaik 分而治之是一种算法范式,它通过将问题分解为较小的子问题然后组合结果来解决问题,我不知道如何将其应用于反向打印数组任何情况都需要 O(n) 时间。
  • @ChingPing 我的回答中的“基本想法”部分展示了您如何做到这一点。我同意分而治之对手头的任务没有多大意义,但它是一个足够简单的例子来演示分而治之的递归。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-02
  • 2021-11-30
  • 2014-11-27
  • 1970-01-01
  • 1970-01-01
  • 2021-06-06
  • 2014-01-12
相关资源
最近更新 更多