问题描述
我正在尝试解决一个问题,我得到一个包含数据整数的 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 ->