ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int len1=1;//记录l1的长度
int len2=1;//记录l2的长度
ListNode* p=l1;
ListNode* q=l2;
while(p->next!=NULL)//获取l1的长度
{
len1++;
p=p->next;
}
while(q->next!=NULL)//获取l2的长度
{
len2++;
q=q->next;
}
if(len1>len2)//l1较长,在l2末尾补零
{
for(int i=1;i<=len1-len2;i++)
{
q->next=new ListNode(0);
q=q->next;
}
}
else//l2较长,在l1末尾补零
{
for(int i=1;i<=len2-len1;i++)
{
p->next=new ListNode(0);
p=p->next;
}
}
p=l1;
q=l2;
bool count=false;//记录进位
ListNode* l3=new ListNode(-1);//存放结果的链表
ListNode* w=l3;//l3的移动指针
int i=0;//记录相加结果
while(p!=NULL&&q!=NULL)
{
i=count+p->val+q->val;
w->next=new ListNode(i%10);
count=i>=10?true:false;
w=w->next;
p=p->next;
q=q->next;
}
if(count)//若最后还有进位
{
w->next=new ListNode(1);
w=w->next;
}
return l3->next;
}
};
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int a=0,c=0,b=0;
ListNode* p=l1;
ListNode* q=l2;
ListNode* ne=new ListNode(0,nullptr);
ListNode* w=ne;
while(p!=NULL&&q!=NULL)
{
c=(p->val+q->val)+b;
w->next=new ListNode(c%10);
b=c/10;
w=w->next;
p=p->next;
q=q->next;
}
while(p==NULL&&q!=NULL)
{
c=q->val+b;
w->next=new ListNode(c%10);
b=c/10;
w=w->next;
q=q->next;
}
while(q==NULL&&p!=NULL)
{
c=p->val+b;
w->next=new ListNode(c%10);
b=c/10;
w=w->next;
p=p->next;
}
if(b)
{w->next=new ListNode(1);
w=w->next;}
return ne->next;
}
}
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* partition(ListNode* head, int x) { ListNode* big = new ListNode(-1); ListNode* let = new ListNode(-1); ListNode *ret = let,*da = big; while(head != NULL){ if(head->val < x){ let->next = head; let = let->next; }else{ big->next = head; big = big->next; } head = head->next; } big->next = NULL; let->next = da->next; return ret->next; } };
解题步骤
建立快指针p和慢指针q,记n的初始值为in
快指针p先走,同时变量n自减
当n自减到0时,p已经比慢指针q先走了in步,此后两个指针开始同步移动
当p指向NULL时,遍历结束,循环体不再执行,故此时p刚好比q多走了in+1步,直接删除q的后一结点即可
特殊情况分析:需要删除头节点时,p最多只会比q多走n步,q并未移动,这与删除倒数第n-1个结点的情况是一样的,不过这种情况下n只会自减到0,直接返回头结点的下一个结点即可
/** * Definition for singly-linked list. * struct ListNode { * int val; * struct ListNode *next; * }; */ struct ListNode* removeNthFromEnd(struct ListNode* head, int n){ struct ListNode *p = head, *q = head; while(p){ if(n < 0){ q = q -> next; } n--; p = p -> next; } if(n == 0){ return head -> next; } q -> next = q -> next -> next; return head; }
方法一:迭代
假设存在链表 1 → 2 → 3 → Ø,我们想要把它改成 Ø ← 1 ← 2 ← 3。
在遍历列表时,将当前节点的 next 指针改为指向前一个元素。由于节点没有引用其上一个节点,因此必须事先存储其前一个元素。在更改引用之前,还需要另一个指针来存储下一个节点。不要忘记在最后返回新的头引用!
Java
public ListNode reverseList(ListNode head) { ListNode prev = null; ListNode curr = head; while (curr != null) { ListNode nextTemp = curr.next; curr.next = prev; prev = curr; curr = nextTemp; } return prev; }
复杂度分析
时间复杂度:O(n),假设 nn 是列表的长度,时间复杂度是 O(n)。
空间复杂度:O(1)。
方法二:递归
递归版本稍微复杂一些,其关键在于反向工作。假设列表的其余部分已经被反转,现在我该如何反转它前面的部分?
public ListNode reverseList(ListNode head) { if (head == null || head.next == null) return head; ListNode p = reverseList(head.next); head.next.next = head; head.next = null; return p; }
复杂度分析
时间复杂度:O(n),假设 nn 是列表的长度,那么时间复杂度为 O(n)。
空间复杂度:O(n),由于使用递归,将会使用隐式栈空间。递归深度可能会达到 nn 层。