【力扣】2、两数相加

力扣(LeetCode)刷题

【力扣】1、两数之和
【力扣】2、两数相加



前言

    最近疫情又开始严重了起来,宅在家里太无聊了,闲着也是闲着,刷刷力扣玩。由于是练习算法,所以我更倾向于用C语言来实现,我对C语言的用法还停留在大学,如果有哪里写的不对的地方也欢迎各位小伙伴提出

在这里插入图片描述


一、题目

    码云
    来源:力扣(LeetCode)
    先来看下题目

    给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头

示例 1:

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]
示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

二、题解

    这个题目在力扣上翻了几下,好像没有多个解法,这里就列出我做题过程中的两种解法吧,不过有一种解法拿去运行溢出了,也不太算 (╥╯^╰╥),这边也列举下吧

    在做题前边先准备下一个链表,先定义一个list.h头文件,代码如下:

#ifndef ADD_TWO_NUMBERS_LIST_H
#define ADD_TWO_NUMBERS_LIST_H
typedef struct node {
    int num;
    struct node *next;
    struct node *prev;
} Node;
typedef struct list {
    int size;
    Node *header;
    Node *tail;

    int (*add)(struct list *list, int num);

    void (*clear)(struct list *list);

    Node *(*get)(struct list *list, int index);

    int (*length)(struct list *list);
} List;

int add(List *list, int num);

void clear(List *list);

Node *get(List *list, int index);

int length(List *list);

void printList(List *list);

List *create();

#endif

在定义一个list.c具体实现,代码如下:

#include <stdlib.h>
#include <stdio.h>
#include "list.h"

List *create() {
    List *list = (List *) malloc(sizeof(List));
    list->header = NULL;
    list->tail = NULL;
    list->length = length;
    list->add = add;
    list->clear = clear;
    list->get = get;
    list->size = 0;
    return list;
}

int add(List *list, int num) {
    if (list != NULL) {
        Node *newNode = (Node *) malloc(sizeof(Node));
        newNode->num = num;
        newNode->next = NULL;
        if (list->header == NULL) {
            list->header = newNode;
            list->tail = newNode;
            newNode->prev = NULL;
            list->size = 1;
        } else {
            Node *temp = list->tail;
            newNode->prev = temp;
            temp->next = newNode;
            list->tail = newNode;
            list->size++;
        }
        return 1;
    }
    return 0;
}

void clear(List *list) {
    if (list != NULL) {
        Node *node = list->header;
        Node *temp = node;
        while (node != NULL) {
            temp = node->next;
            free(node);
            node = temp;
        }
        node = NULL;
        temp = NULL;
        free(list);
        list = NULL;
    }
}

int length(List *list) {
    if (list != NULL) {
        return list->size;
    }
    return -1;
}

Node *get(List *list, int index) {
    if (list != NULL) {
        if (index < list->size && index >= 0) {
            Node *temp;
            /**
             * 下标在链表右侧,从尾指针开始查找
             */
            if (index > (list->size / 2)) {
                temp = list->tail;
                for (int i = 0; i < list->size - index - 1; ++i) {
                    temp = temp->prev;
                }
            } else {
                /**
                 * 下标在链表左侧,从头指针开始查找
                 */
                temp = list->header;
                for (int i = 0; i < index; i++) {
                    temp = temp->next;
                }
            }
            return temp;
        }
    }
    return NULL;
}

void printList(List *list) {
    if (list != NULL && list->size != 0) {
        printf("list:");
        for (int i = 0; i < list->length(list) - 1; ++i) {
            printf("%d -> ", list->get(list, i)->num);
        }
        printf("%d\n", list->get(list, list->size - 1)->num);
    } else {
        printf("empty list\n");
    }
}

    定义好链表之后,再来看下解法,注:这里的链表结构和力扣上的不太一样,放上去执行的话需要转换一下才行。如下:

1.转换数字相加

    对于这道题目,其实原先我想法是,转成数字进行相加,在转换成链表的,在自己机子上运行成功后,满心欢喜的拿到力扣上执行,结果。。计算量太大溢出了,所以这个解法算是失败的解法,这里一并放上来吧

    本地机子上的代码,如下:

#include <stdio.h>
#include <stdlib.h>
#include "list.h"
#include <math.h>

__int128_t getRealNum(Node *node, int index) {
    if (node != NULL) {
        __int128_t powNum = 1;
        for (int i = 1; i <= index; i++) {
            powNum *= 10;
        }
        return node->num * powNum;
    }
    return 0;
}


