由于我们学院(没错就是信通弟弟学院)辅导员的神操作(在我们没学数据结构的情况下要求我们刷力扣)
本人提前了自己的规划,由于自己自学了一点链表的知识,因此想试着找道题练习,于是选择了第二题(以后绝不轻易碰中等题。。。)
在经历了许多次增加,改bug之后,经过敏捷开发的洗礼,3天半的苦战,自己终于做出了这道题,
查看结果,发现并不是很理想,再次将自己的思路和改进的经验分享给大家,也提醒大家,少走弯路。
首先,代码奉上:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *Apply(int x){
struct ListNode * p,*q;
p = (struct ListNode *)malloc(sizeof(struct ListNode));
if (x < 10) {
p->val = x;
p->next = NULL;
return(p);
}
else {
p->val = x - 10;
q = (struct ListNode *)malloc(sizeof(struct ListNode));
q->val = 1;
q->next = NULL;
p->next = q;
return(p);
}
}
//初始化节点(建立表头)
struct ListNode *InitList(){
struct ListNode *head;
head = (struct ListNode *)malloc(sizeof(struct ListNode));
head->val = 0;
head->next = NULL;
return(head);
}
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
struct ListNode* head, *p, *q,*m,*n;
p = l1;
q = l2;
int flag = 0, temp = 0, shi = 0,flag1 = 1;
head = m = InitList();
while (p!=NULL && q!=NULL){
temp = (p->val) + (q->val);
if (flag != 1) {
shi = temp >= 10 ? 1 : 0;
temp = temp - 10 * (temp / 10);//个位
n = Apply(temp+flag);
m->next = n;
m = n; //尾插法建立新的链表
flag = shi;
p = p->next;
q = q->next;
}
else {
shi = temp >= 9 ? 1 : 0;
temp = temp + flag >= 10 ? temp+flag-10:temp+flag ;
n = Apply(temp );
m->next = n;
m = n; //尾插法建立新的链表
flag = shi;
p = p->next;
q = q->next;
}
}
while (p!=NULL)//l1未结束l2结束了
{
if (flag != 0) {
while (flag!=0 && p!=NULL)
{
if (p == NULL)//********************************
{
n = Apply(1);
m->next = n;
m = n;
}
else {
if (p->val > 8)
{
p->val = p->val + 1 - 10;
flag = 1;
n = Apply(p->val);
m->next = n;
m = n;
p = p->next;
}
else {
flag = 0;
n = Apply(1 + p->val);
m->next = n;
m = n;
p = p->next;
}
}
}
}
else {
n = Apply( p->val);
m->next = n;
m = n;
p = p->next;
}
if (p == NULL && q == NULL && m->val == 0) { //防止最后出现一个0
m->next = Apply(1);
p = NULL;
}
}
while (q!=NULL)//l2未结束l1结束了
{
if (flag != 0) {
while (flag != 0 && q != NULL)
{
if (q == NULL)//********************************
{
n = Apply(1);
m->next = n;
m = n;
}
else {
if (q->val > 8)
{
q->val = q->val + 1 - 10;
flag = 1;
n = Apply(q->val);
m->next = n;
m = n;
q = q->next;
}
else {
flag = 0;
n = Apply(1 + q->val);
m->next = n;
m = n;
q = q->next;
}
}
}
}
else {
n = Apply(q->val);
m->next = n;
m = n;
q = q->next;
}
if (p == NULL && q == NULL && m->val == 0) { //防止最后出现一个0
m->next = Apply(1);
q = NULL;
}
}
if (flag != 0) {
n = Apply(1);
m->next = n;
m = n;
flag = 0;
}
return(head->next);
}
自己的体会,零零散散的就
一.大家可以看到,自己为了将建立链表节点的步骤简化,写了两个函数InitList()和Apply(),分别建立头指针和申请新的节点。
二.由于自己只会含有头节点的链表,而题目的是不含有头节点的链表,因此我选择了按照含有头节点,用尾插法做,最后return的时候返回 head->next。
接下来说说自己的改进过程吧:
1.首先,自己解决的就是 342+456 这个问题,自己设置了变量:十位 shi,个位 temp,以及进位标志 flag;完成了第一个题;
2.紧接着,下一个例子 [1,8]+[0] 就难到我了,因为自己没有考虑到位数不同的情况,在查询其他人的答案之后,发现 由于自己while循环的中制条件是 (p!=NULL && q!=NULL) ,因此在退出循环后,如果(p!=NULL),则说明p指向的 l1链表还有剩余元素,也就是 l1没有结束,按照这个思路,自己又写了while(p!=NULL)和while(q!=NULL)的情况,解决了这一问题。
3.然后由于没有考虑到进位,在 [2]+[8,9,9,9] 这个例子又翻车了,自己于是加了个flag进位标志判定。
4.在主循环中依然有[2,1,8]+[8,2,9,9]这个例子翻车。。。。再改进
5.由于自己用的VS2017,显然力扣的编译器功能不那么强大,遇到空指针的应用还是报超时,再改。。。增加空指针判断。。。。
最终就成了这个又臭又长的。。。。
虽然很丑吧,但是思路清晰,我觉的还是很有必要看看别人的,他们怎么能用几十行就写完的啊啊啊啊啊啊(苦.orz)
最后说一句,C语言写的的确很长,不如py或者Java的行数少得多,但是我C的运行快啊,而且内存空间才9MB,很少的(同等8ms的Java用了44MB)