【问题标题】:Remove node from linked list recursively递归地从链表中删除节点
【发布时间】:2016-07-19 05:35:21
【问题描述】:

给定链表的头部和作为参数搜索的 int,我需要一个方法来删除该数字在列表中的第一次出现,并返回修改后的列表。但是我无法修改原始列表。我知道如何从列表中删除节点,但我不确定如何保持原始列表完整,因为这必须递归完成。下面是方法 ** 最初 M 是原始列表。不知道再次调用该方法后还是一样的列表...?

MyList removeNumber(MyList m, int removee){

【问题讨论】:

  • 我是否正确假设参数“MyList m”是原始列表(即您不想更改的列表)?
  • 在递归时复制列表。
  • 是 m 是最初调用该方法时的原始列表。我不确定递归调用该方法后是否仍然如此。

标签: java recursion linked-list


【解决方案1】:

这个想法是生成的结构将是一个“Y”:一个双头列表(实际上是一个简单的图)。

Y 的一个分支是原始列表。另一个是您删除节点的新列表。 Y 的垂直柄是您删除的元素之后的内容。这两个列表都很常见。这是一些将 Y 翻转过来的 ascii 艺术作品,显示了 1 到 5 的列表,其中 3 被删除了。

     new -> 1 -> 2 ------\
                          v
original -> 1 -> 2 -> 3 -> 4 -> 5 -> null

递归思考就是根据自身的较小版本加上固定的工作量来定义问题。而且您需要一个基本案例(或者可能几个)。

链表本身就是一个递归结构:

列表要么是空的,要么是通过其“下一个”引用链接到列表的元素。

请注意,这使用较小的列表定义了一个列表。基本情况是空列表。固定位是元素。

阅读这个定义几次,然后看看它是如何翻译代码的:

class MyList {
  int value;    // the element at the head of this list
  MyList next;  // the rest of the list

  MyList(int value, MyList next) {
    this.value = value;
    this.next = next;
  }
}

基本情况“空列表”只是一个null 引用。使用相同模式递归表示的元素去除问题变为:

删除一个元素的列表的副本是 a) 如果要删除的元素是头部,则列表后面的其余部分是头部或 b) 当前节点的副本,然后是副本删除了所需元素的列表的其余部分。

在这里,我使用相同事物的较小版本来定义“删除了一个元素的列表副本”。情况 a) 是基本情况。当它不是removee时,固定位正在复制头部。

当然还有另一种基本情况:如果列表为空,则无法找到 removee。这是一个错误。

将其放入代码中:

MyList removeNumber(MyList m, int removee) {
  if (m == null) throw new RuntimeException("removee not found");
  if (m.value == removee) return m.next;
  return new MyList(m.value, removeNumber(m.next, removee));
}

使用函数看起来像这样:

MyList originalList = ... // list of 1 to 5.
MyList newListWith3removed = removeNumber(originalList, 3);

System.out.println("Original list:");
for (MyList p : originalList) System.out.println(p.value); 
System.out.println("With 3 removed:");
for (MyList p : newListWith3removed) System.out.println(p.value);

输出将与预期一样:第一个列表中为 1 到 5,第二个列表中为 1,2,4,5。 IE。第一个列表没有改变。

【讨论】:

    【解决方案2】:
    //This function will always return a new list with 'remove' removed
    MyList removeNumber(MyList m, int remove){
    //if m is empty List, return an empty list
    
    //if head is not the int to remove, return a New list from 
    //   head concat removeNumber(m.next,remove)
    //else return removeNumber(m.next,remove)
    }
    

    【讨论】:

      【解决方案3】:

      我认为它缺乏信息。但是,我假设链表的实现非常传统,例如:

      class MyList {
      
        MyList prev;
        MyList next;
        int data;
      
        static MyList removeNumber(MyList m,int removee) {
      
          if(m == null) return null; // already empty
      
          if(m.data == removee) { // m already is the node to throw away
      
            if(m.prev != null)// relink
              m.prev.next = m.next;
      
            if(m.next != null)// relink
              m.next.prev = m.prev;
      
            return m.prev;
          }
          // if this node isn't the one yet, keep looking for
          return removeNumber(m.next,removee); 
        }
      }
      

      有很多不同的方法可以做到这一点,但您必须提供更多信息才能让我们为您指出正确的文献。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-06
        • 1970-01-01
        • 2012-09-13
        • 2023-03-26
        • 2018-01-23
        • 2023-02-23
        • 1970-01-01
        相关资源
        最近更新 更多