List *addTwoNumbers(Node *l1, Node *l2) {
  __int128_t sum = 0;
    Node *t1 = l1;
    Node *t2 = l2;
    int index = 0;
    while (t1 != NULL || t2 != NULL) {

        sum += getRealNum(t1, index);
        sum += getRealNum(t2, index);
        index++;
        if (t1 != NULL) {
            t1 = t1->next;
        }
        if (t2 != NULL) {
            t2 = t2->next;
        }
    }
    List *list = create();
    do {
        list->add(list, sum % 10);
        sum /= 10;
    } while (sum != 0);

    return list;

    力扣上的代码,如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2);

__int128_t getRealNum(struct ListNode*node, int index);

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
 __int128_t  sum = 0;
   struct ListNode *t1 = l1;
   struct ListNode *t2 = l2;
    int index = 0;
    while (t1 != NULL || t2 != NULL) {
        sum += getRealNum(t1, index);
        sum += getRealNum(t2, index);
        index++;
        if (t1 != NULL) {
            t1 = t1->next;
        }
        if (t2 != NULL) {
            t2 = t2->next;
        }
    }
    struct ListNode* list = (struct ListNode*)malloc(sizeof(struct ListNode));
    list->next = NULL;
    struct ListNode* temp= list;
    while (true) {
        temp->val =  sum % 10;
        sum /= 10;
        if(sum ==0){
            break;
        }
        struct ListNode* next = (struct ListNode*)malloc(sizeof(struct ListNode));
        next->next=NULL;
        temp->next=next;
        temp = temp->next;
    }
    return list;
}

__int128_t  getRealNum(struct ListNode *node, int index) {
    if (node != NULL) {
        __int128_t powNum = 1;
        for (int i = 1; i <= index; i++) {
            powNum *= 10;
        }
        return node->val * powNum;
    }
    return 0;
}

执行到这里,溢出了,位数实在太大了,如下:
在这里插入图片描述

在这里插入图片描述
    看到这里我就放弃,再继续往下计算,就算能通过,耗时也会很长的

2.同一位置相加

    这个解法就是官方的解法了,就是把链表的同一位置的数字相加即可,这里需要注意的有两点:一是长度不同的链表,短的需要补0,二是需要注意下进位

    本地机子上的代码,如下:

int addNum(Node *n1, Node *n2, int *sum, int carry) {
    int num1 = 0;
    int num2 = 0;
    if (n1 != NULL) {
        num1 = n1->num;
    }
    if (n2 != NULL) {
        num2 = n2->num;
    }

    *sum = num1 + num2 + carry;
    return *sum >= 10 ? 1 : 0;
}

List *addTwoNumbers(Node *l1, Node *l2) {
    int *sum = (int *) malloc(sizeof(int));
    Node *t1 = l1;
    Node *t2 = l2;
    int carry = 0;
    List *list = create();
    while (t1 != NULL || t2 != NULL) {
        carry = addNum(t1, t2, sum, carry);
        list->add(list, *sum % 10);
        if (t1 != NULL) {
            t1 = t1->next;
        }
        if (t2 != NULL) {
            t2 = t2->next;
        }
    }
    if (carry == 1) {
        list->add(list, 1);
    }
    free(sum);
    sum = NULL;

    return list;
}

    力扣上的代码,如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2);

int addNum(struct ListNode *n1, struct ListNode *n2, int *sum, int carry) {
    int num1 = 0;
    int num2 = 0;
    if (n1 != NULL) {
        num1 = n1->val;
    }
    if (n2 != NULL) {
        num2 = n2->val;
    }

    *sum = num1 + num2 + carry;
    return *sum >= 10 ? 1 : 0;
}

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
  int *sum = (int *) malloc(sizeof(int));
   struct ListNode *t1 = l1;
   struct ListNode *t2 = l2;
   int carry = 0;
    struct ListNode* list = (struct ListNode*)malloc(sizeof(struct ListNode));
    list->val = 0;
    list->next = NULL;
    struct ListNode* temp= list;
    while (t1 != NULL || t2 != NULL) {
        carry = addNum(t1, t2, sum, carry);
        temp->val =  *sum % 10;
        if((t1!=NULL&&t1->next!=NULL)||(t2!=NULL&&t2->next!=NULL)){
            struct ListNode* next = (struct ListNode*)malloc(sizeof(struct ListNode));
            next->next=NULL;
            temp->next=next;
            temp = temp->next;
        }
        if (t1 != NULL) {
            t1 = t1->next;
        }
        if (t2 != NULL) {
            t2 = t2->next;
        }
    }
    if (carry == 1) {
        struct ListNode* next = (struct ListNode*)malloc(sizeof(struct ListNode));
        next->next=NULL;
        temp->next=next;
        temp = temp->next;
        temp->val = 1;
    }
    free(sum);
    sum = NULL;
    return list;
}

    力扣评论的解法大体差不多,这边就不在一一列举了
在这里插入图片描述


总结

    以上就是我所知道的两数相加解法,如果还有其他解法或者错误的地方欢迎各位小伙伴提出

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

穷儒公羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值