数学问题_大整数

1 Leetcode 2. 两数相加
1.1 题目描述
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
1.2 思路
一位一位的相加,不需要转化,因为如果很大的数会超出可以表示的范围
1.3 代码
/**

  • Definition for singly-linked list.
  • struct ListNode {
  • int val;
    
  • struct ListNode *next;
    
  • };
    */

struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
int temp = 0, sum = 0;
struct ListNode* resultList = NULL;
struct ListNode* node = NULL;
struct ListNode* tempNode = NULL;
resultList = (struct ListNode*)malloc(sizeof(struct ListNode));
resultList->next = NULL;
node = resultList;
//一位一位的相加,不需要转化,因为如果很大的数会超出可以表示的范围
while(!(l1 == NULL && l2 == NULL)) {
tempNode = (struct ListNode*)malloc(sizeof(struct ListNode));
tempNode->next = NULL;
if(l1 == NULL) {//如果l1已经为NULL,那这一位就取l2的
sum = l2->val;
l2 = l2->next;
}
else if(l2 == NULL) {//如果l2已经为NULL,那这一位就取l1的
sum = l1->val;
l1 = l1->next;
}
else {//这一位l1和l2相加
sum = l2->val + l1->val;
l1 = l1->next;
l2 = l2->next;
}
tempNode->val = (sum + temp) % 10;
temp = (sum + temp) / 10; //进位

    node->next = tempNode;
    node = tempNode;
}

//如果最高位进位了
if(temp != 0) {
    tempNode = (struct ListNode*)malloc(sizeof(struct ListNode));
    tempNode->next = NULL;
    tempNode->val = temp;
    node->next = tempNode;
    node = tempNode;
}
return resultList->next;

}
2 Leetcode 29. 两数相除
2.1 题目描述
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。

示例 1:
输入: dividend = 10, divisor = 3
输出: 3

示例 2:
输入: dividend = 7, divisor = -3
输出: -2

说明:
被除数和除数均为 32 位有符号整数。
除数不为 0。
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1。
2.2 思路
举例(下面的数都是二进制):
被除数1111,4bit;除数1,1bit。
(1)第一次,将除数左移3位,变成1000,也就是:
1111
1000
被除数1111大于1000,得到一个商1<<3,等于1000.然后被除数减去除数1000,剩余0111.此时result=1000.
(2)第二次,将除数左移2位,变成100,也就是:
0111
0100
被除数0111大于0100,得到一个商1<<2,等于100.然后被除数减去除数0100,剩余0011. 此时result=1100。
(3)第三次,将除数左移1位,变成10,也就是:
0011
0010
被除数0011大于0010,得到一个商1<<1,等于10.然后被除数减去除数0010,剩余0001. 此时result=1110。
(4)第四次,将除数左移0位,变成1,也就是:
0001
0001
被除数0001大于等于0001,得到一个商1<<0,等于1.然后被除数减去除数0001,剩余0000. 此时result=1111。结束。
(5)由于int型位数的限制,如果除数坐移可能会超出表示范围,因此改成被除数右移。

2.3 代码
int divide(int dividend, int divisor){
if(divisor == 0) {
return 0xffffffff;
}
int isNag = 0;
unsigned int x = 0, y = 0;
int i = 0;
unsigned int result = 0;
unsigned int one = 1;

if((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) {
    isNag = 1;
}

x = (dividend == INT_MIN) ? (unsigned int)INT_MIN : (unsigned int)abs(dividend);
y = (divisor == INT_MIN) ? (unsigned int)INT_MIN : (unsigned int)abs(divisor);

if(x < y) {
    return 0;
}
if(x == y) {
    return isNag ? -1 : 1;
}

for(i = 31; i >= 0; i--) {
    if((x >> i) >= y) {//移动被除数,如果移动后大于除数,放入结果
        result += (one << i);
        x -= (y << i);
    }
}

if(result == INT_MIN) {
    return isNag ? INT_MIN : INT_MAX;
}
return isNag ? -(int)result : (int)result;

}

发布了39 篇原创文章 · 获赞 1 · 访问量 856

猜你喜欢

转载自blog.csdn.net/weixin_42268479/article/details/103301036