JavaScript:遍历和反转单链表,并在SLL和数字之间进行转换
简介 今天,我在做一个关于Facebook JavaScript问题的模拟采访时,对如何处理单链接列表一窍不通。到目前为止,我的代码只是一个函数,它接受两个链表并返回另一个链表。我的计划如下 问题 给您两个任意长度的非空链表,表示两个非负整数。数字按相反顺序存储,每个节点包含一个数字。将这两个数字相加,并将其作为链表返回 您可以假设这两个数字不包含任何前导零,除了数字0本身 例如: 输入:(2->4->3)+(5->6->4)输出:7->0->8说明: 342+465=807 计划JavaScript:遍历和反转单链表,并在SLL和数字之间进行转换,javascript,Javascript,简介 今天,我在做一个关于Facebook JavaScript问题的模拟采访时,对如何处理单链接列表一窍不通。到目前为止,我的代码只是一个函数,它接受两个链表并返回另一个链表。我的计划如下 问题 给您两个任意长度的非空链表,表示两个非负整数。数字按相反顺序存储,每个节点包含一个数字。将这两个数字相加,并将其作为链表返回 您可以假设这两个数字不包含任何前导零,除了数字0本身 例如: 输入:(2->4->3)+(5->6->4)输出:7->0->8说明: 342+465=807 计划 按顺序将第一
您不必创建包含与链表相同数据的新数组。您可以在迭代这两个列表并在同一循环中创建结果列表的同时处理这两个列表。在进行此操作时,您必须注意从加法器中进行的进位 基本上你必须这样做:
let currNodeList1 = l1, currNodeList2 = l2; //assuming that l1 and l2 point to head of linked list
let resultListHead = null, currNodeResultList = null; //to store the result
let carry = 0, sum = 0;
while(currNodeList1 != null && currNodeList2 != null) {
sum = carry + currNodeList1.val + currNodeList2.val;
carry = Math.trunc(sum / 10);
sum = sum % 10;
let newListNode = new ListNode(sum);
if(currNodeResultList == null) {
resultListHead = newListNode;
} else {
currNodeResultList.next = newListNode;
}
currNodeResultList = newListNode;
currNodeList1 = currNodeList1.next;
currNodeList2 = currNodeList2.next;
}
if(currNodeList1 == null) { //other list is longer in length
while(currNodeList2 != null) {
// calculate sum as carry + currNodeList2.val
//same carry logic and keep appending to the end of the result list
}
}
if(currNodeList2 == null) { //other list is longer in length
while(currNodeList1 != null) {
//calculate sum as carry + currNodeList2.val
//same carry logic and keep appending to the end of the result list
}
}
显然,通过重构重复部分,您可以使代码更加模块化,但总体思路应该是这样的。您的计划似乎很复杂。只需编写足够的ADT,以提供从列表到int的转换,并添加int。反之亦然,因为这是创建数据的最简单方法
函数列表节点(val,下一个)
{
this.val=val;
this.next=next;
}
函数列表NodeFromint(val){
如果(val>10){
返回新的ListNode(val%10,listNodeFromInt(Math.trunc(val/10));
}
返回新的ListNode(val,null);
}
函数intFromNode(节点){
var-foo=0;
var-exp=0;
while(node){foo+=node.val*Math.pow(10,exp++);node=node.next}
返回foo
}
var a=listNodeFromInt(342);
控制台日志(a);
var b=listNodeFromInt(465);
控制台日志(b);
log(listNodeFrommit(intFromNode(a)+intFromNode(b))代码>处理链表时,可以轻松地采用递归方法。它倾向于保持代码简单。要将两个链接列表添加到一起,只需执行以下操作:
以节点为例
将这两个值相加
将该值保留在新节点中
移动到下一个节点并从步骤1开始重复
这是总纲。几乎没有需要跟踪的边缘情况
- 这两个数字的总和大于
10
——在这种情况下,您必须将多余的数字带到下一个求和运算中。因此,对于12
的总和,您只需保留2
并携带1
- 一个列表已用尽,但另一个列表仍具有值-仅将其视为具有值
0
-这不会影响结果。如果你尝试将1
和0
相加,你会得到1
,这是正确的选择
- 两个列表都已用尽,但有一个值已结转-同上。如果将
9
和3
的列表相加,则得到2
,下一次迭代将没有更多的列表,只有1
的结转
/*
*单链表的定义。
*/
函数列表节点(val)
{
this.val=val;
this.next=null;
}
/*预期的输入和输出。
*@param{ListNode}l1
*@param{ListNode}l2
*@return{ListNode}
*/
var addTwoNumbers=函数(l1,l2)
{
返回递归的ddlists(l1,l2,0);
};
/*
*递归地将两个列表相加,为每个数字生成一个新列表
*@param{ListNode}l1
*@param{ListNode}l2
*@param{number}结转
*@return{ListNode}
*/
函数递归DDLists(l1、l2、结转)
{
//您还可以放心地假设结转始终存在。
//但添加默认值是一种很好的做法
结转=结转| | 0;
//如果没有什么可补充的,我们就完了
if(l1==null&&l2==null&&carryover==0)返回null;
//在至少一个或两个列表用尽的情况下提供回退
l1=l1 | |新列表节点(0);
l2=l2 | |新列表节点(0);
//计算两个节点的总和,其中包含先前总和的任何潜在剩余值
var总和=l1.val+l2.val+结转;
//仅限单个数字
var newVal=总和%10
//要移动的量与下一个节点一起添加
var新结转=数学下限(总和/10);
//创建结果节点
var newList=newlistnode(newVal);
//递归地确定下一个节点是什么
newList.next=recursivelyAddLists(l1.next,l2.next,newCarryover);
//完成
返回新列表
}
//使用样本数据进行测试
var input1=新的列表节点(2);
input1.next=新列表节点(4);
input1.next.next=新列表节点(3);
var input2=新的列表节点(5);
input2.next=新列表节点(6);
input2.next.next=新列表节点(4);
log(debugPrintList(addTwoNumber(input1,input2)))
//用于递归地将列表内容收集到字符串的简单函数
函数debugPrintList(列表){
if(list.next==null)return list.val;
return list.val+“->”+debugPrintList(list.next);
}
执行计划步骤8的一种方法是使用
像这样:
function ListNode(val)
{
this.val = val;
this.next = null;
}
const array2List = function(list, nextValue)
{
let node = new ListNode(parseInt(nextValue));
node.next = list;
return node;
}
let numberArray = Array.from('807');
let list = numberArray.reduce(array2List, null);
console.log(list);
或者改变你的计划,做一些类似的事情:
const addTwoNumbers = function(l1, l2)
{
let sumList = new ListNode(0);
let node = sumList;
let carry = 0;
while (node)
{
let l1Value = (l1) ? parseInt(l1.val) : 0;
let l2Value = (l2) ? parseInt(l2.val) : 0;
let sum = carry + l1Value + l2Value;
node.val = sum % 10;
carry = (sum - node.val)/10;
if (l1) { l1 = l1.next }
if (l2) { l2 = l2.next }
node.next = (l1 || l2 || carry) ? new ListNode(0) : null;
node = node.next;
}
return sumList;
}
另一种方式
var addTwoNumbers = function(l1, l2) {
var List = new ListNode(0);
var head = List;
var sum = 0;
var carry = 0;
while(l1 || l2 || sum) {
if(l1) {
sum = sum + l1.val;
l1 = l1.next;
}
if(l2) {
sum = sum + l2.val;
l2 = l2.next;
}
if(sum >= 10) {
carry = 1;
sum = sum - 10;
}
head.next = new ListNode(sum)
head = head.next;
sum = carry;
carry = 0;
}
return List.next;
};
你必须在适当的地方做吗?或者你必须为结果列表分配新的空间??顺便说一句。你刚刚意识到你实际上并没有问一个问题-只是跳一下
var addTwoNumbers = function(l1, l2) {
var List = new ListNode(0);
var head = List;
var sum = 0;
var carry = 0;
while(l1 || l2 || sum) {
if(l1) {
sum = sum + l1.val;
l1 = l1.next;
}
if(l2) {
sum = sum + l2.val;
l2 = l2.next;
}
if(sum >= 10) {
carry = 1;
sum = sum - 10;
}
head.next = new ListNode(sum)
head = head.next;
sum = carry;
carry = 0;
}
return List.next;
};