导语
这是两道关于链表的习题,不算难题,但是有很多需要注意的小细节,在这里记录一下
Add Two Numbers
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
分析:题目翻译翻译过来就是:给你两个非空链表,表示两个非负整数。数字以相反的顺序存储,每个节点包含一个数字。 添加这两个数字并将其作为链接列表返回。
您可以假定这两个数字不包含任何前导零,除了数字0本身。
简单来说就是用两个链表来表示两个数字,链表中每个节点中存储一位数。需要做的就是按照加法规则,将链表中每个节点的数字相加,并将每一位存储在一个新链表中。
解决方法:按照从低位开始相加,设置进位标记,有进位的就进位。
需要注意的特殊情况:链表长度不一致;加到最高位时存在进位。整体逻辑比较简单,但是特别需要注意细节的处理。
下面是我解决这道题的方法:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2) {
struct ListNode *p,*per,*a;
int carry=0;//标记进位
p=(struct ListNode*)malloc(sizeof(struct ListNode));
int temp=l1->val+l2->val;
p->val=(temp)%10;
l1=l1->next;l2=l2->next;
p->next=NULL;//一个空链表
per=p;
if(temp>=10) carry=1;
while(l1&&l2){
/**
*两个链表都存在的情况下,按照逐位相加的方法进行运算
*注意每次相加后都要判断是否存在需要进位的情况
*/
int s=0;//逐位加法
s=l1->val;l1=l1->next;
s+=l2->val; l2=l2->next;
if(carry){
s+=1;
carry=0;
}
if(s>=10) carry=1;//保存进位
a=(struct ListNode*)malloc(sizeof(struct ListNode));
a->val=s%10;
a->next=per->next;
per->next=a;
per=a;
}
while(l1){
/**
*只剩下l1的情况下,将l1相加
*/
int s=0;
s=l1->val+carry;l1=l1->next;
if(s>=10)
carry=1;
else
carry=0;
a=(struct ListNode*)malloc(sizeof(struct ListNode));
a->val=s%10;
a->next=per->next;
per->next=a;
per=a;
}
while(l2){
int s=0;
s=l2->val+carry;l2=l2->next;
if(s>=10)
carry=1;
else
carry=0;
a=(struct ListNode*)malloc(sizeof(struct ListNode));
a->val=s%10;
a->next=per->next;
per->next=a;
per=a;
}
/**
*最后一定记得判断是否还有进位没有处理
*/
if(carry){
a=(struct ListNode*)malloc(sizeof(struct ListNode));
a->val=1;
a->next=per->next;
per->next=a;
per=a;
}
return p;
}
Remove Nth Node From End of List
Given a linked list, remove the nth node from the end of list and return its head.
For example,
Given linked list: 1->2->3->4->5, and n = 2.
After removing the second node from the end, the linked list becomes 1->2->3->5.
Note:
Given n will always be valid.
Try to do this in one pass.
给定一个链表,从列表的最后删除第n个节点并返回它的头部。
例如,
给定链表:1-> 2-> 3-> 4-> 5,并且n = 2。
从最后删除第二个结点后,链表将变为1-> 2-> 3-> 5。
分析:这道题目需要注意的一个地方是链表为空的情况下,返回一个空链表,另外的主要问题就是找到从后面数起的第n个结点。
下面是我的方法:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
struct ListNode *p=head,*per=head;
if(head == NULL || head->next == NULL)
return NULL;
for(int i = 0;i < n;i++)
per = per->next;
if(per == NULL)
return head->next;
while(per->next != NULL)
{
per = per->next;
p = p->next;
}
p->next = p->next->next;
return head;
}
思路是:因为是要找从后面数起的第n位,所以用了一个per来辅助寻找第n个结点,首先让per移位到从头结点起的第n+1位,然后让per结点移动到尾结点的位置,同时P从头结点开始移动,当per移动到尾结点是,p刚好移动到要删除位置的前一位。然后就是很简单的删除再返回链表就可以了