2

1561/1563 test cases passed

problem discription:

You are given two non-empty linked lists representing two non-negative integers. The most significant digit comes first and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself. link to problem: https://leetcode.com/problems/add-two-numbers-ii/

you dont need to provide me with code(would be helpful), just the answer why do I get wrong answer for next questions.

void insert_begging(struct ListNode **root,unsigned __int128 val){
    struct ListNode *new_node = malloc(sizeof(struct ListNode));
    new_node->val = val;
    if(*root == NULL){
        new_node->next = NULL;
        *root = new_node;
        return;
    }
    new_node->next = *root;
    *root = new_node;
}
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
    struct ListNode* result = NULL;
    struct ListNode* curr = l1;
    unsigned __int128  sum = 0;
    unsigned __int128 sum2 = 0;
    while(curr!=NULL){
        sum=sum*10+curr->val;
        curr=curr->next;
    }
    struct ListNode* curr2 = l2;
    while(curr2!= NULL){
        sum2=sum2*10+curr2->val;
        curr2=curr2->next;
    }
    unsigned __int128 rsum = sum+sum2;
    unsigned __int128  digit = 0;
    if(rsum == 0){
        struct ListNode* result = malloc(sizeof(struct ListNode));
        result->val = rsum;
        result->next = NULL;
        return result;
    }
    while (rsum > 0) {
        int digit = rsum % 10;
        insert_begging(&result, digit);
        rsum /= 10;
    }
    return result;
}

so I spent 1 hour trying to solve this problem, with no luck

this is the test i failed:

l1 = [2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,9]
l2 = [5,6,4,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,9,9,9,9]

result is supposed to be:

[8,0,7,4,8,6,4,8,6,4,8,6,4,8,6,4,8,6,4,8,6,4,8,6,4,8,6,4,8,6,4,8,6,4,8,6,4,8,6,4,8,6,4,8,6,4,8,6,4,8,6,4,8,6,4,8,7,2,4,3,8]

firstly I got int overflows even with unsigned long long type so I changed it to unsigned __int128 but i got this:

[1,7,0,4,9,1,2,5,7,9,2,0,1,8,3,3,6,8,2,6,4,9,7,6,4,3,9,5,8,5,1,6,4,5,3,5,7,9,8]
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Can you scope this down a *lot* to what you think the problem is? Why the pervasive use of `__int128`? What numerical ranges are you expecting? You're showing single digit numbers here. – tadman May 11 '23 at 19:39
  • @tadman , because sum and sum2 , aswell as result THAT WERE INTIGER cannot handle such big numbers as [5,6,4,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,2,4,3,9,9,9,9], so i tried to use long long with more storage space, turns out even long long cannot handle such big numbers ,aswell as unsigned long long so i got to googling data types bigger than long long – Jovan Dejanović May 11 '23 at 19:41
  • 5
    You haven't told us anything at all about the problem this code is trying to solve, and there's a whole lot missing. Consider explaining the problem and working on a [mcve]. – Retired Ninja May 11 '23 at 19:42
  • At least link to the Leetcode problem instead of an image of a failure report. The big allegedly big numbers might be avoidable with a good algorithm. *Add the two numbers and return the sum as a linked list.* If this is single-digit addition you can simply propagate a carry as you build the list. – Weather Vane May 11 '23 at 19:47
  • 3
    I don't think you'll solve this by aggregating into any integer supported by C – cafce25 May 11 '23 at 19:49
  • 10
    You're not supposed to convert the linked lists into C numbers. The whole point of using the linked list is that it can hold numbers bigger than any C integer datatype. You're supposed to add the elements of the linked lists directly, like the way you learned to do addition in grade school. You have to add each digit and then carry into the next digit. – Barmar May 11 '23 at 19:50
  • ... and indeed, the problem description says that the input lists may contain up to 100 decimal digits each, so you should expect test cases that exercise that limit. You need at least 333 bits to represent that as a binary integer, so even if the judge's C implementation provides (nonstandard) `__int128`, that's nowhere near large enough. – John Bollinger May 11 '23 at 20:36
  • It's worth noting here that trying random data types in the hopes that they contain the data you want isn't a productive problem solving method. The numerical range supported for any given type is documented. I'd *strongly* encourage you to look at the type specification before using it. The range may not be what you expect. – tadman May 11 '23 at 21:20

1 Answers1

5

Nobody will help us if we, beginners, will not help each other.:)

It is obvious that neither object of a fundamental integer type can hold such big numbers.

So the approach to build a number in an object of a fundamental integer type does not work.

A straightforward approach can look the following way as shown in the demonstration program below.

An alternative and more efficient approach is at first to build the result list using one of the passed lists in the reversed order and then add the second list and after that again to reverse the result list.

Here is the demonstration program that uses the straightforward approach.

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

struct ListNode
{
    unsigned int digit;
    struct ListNode *next;
};

void clear( struct ListNode **head )
{
    while (*head)
    {
        struct ListNode *current = *head;
        *head = ( *head )->next;
        free( current );
    }
}

void assign( struct ListNode **head, const unsigned int a[], size_t n )
{
    clear( head );

    while (n--)
    {
        *head = malloc( sizeof( struct ListNode ) );
        ( *head )->digit = *a++;
        ( *head )->next = NULL;
        head = &( *head )->next;
    }
}

