【问题标题】:Recursively split a LinkedList in Java into odd and even lists递归地将Java中的LinkedList拆分为奇数和偶数列表
【发布时间】:2021-03-11 18:20:23
【问题描述】:

我正在尝试解决一个问题,其中给我一个带有数据整数的 LinkedList,我的任务是将列表拆分为两个单独的列表,一个具有所有偶数位置,一个具有所有奇数位置。

输入:0 1 2 3 0 -4 -5

ListNode 类:

public class ListNode
{
    public int data;
    public ListNode next;

    public ListNode(int _data)
    {
        data = _data;
        next = null;
    }
}

驱动方法:

    public static void main(String [] args) {
        MyList L = new MyList();
        ListNode head = L.getHead();        // Get the head node of the linked list.
        System.out.print("INPUT: ");
        print(head);
        ListNode [] R = split(head);        // Split into two list. The first list contains all elements in odd positions, the second contains all elements at even positions.
        System.out.println("Printing the list with odd positions");
        print(R[0]);
        System.out.println("Printing the list with even positions");
        print(R[1]);
    }

我正在努力想办法做到这一点,我没有得到任何帮助方法来添加节点,这是我尝试过但无法正常工作的方法。

private static ListNode[] split(ListNode L)
    {
        ListNode[] ret = new ListNode[2];
        
        for (ListNode cur = L; cur != null; cur = cur.next)
        {
            if ((cur.data % 2) == 0)
            {
                ret[1] = cur;
                ret[1].data = cur.data;
                System.out.print("CURRENT EVEN LIST IS ");
                print(ret[1]);
            }
            else
            {
                ret[0] = cur;
                ret[0].data = cur.data;
                System.out.print("CURRENT ODD LIST IS ");
                print(ret[0]);
            }
        }
        return ret;
    }

这是我得到的输出:

INPUT: 0 1 2 3 0 -4 -5 
CURRENT EVEN LIST IS 0 1 2 3 0 -4 -5 
CURRENT ODD LIST IS 1 2 3 0 -4 -5 
CURRENT EVEN LIST IS 2 3 0 -4 -5 
CURRENT ODD LIST IS 3 0 -4 -5 
CURRENT EVEN LIST IS 0 -4 -5 
CURRENT EVEN LIST IS -4 -5 
CURRENT ODD LIST IS -5 
Printing the list with odd positions
-5 
Printing the list with even positions
-4 -5 

我希望有人能带领我走上正确的道路,我知道我的尝试是错误的,因为它总是复制整个列表,但我知道我错过了一些东西。有递归方法吗?

谢谢

【问题讨论】:

  • 你想要递归,但你展示的方法是迭代的
  • 是的,我正在寻找一个正确方向的观点,说明如何递归地处理这个问题,或者如果可能的话,帮助纠正我的迭代方法。

标签: java data-structures linked-list nodes


【解决方案1】:

在单链表中,头节点隐含地表示整个链表,第二个节点表示自身和链表的其余部分。

当你这样做 ret[1] = cur; 当 cur 是头节点时,你只是将该索引设置为整个列表,并且在 for 循环的下一次迭代中,当 cur 是第二个节点 ret[1] = cur; 将设置 ret[1 ] 到整个列表减去前一个节点。

您需要更改原始列表中的连接。试着画出来。

原来的列表有这样的联系:

(0) -> (1) -> (2) -> (3) -> (0) -> (-4) -> (-5)

你想要这个:

(0) -> (2) -> (0) -> (-5)

(1) -> (3) -> (-4)

设置连接/链接将通过节点定义中的下一个字段来完成。您将不得不断开连接并设置新的连接。

例如,第一个 (0) 的下一个字段将是 (1) 的原始下一个字段,代码如下:cur.next = cur.next.next;

【讨论】:

  • 我认为您的子列表的最后一个元素混淆了。
  • 假设 0 1 2 3 0 -4 -5 是输入,我所描述的不正确吗?因为偶数位置是 0,2,4,6,奇数位置是 1,3,5。
  • 对不起,你可能是对的。我将其解释为偶数,而不是偶数。但是条件cur.data % 2 表示数据,但没有预期的输出谁知道。
  • 我也对此感到困惑,但最终注意到他的驱动方法中有一条评论。但是,是的,您是正确的,他在 if 语句中的表达确实表明了这一点。尽管如此,预期的输出绝对可以解决混乱。
【解决方案2】:

这是一个递归实现。

    private void split(Predicate<Integer> p, ListNode n, Pair<ListNode> pair) {
        if (null == n) {
            return;
        }

        if (p.test(n.data)) {
            pair.left = pair.left.next = n;
        } else {
            pair.right = pair.right.next = n;
        }

        ListNode nn = n.next;
        n.next = null;
        split(p, nn, pair);
    }

递归运行也需要携带拆分列表。我使用了Pair 而不是数组,这只是

static class Pair<T> {
    T left, right;

    public Pair(T left, T right) {
        this.left = left;
        this.right = right;
    }
}

要开始递归拆分,您需要使用虚拟根对象创建Pair,以便您可以在递归步骤中消除对第一个条目的空检查。完成后,只需剥离标题并返回其余部分

    Pair<ListNode> split(Predicate<Integer> p) {
        ListNode leftRoot = new ListNode(0);
        ListNode rightRoot = new ListNode(0);
        Pair<ListNode> pair = new Pair<>(leftRoot, rightRoot);
        split(p, this, pair);
        return new Pair<>(leftRoot.next, rightRoot.next);
    }

只需使用正确的谓词调用条目拆分

    int[] input = {0, 1, 2, 3, 0, -4, -5};
    ListNode ln = ... // initialize for the input

    Predicate<Integer> even = i -> i % 2 == 0;
    Pair<ListNode> split = ln.split(even);
    System.out.println(split.left);
    System.out.println(split.right);

如果你编写了一个toString() 方法来获取格式良好的内容

例如,用这个

    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(data).append(" -> ");
        ListNode n = this;
        while (null != (n = n.next)) {
            sb.append(n.data).append(" -> ");
        }
        return sb.toString();
    }

你会得到输出:

0 -> 2 -> 0 -> -4 -> 
1 -> 3 -> -5 -> 

【讨论】:

    猜你喜欢
    • 2021-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-09
    • 2011-12-18
    • 1970-01-01
    相关资源
    最近更新 更多