Java 两个链接列表求和时,如何从余数中取1?
我声明了两个链表,其中包含一组表示完整整数的数字。对于这个例子,我使用的是Java 两个链接列表求和时,如何从余数中取1?,java,linked-list,Java,Linked List,我声明了两个链表,其中包含一组表示完整整数的数字。对于这个例子,我使用的是x=666和y=666,因为在这种情况下,它需要处理一个余数,并为每次迭代向下一个整数加1 整数将自动生成,并按相反顺序放入链表中。但是,这些链表可以是任意长度,具体取决于生成的整数。将两个列表相加时,如何处理进位和余数?我假设我们在列表中存储从最低有效位到最高有效位的数字。换言之,数字143将以列表形式表示为: [3] -> [4] -> [1] ^ ^ |
x=666
和y=666
,因为在这种情况下,它需要处理一个余数,并为每次迭代向下一个整数加1
整数将自动生成,并按相反顺序放入链表中。但是,这些链表可以是任意长度,具体取决于生成的整数。将两个列表相加时,如何处理进位和余数?我假设我们在列表中存储从最低有效位到最高有效位的数字。换言之,数字143将以列表形式表示为:
[3] -> [4] -> [1]
^ ^
| |
front back
在头部存储最重要的数字会降低添加的效率,因为需要额外的遍历来确定列表的长度
此代码中有几个问题需要解决:
while(xInter.hasNext()){//检查是否有数字
仅检查x
是否有数字,这仅在列表长度相同或x
较长时有效。相反,在xIt
或yIt
有数字时继续迭代,因为还有更多工作要做
result.add(rem)了,不要试图添加一个新的result元素;//将余数添加到结果列表中。
,我建议延迟添加余数,直到在下一次迭代中实际需要它。手工操作时,严格遵循算术方法的直觉似乎更容易
此外,llist1.set(pos++,xInter.next()+1);//将1添加到下一个int。
是一个棘手的问题,因为您已经向前推进了一个迭代器,而无法返回。逻辑变得混乱,下一步需要知道太多的状态。在任何步骤中,只从每个迭代器中删除一个元素,并且只向结果添加一个节点
pos
和carryBool
是不需要的,这会使代码更难理解
import java.util.*;
import static java.lang.System.out;
class Main {
public static LinkedList<Integer> add(
LinkedList<Integer> a, LinkedList<Integer> b
) {
LinkedList<Integer> result = new LinkedList<>();
Iterator<Integer> xIt = a.iterator();
Iterator<Integer> yIt = b.iterator();
int rem = 0;
while (xIt.hasNext() || yIt.hasNext()) {
int x = xIt.hasNext() ? xIt.next() : 0;
int y = yIt.hasNext() ? yIt.next() : 0;
result.add((x + y + rem) % 10);
rem = x + y + rem >= 10 ? 1 : 0;
}
if (rem > 0) {
result.add(rem);
}
return result;
}
public static void main(String[] args) {
int[][] tests = {
{143, 675},
{77666, 666},
{985, 824},
{9999, 1},
{1, 9999},
{667, 677},
};
for (int[] test : tests) {
LinkedList<Integer> a = itol(test[0]);
LinkedList<Integer> b = itol(test[1]);
LinkedList<Integer> sum = add(a, b);
int expected = test[0] + test[1];
out.println("a : " + a + "\n" + "b : " + b);
out.println("sum : " + sum);
out.println(test[0] + " + " + test[1] + " = " + ltoi(sum));
out.println("Correct? " + (ltoi(sum) == expected) + "\n");
}
}
private static LinkedList<Integer> itol(int i) {
LinkedList<Integer> res = new LinkedList<>();
for (; i > 0; i /= 10) res.offer(i % 10);
return res;
}
private static int ltoi(LinkedList<Integer> ll) {
String digits = "";
for (int i : ll) digits = i + digits;
return Integer.parseInt(digits);
}
}
感谢您的反馈。不过,关于您的第一点,我已经通过在较短的列表中添加0来处理不同的列表大小。因此
llist1=[1,2,3,4,5]
和llist2=[1,2,3]
然后llist2=[0,0,1,2,3]
。因此,在它们到达while循环之前,它们将始终具有相同数量的元素。这是可行的,但随后您对输入进行了变异,这可能是调用方所不期望的,并完成了大量额外的繁重工作。这种方法无需任何额外工作即可完成此任务(只需添加快速条件检查)。我想我发现了一个小问题。如果我们输入,比如说,x=143
和y=675
我们得到的输出是717
,但预期是818
。或者,如果我们输入x=985
和y=824
,我们得到的输出是710
,但预期是1809
。我看不到这些输出中的模式。我我得到了818。关于列表的顺序可能会有一些混乱。我假设最低有效位在列表的开头,所以143
将存储为3->4->1
。如果列表不是这样存储的,那么添加会变得相当慢,因为需要额外的迭代。尽管如此,您确实发现了一个bug(<10
应该是我添加了我的链表是如何生成的。此外,我没有667+677的示例。这些只是我断环的输出。输入都是666,预期输出为1332。