FILE * display( const struct ListNode *head, FILE *fp )
{
    if (head == NULL)
    {
        fputc( '0', fp );
    }
    else
    {
        for (; head != NULL; head = head->next)
        {
            fputc( head->digit + '0', fp );
        }
    }

    return fp;
}

struct ListNode * addTwoNumbers( const struct ListNode *head1, const struct ListNode *head2 )
{
    const unsigned int Base = 10;

    struct ListNode *result = NULL;

    unsigned int carry = 0;

    const struct ListNode *last1 = NULL, *last2 = NULL;

    while (  last1 != head1 && last2 != head2 )
    {
        const struct ListNode *current1 = head1;

        while (current1->next != last1)
        {
            current1 = current1->next;
        }

        const struct ListNode *current2 = head2;

        while (current2->next != last2)
        {
            current2 = current2->next;
        }

        struct ListNode *tmp = malloc( sizeof( struct ListNode ) );
        tmp->digit = ( current1->digit + current2->digit + carry ) % Base;
        tmp->next = result;
        result = tmp;

        carry = ( current1->digit + current2->digit + carry ) / Base;

        last1 = current1;
        last2 = current2;
    }

    while (last1 != head1)
    {
        const struct ListNode *current1 = head1;

        while (current1->next != last1)
        {
            current1 = current1->next;
        }

        struct ListNode *tmp = malloc( sizeof( struct ListNode ) );
        tmp->digit = ( current1->digit + carry ) % Base;
        tmp->next = result;
        result = tmp;

        carry = ( current1->digit + carry ) / Base;

        last1 = current1;
    }

    while (last2 != head2)
    {
        const struct ListNode *current2 = head2;

        while (current2->next != last2)
        {
            current2 = current2->next;
        }

        struct ListNode *tmp = malloc( sizeof( struct ListNode ) );
        tmp->digit = ( current2->digit + carry ) % Base;
        tmp->next = result;
        result = tmp;

        carry = ( current2->digit + carry ) / Base;

        last2 = current2;
    }

    if (carry)
    {
        struct ListNode *tmp = malloc( sizeof( struct ListNode ) );
        tmp->digit = carry;
        tmp->next = result;
        result = tmp;
    }

    return result;
}

int main( void )
{
    unsigned int a1[] =
    {
        2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 9
    };
    const size_t N1 = sizeof( a1 ) / sizeof( *a1 );

    unsigned int a2[] =
    {
        5, 6, 4, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 2, 4, 3, 9, 9, 9, 9
    };
    const size_t N2 = sizeof( a2 ) / sizeof( *a2 );

    struct ListNode *head1 = NULL;
    struct ListNode *head2 = NULL;

    assign( &head1, a1, N1 );
    assign( &head2, a2, N2 );

    fputc( '\n', display( head1, stdout ) );
    fputc( '\n', display( head2, stdout ) );

    struct ListNode *result = addTwoNumbers( head1, head2 );

    fputc( '\n', display( result, stdout ) );

    clear( &result );
    clear( &head2 );
    clear( &head1 );
}

The program output is

2432432432432432432432432432432432432432432432432432432432439
5642432432432432432432432432432432432432432432432432432439999
8074864864864864864864864864864864864864864864864864864872438

If for example the first list contains the number

99999999999999999999

and the second list contains the number

1

then the result will be

100000000000000000000

The function addTwoNumbers can be made more readable if to introduce an additional function that will push a new node on the beginning of the list.

For example

struct ListNode * push_front( struct ListNode *head, unsigned int digit )
{
    struct ListNode *tmp = malloc( sizeof( struct ListNode ) );

    tmp->digit = digit;
    tmp->next  = head;

    return tmp;
}

struct ListNode * addTwoNumbers( const struct ListNode *head1, const struct ListNode *head2 )
{
    const unsigned int Base = 10;

    struct ListNode *result = NULL;

    unsigned int carry = 0;

    const struct ListNode *last1 = NULL, *last2 = NULL;

    while (  last1 != head1 && last2 != head2 )
    {
        const struct ListNode *current1 = head1;

        while (current1->next != last1)
        {
            current1 = current1->next;
        }

        const struct ListNode *current2 = head2;

        while (current2->next != last2)
        {
            current2 = current2->next;
        }

        result = push_front( result, ( current1->digit + current2->digit + carry ) % Base );

        carry = ( current1->digit + current2->digit + carry ) / Base;

        last1 = current1;
        last2 = current2;
    }

    while (last1 != head1)
    {
        const struct ListNode *current1 = head1;

        while (current1->next != last1)
        {
            current1 = current1->next;
        }

        result = push_front( result, ( current1->digit + carry ) % Base );

        carry = ( current1->digit + carry ) / Base;

        last1 = current1;
    }

    while (last2 != head2)
    {
        const struct ListNode *current2 = head2;

        while (current2->next != last2)
        {
            current2 = current2->next;
        }

        result = push_front( result, ( current2->digit + carry ) % Base );

        carry = ( current2->digit + carry ) / Base;

        last2 = current2;
    }

    if (carry)
    {
        result = push_front( result, carry );
    }

    return result;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335