我正在尝试将节点列表拆分为两个,并将两个链接列表合并回一个列表中。例如,{"KH","4C","8C","QC","3D","7D","JD"}
变为{"KH","4C","8C","QC"}
{"3D","7D","JD"}
(如果在这种情况下,列表具有奇数个节点,则第一个列表更长)并返回列表{"KH","3D","4C","7D","8C","JD","QC"}
。看看我的错误,似乎我没有在if语句中正确地合并列表。
我必须使用提供的节点类,不能使用静态变量,数组或Java集合。你能解释我应该如何将我的两个节点列表合并在一起吗?
我的代码
public class ListShuffleExample {
public static Node<String> shuffle(Node<String> deck) {
if(deck == null){
return null;
}
int decklength = length(deck);
if(decklength % 2 == 0){
Node<String> first = deck;
Node<String> second = deck;
int halflength = decklength / 2;
int i;
for(i = 0; i < halflength; i++){
second = second.next;
}
while(second.next != null){
first.next = second;
second = second.next;
}
return first;
}
else{
Node<String> first = deck;
Node<String> second = deck;
int halflength = (decklength / 2) + 1;
int i;
for(i = 0; i < halflength; i++){
second = second.next;
}
while(second.next != null){
first.next = second;
second = second.next;
}
return first;
}
}
public static int length(Node<String> adeck){
int length = 0;
while(adeck.next != null){
length++;
adeck = adeck.next;
}
return length;
}
}
节点类
public final class Node<T> {
public final T value;
public Node<T> next;
public Node(T _value) {
this( _value, null );
}
public Node(T _value, Node<T> _next) {
value = _value;
next = _next;
}
@Override
public String toString() {
return "" + value;
}
}
我的测试用例
@Test
public void testMany() {
@SuppressWarnings("unchecked")
Node<String> input = makeList( _AH, _5H, _9H, _KH, _4C, _8C, _QC, _3D, _7D, _JD, _2S, _6S, _TS );
Node<String> actual = ListShuffleExample.shuffle( input );
// _AH, _5H, _9H, _KH, _4C, _8C, _QC
// _3D, _7D, _JD, _2S, _6S, _TS
for (Object expected : new Object[]{ _AH, _3D, _5H, _7D, _9H, _JD, _KH, _2S, _4C, _6S, _8C, _TS, _QC }) {
assertEquals( "Incorrect value", expected, actual );
actual = actual.next;
}
assertNull( "Incorrect result", actual );
}
答案 0 :(得分:0)
根据我的理解,你并没有真正改变,但是你将两个列表交织在一起。因此,当你到达卡片组并将它们连接到一个卡座中时,就像它们从每个卡座中交替一样。
您的代码中存在问题:
while(second.next != null){
first.next = second;
second = second.next;
}
您永远不会更新first
引用以移动到下一个节点,并且您永远不会更新second
引用以指向第一个之后的引用。您总是会覆盖相同的first.next
。
怎么样:
Node<String> curFirst = first;
Node<String> curSecond = second;
while(curFirst != null && curSecond != null)
{
//save the next one of the first list
Node<String> nextFirst = curFirst.next;
//set the next one of the first list to the first one of the second list
curFirst.next = curSecond;
//save the next one of the second list
Node<String> nextSecond = curSecond.next;
//set the next one after the inserted item to the previous next of the first list
curSecond.next = nextFirst;
//set the current references to the next ones
curFirst = nextFirst;
curSecond = nextSecond;
}
//once any of the pointers becomes null it means we're done because the rest of the list should be still intact
当列表为空,或者列表中只有1个项目等时,您可能需要检查一些极端情况,但我留给您!
更新以下评论后
长度计算也是错误的,如果列表为空(例如NullPointerException
为aDeck
),它将抛出null
,如果它包含任何项目,将返回少一项。您应该将条件更改为while(adeck != null)
。
此外,没有重复的代码。将您正在遍历的部分移动到halflength
并将其合并到else之后。当长度均匀或奇数时,它都是相同的。