微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

递归地将 Java 中的 LinkedList 拆分为奇数和偶数列表

如何解决递归地将 Java 中的 LinkedList 拆分为奇数和偶数列表

我正在尝试解决一个问题,我得到一个包含数据整数的 LinkedList,我的任务是将 List 分成两个单独的列表,一个是偶数位置,一个是奇数。

输入: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 

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

谢谢

解决方法

在单向链表中,头节点隐式表示整个列表,第二个节点表示它自己和列表的其余部分。

当你这样做 ret[1] = cur; 当 cur 是头节点时,你只是将该索引设置为整个列表,并且当 cur 是第二个节点时,在 for 循环的下一次迭代中 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;

,

这是一个递归实现。

    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,-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 -> 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。